Skip to content

Commit d19b7c1

Browse files
SC llvm teamSC llvm team
authored andcommitted
Merged main:57907c1a96e8 into amd-gfx:4746962a0740
Local branch amd-gfx 4746962 Merged main:7907292daa78 into amd-gfx:006dcb723c69 Remote branch main 57907c1 [clang-tidy] ignore `[[clang::lifetimebound]]` param in return-const-ref-from-parameter (llvm#118315)
2 parents 4746962 + 57907c1 commit d19b7c1

File tree

158 files changed

+6089
-1364
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

158 files changed

+6089
-1364
lines changed

.github/CODEOWNERS

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@
77
# to receive an approval from a "code owner" in particular -- any LLVM project
88
# member can approve pull requests.
99
#
10-
# Note that GitHub's concept of "code owner" is independent from LLVM's own
11-
# "code owner" concept, they merely happen to share terminology. See
12-
# https://llvm.org/docs/DeveloperPolicy.html#code-owners, as well as the
13-
# CODE_OWNERS.txt files in the respective subproject directories.
10+
# This is independent of LLVM's own "maintainer" concept.
11+
# See https://llvm.org/docs/DeveloperPolicy.html#maintainers as well as the
12+
# Maintainers.* files in the the respective subproject directories.
1413

1514
/libcxx/ @llvm/reviewers-libcxx
1615
/libcxxabi/ @llvm/reviewers-libcxxabi

clang-tools-extra/clang-tidy/bugprone/ReturnConstRefFromParameterCheck.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "ReturnConstRefFromParameterCheck.h"
10+
#include "clang/AST/Attrs.inc"
1011
#include "clang/AST/Expr.h"
1112
#include "clang/ASTMatchers/ASTMatchFinder.h"
1213
#include "clang/ASTMatchers/ASTMatchers.h"
@@ -15,14 +16,23 @@ using namespace clang::ast_matchers;
1516

1617
namespace clang::tidy::bugprone {
1718

19+
namespace {
20+
21+
AST_MATCHER(ParmVarDecl, hasLifetimeBoundAttr) {
22+
return Node.hasAttr<LifetimeBoundAttr>();
23+
}
24+
25+
} // namespace
26+
1827
void ReturnConstRefFromParameterCheck::registerMatchers(MatchFinder *Finder) {
1928
const auto DRef = ignoringParens(
2029
declRefExpr(
2130
to(parmVarDecl(hasType(hasCanonicalType(
2231
qualType(lValueReferenceType(pointee(
2332
qualType(isConstQualified()))))
2433
.bind("type"))),
25-
hasDeclContext(functionDecl().bind("owner")))
34+
hasDeclContext(functionDecl().bind("owner")),
35+
unless(hasLifetimeBoundAttr()))
2636
.bind("param")))
2737
.bind("dref"));
2838
const auto Func =

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ Changes in existing checks
184184
<clang-tidy/checks/bugprone/return-const-ref-from-parameter>` check to
185185
diagnose potential dangling references when returning a ``const &`` parameter
186186
by using the conditional operator ``cond ? var1 : var2`` and no longer giving
187-
false positives for functions which contain lambda.
187+
false positives for functions which contain lambda and ignore parameters
188+
with ``[[clang::lifetimebound]]`` attribute.
188189

189190
- Improved :doc:`bugprone-sizeof-expression
190191
<clang-tidy/checks/bugprone/sizeof-expression>` check to find suspicious

clang-tools-extra/docs/clang-tidy/checks/bugprone/return-const-ref-from-parameter.rst

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,6 @@ after the call. When the function returns such a parameter also as constant refe
1212
then the returned reference can be used after the object it refers to has been
1313
destroyed.
1414

15-
This issue can be resolved by declaring an overload of the problematic function
16-
where the ``const &`` parameter is instead declared as ``&&``. The developer has
17-
to ensure that the implementation of that function does not produce a
18-
use-after-free, the exact error that this check is warning against.
19-
Marking such an ``&&`` overload as ``deleted``, will silence the warning as
20-
well. In the case of different ``const &`` parameters being returned depending
21-
on the control flow of the function, an overload where all problematic
22-
``const &`` parameters have been declared as ``&&`` will resolve the issue.
23-
2415
Example
2516
-------
2617

@@ -38,3 +29,23 @@ Example
3829

3930
const S& s = fn(S{1});
4031
s.v; // use after free
32+
33+
34+
This issue can be resolved by declaring an overload of the problematic function
35+
where the ``const &`` parameter is instead declared as ``&&``. The developer has
36+
to ensure that the implementation of that function does not produce a
37+
use-after-free, the exact error that this check is warning against.
38+
Marking such an ``&&`` overload as ``deleted``, will silence the warning as
39+
well. In the case of different ``const &`` parameters being returned depending
40+
on the control flow of the function, an overload where all problematic
41+
``const &`` parameters have been declared as ``&&`` will resolve the issue.
42+
43+
This issue can also be resolved by adding ``[[clang::lifetimebound]]``. Clang
44+
enable ``-Wdangling`` warning by default which can detect mis-uses of the
45+
annotated function. See `lifetimebound attribute <https://clang.llvm.org/docs/AttributeReference.html#id11>`_
46+
for details.
47+
48+
.. code-block:: c++
49+
50+
const int &f(const int &a [[clang::lifetimebound]]) { return a; } // no warning
51+
const int &v = f(1); // warning: temporary bound to local reference 'v' will be destroyed at the end of the full-expression [-Wdangling]

clang-tools-extra/test/clang-tidy/checkers/bugprone/return-const-ref-from-parameter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,9 @@ int const &overload_params_difference3(int p1, int const &a, int p2) { return a;
197197
int const &overload_params_difference3(int p1, long &&a, int p2);
198198

199199
} // namespace overload
200+
201+
namespace gh117696 {
202+
namespace use_lifetime_bound_attr {
203+
int const &f(int const &a [[clang::lifetimebound]]) { return a; }
204+
} // namespace use_lifetime_bound_attr
205+
} // namespace gh117696

clang/docs/LanguageExtensions.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,7 @@ elementwise to the input.
648648
Unless specified otherwise operation(±0) = ±0 and operation(±infinity) = ±infinity
649649

650650
The integer elementwise intrinsics, including ``__builtin_elementwise_popcount``,
651-
can be called in a ``constexpr`` context.
651+
``__builtin_elementwise_bitreverse``, can be called in a ``constexpr`` context.
652652

653653
============================================== ====================================================================== =========================================
654654
Name Operation Supported element types

clang/docs/ReleaseNotes.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,9 @@ Resolutions to C++ Defect Reports
310310
by default.
311311
(`CWG2521: User-defined literals and reserved identifiers <https://cplusplus.github.io/CWG/issues/2521.html>`_).
312312

313+
- Fix name lookup for a dependent base class that is the current instantiation.
314+
(`CWG591: When a dependent base class is the current instantiation <https://cplusplus.github.io/CWG/issues/591.html>`_).
315+
313316
C Language Changes
314317
------------------
315318

@@ -404,6 +407,7 @@ Non-comprehensive list of changes in this release
404407
- ``__builtin_reduce_and`` function can now be used in constant expressions.
405408
- ``__builtin_reduce_or`` and ``__builtin_reduce_xor`` functions can now be used in constant expressions.
406409
- ``__builtin_elementwise_popcount`` function can now be used in constant expressions.
410+
- ``__builtin_elementwise_bitreverse`` function can now be used in constant expressions.
407411

408412
New Compiler Flags
409413
------------------
@@ -763,6 +767,8 @@ Bug Fixes to C++ Support
763767
- Fixed an assertion failure caused by using ``consteval`` in condition in consumed analyses. (#GH117385)
764768
- Fix a crash caused by incorrect argument position in merging deduced template arguments. (#GH113659)
765769
- Fixed an assertion failure caused by mangled names with invalid identifiers. (#GH112205)
770+
- Fixed an incorrect lambda scope of generic lambdas that caused Clang to crash when computing potential lambda
771+
captures at the end of a full expression. (#GH115931)
766772

767773
Bug Fixes to AST Handling
768774
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/Basic/Builtins.td

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1270,7 +1270,7 @@ def ElementwiseATan2 : Builtin {
12701270

12711271
def ElementwiseBitreverse : Builtin {
12721272
let Spellings = ["__builtin_elementwise_bitreverse"];
1273-
let Attributes = [NoThrow, Const, CustomTypeChecking];
1273+
let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr];
12741274
let Prototype = "void(...)";
12751275
}
12761276

@@ -4930,6 +4930,12 @@ def HLSLClip: LangBuiltin<"HLSL_LANG"> {
49304930
let Prototype = "void(...)";
49314931
}
49324932

4933+
def HLSLGroupMemoryBarrierWithGroupSync: LangBuiltin<"HLSL_LANG"> {
4934+
let Spellings = ["__builtin_hlsl_group_memory_barrier_with_group_sync"];
4935+
let Attributes = [NoThrow, Const];
4936+
let Prototype = "void()";
4937+
}
4938+
49334939
// Builtins for XRay.
49344940
def XRayCustomEvent : Builtin {
49354941
let Spellings = ["__xray_customevent"];

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1000,7 +1000,10 @@ bool Compiler<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) {
10001000
if (!visitAsPointer(RHS, *RT) || !visitAsPointer(LHS, *LT))
10011001
return false;
10021002

1003-
return this->emitSubPtr(classifyPrim(E->getType()), E);
1003+
PrimType IntT = classifyPrim(E->getType());
1004+
if (!this->emitSubPtr(IntT, E))
1005+
return false;
1006+
return DiscardResult ? this->emitPop(IntT, E) : true;
10041007
}
10051008

10061009
PrimType OffsetType;
@@ -5911,6 +5914,9 @@ bool Compiler<Emitter>::VisitVectorUnaryOperator(const UnaryOperator *E) {
59115914
return this->discard(SubExpr);
59125915

59135916
auto UnaryOp = E->getOpcode();
5917+
if (UnaryOp == UO_Extension)
5918+
return this->delegate(SubExpr);
5919+
59145920
if (UnaryOp != UO_Plus && UnaryOp != UO_Minus && UnaryOp != UO_LNot &&
59155921
UnaryOp != UO_Not && UnaryOp != UO_AddrOf)
59165922
return this->emitInvalid(E);

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,17 @@ static bool retPrimValue(InterpState &S, CodePtr OpPC,
148148
#undef RET_CASE
149149
}
150150

151+
static void diagnoseNonConstexprBuiltin(InterpState &S, CodePtr OpPC,
152+
unsigned ID) {
153+
auto Loc = S.Current->getSource(OpPC);
154+
if (S.getLangOpts().CPlusPlus11)
155+
S.CCEDiag(Loc, diag::note_constexpr_invalid_function)
156+
<< /*isConstexpr=*/0 << /*isConstructor=*/0
157+
<< ("'" + S.getASTContext().BuiltinInfo.getName(ID) + "'").str();
158+
else
159+
S.CCEDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
160+
}
161+
151162
static bool interp__builtin_is_constant_evaluated(InterpState &S, CodePtr OpPC,
152163
const InterpFrame *Frame,
153164
const CallExpr *Call) {
@@ -181,10 +192,14 @@ static bool interp__builtin_is_constant_evaluated(InterpState &S, CodePtr OpPC,
181192

182193
static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
183194
const InterpFrame *Frame,
184-
const CallExpr *Call) {
195+
const Function *Func, const CallExpr *Call) {
196+
unsigned ID = Func->getBuiltinID();
185197
const Pointer &A = getParam<Pointer>(Frame, 0);
186198
const Pointer &B = getParam<Pointer>(Frame, 1);
187199

200+
if (ID == Builtin::BIstrcmp)
201+
diagnoseNonConstexprBuiltin(S, OpPC, ID);
202+
188203
if (!CheckLive(S, OpPC, A, AK_Read) || !CheckLive(S, OpPC, B, AK_Read))
189204
return false;
190205

@@ -224,9 +239,13 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
224239

225240
static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,
226241
const InterpFrame *Frame,
227-
const CallExpr *Call) {
242+
const Function *Func, const CallExpr *Call) {
243+
unsigned ID = Func->getBuiltinID();
228244
const Pointer &StrPtr = getParam<Pointer>(Frame, 0);
229245

246+
if (ID == Builtin::BIstrlen)
247+
diagnoseNonConstexprBuiltin(S, OpPC, ID);
248+
230249
if (!CheckArray(S, OpPC, StrPtr))
231250
return false;
232251

@@ -1772,6 +1791,7 @@ static bool interp__builtin_elementwise_popcount(InterpState &S, CodePtr OpPC,
17721791
INT_TYPE_SWITCH_NO_BOOL(ElemT, {
17731792
Dst.atIndex(I).deref<T>() =
17741793
T::from(Arg.atIndex(I).deref<T>().toAPSInt().popcount());
1794+
Dst.atIndex(I).initialize();
17751795
});
17761796
}
17771797

@@ -1781,21 +1801,36 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
17811801
const InterpFrame *Frame,
17821802
const Function *Func, const CallExpr *Call) {
17831803
assert(Call->getNumArgs() == 3);
1804+
unsigned ID = Func->getBuiltinID();
17841805
Pointer DestPtr = getParam<Pointer>(Frame, 0);
17851806
const Pointer &SrcPtr = getParam<Pointer>(Frame, 1);
17861807
const APSInt &Size =
17871808
peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2)));
17881809
assert(!Size.isSigned() && "memcpy and friends take an unsigned size");
17891810

1790-
if (DestPtr.isDummy() || SrcPtr.isDummy())
1791-
return false;
1811+
if (ID == Builtin::BImemcpy || ID == Builtin::BImemmove)
1812+
diagnoseNonConstexprBuiltin(S, OpPC, ID);
1813+
1814+
bool Move = (ID == Builtin::BI__builtin_memmove || ID == Builtin::BImemmove);
17921815

17931816
// If the size is zero, we treat this as always being a valid no-op.
17941817
if (Size.isZero()) {
17951818
S.Stk.push<Pointer>(DestPtr);
17961819
return true;
17971820
}
17981821

1822+
if (SrcPtr.isZero() || DestPtr.isZero()) {
1823+
Pointer DiagPtr = (SrcPtr.isZero() ? SrcPtr : DestPtr);
1824+
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_null)
1825+
<< /*IsMove=*/Move << /*IsWchar=*/false << !SrcPtr.isZero()
1826+
<< DiagPtr.toDiagnosticString(S.getASTContext());
1827+
return false;
1828+
}
1829+
1830+
// As a last resort, reject dummy pointers.
1831+
if (DestPtr.isDummy() || SrcPtr.isDummy())
1832+
return false;
1833+
17991834
if (!DoBitCastPtr(S, OpPC, SrcPtr, DestPtr))
18001835
return false;
18011836

@@ -1818,11 +1853,13 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
18181853
case Builtin::BI__assume:
18191854
break;
18201855
case Builtin::BI__builtin_strcmp:
1821-
if (!interp__builtin_strcmp(S, OpPC, Frame, Call))
1856+
case Builtin::BIstrcmp:
1857+
if (!interp__builtin_strcmp(S, OpPC, Frame, F, Call))
18221858
return false;
18231859
break;
18241860
case Builtin::BI__builtin_strlen:
1825-
if (!interp__builtin_strlen(S, OpPC, Frame, Call))
1861+
case Builtin::BIstrlen:
1862+
if (!interp__builtin_strlen(S, OpPC, Frame, F, Call))
18261863
return false;
18271864
break;
18281865
case Builtin::BI__builtin_nan:
@@ -2263,6 +2300,9 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
22632300
break;
22642301

22652302
case Builtin::BI__builtin_memcpy:
2303+
case Builtin::BImemcpy:
2304+
case Builtin::BI__builtin_memmove:
2305+
case Builtin::BImemmove:
22662306
if (!interp__builtin_memcpy(S, OpPC, Frame, F, Call))
22672307
return false;
22682308
break;

clang/lib/AST/CXXInheritance.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches) const {
134134
return false;
135135

136136
CXXRecordDecl *Base =
137-
cast_or_null<CXXRecordDecl>(Ty->getDecl()->getDefinition());
137+
cast_if_present<CXXRecordDecl>(Ty->getDecl()->getDefinition());
138138
if (!Base ||
139139
(Base->isDependentContext() &&
140140
!Base->isCurrentInstantiation(Record))) {
@@ -169,13 +169,21 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
169169
QualType BaseType =
170170
Context.getCanonicalType(BaseSpec.getType()).getUnqualifiedType();
171171

172+
bool isCurrentInstantiation = isa<InjectedClassNameType>(BaseType);
173+
if (!isCurrentInstantiation) {
174+
if (auto *BaseRecord = cast_if_present<CXXRecordDecl>(
175+
BaseSpec.getType()->getAsRecordDecl()))
176+
isCurrentInstantiation = BaseRecord->isDependentContext() &&
177+
BaseRecord->isCurrentInstantiation(Record);
178+
}
172179
// C++ [temp.dep]p3:
173180
// In the definition of a class template or a member of a class template,
174181
// if a base class of the class template depends on a template-parameter,
175182
// the base class scope is not examined during unqualified name lookup
176183
// either at the point of definition of the class template or member or
177184
// during an instantiation of the class tem- plate or member.
178-
if (!LookupInDependent && BaseType->isDependentType())
185+
if (!LookupInDependent &&
186+
(BaseType->isDependentType() && !isCurrentInstantiation))
179187
continue;
180188

181189
// Determine whether we need to visit this base class at all,
@@ -243,9 +251,8 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
243251
return FoundPath;
244252
}
245253
} else if (VisitBase) {
246-
CXXRecordDecl *BaseRecord;
254+
CXXRecordDecl *BaseRecord = nullptr;
247255
if (LookupInDependent) {
248-
BaseRecord = nullptr;
249256
const TemplateSpecializationType *TST =
250257
BaseSpec.getType()->getAs<TemplateSpecializationType>();
251258
if (!TST) {
@@ -264,8 +271,7 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
264271
BaseRecord = nullptr;
265272
}
266273
} else {
267-
BaseRecord = cast<CXXRecordDecl>(
268-
BaseSpec.getType()->castAs<RecordType>()->getDecl());
274+
BaseRecord = cast<CXXRecordDecl>(BaseSpec.getType()->getAsRecordDecl());
269275
}
270276
if (BaseRecord &&
271277
lookupInBases(Context, BaseRecord, BaseMatches, LookupInDependent)) {

clang/lib/AST/DeclCXX.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2602,8 +2602,6 @@ bool CXXMethodDecl::isMoveAssignmentOperator() const {
26022602

26032603
void CXXMethodDecl::addOverriddenMethod(const CXXMethodDecl *MD) {
26042604
assert(MD->isCanonicalDecl() && "Method is not canonical!");
2605-
assert(!MD->getParent()->isDependentContext() &&
2606-
"Can't add an overridden method to a class template!");
26072605
assert(MD->isVirtual() && "Method is not virtual!");
26082606

26092607
getASTContext().addOverriddenMethod(this, MD);

0 commit comments

Comments
 (0)