Fznamznon created this revision. Herald added a project: All. Fznamznon requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
Attribute arguments are always compile-time expressions that need to be evaluated. So, it is not necessary to treat attribute use as ODR use. Treatment of use from attribute aruments as ODR use had a side effect in incorrect processing of attributes applied to nested lambdas. That happened because ODR use from attribute applied to a lambda forced Sema to check if used variable is correctly captured. For the following example: const int I = 10; auto OL = [=] () { auto IL = [&](int K) __attribute__((enable_if(I > K, "..."))) {}; }; when capture-checking function was validating use of either variable `I` or parameter `K` the error "variable cannot be implicitly captured in a lambda with no capture-default specified" was emitted. That happened due to the following order of actions during lambda parsing: first, an empty lambda scope is pushed to `FunctionScopes` collection in `Sema`, then the attributes on lambdas are handled, and only after that the info about inner lambda capturing style is saved to a corresponding lambda scope. So, at the point when attributes on inner lambda are handled, capture-checking function thinks that it is already inside the inner lambda and it doesn't have capturing style, so the error was emitted. This patch makes this error go away. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D122494 Files: clang/include/clang/Sema/Sema.h clang/lib/Parse/ParseDecl.cpp clang/lib/Sema/SemaExpr.cpp clang/test/SemaCXX/attr-on-lambda.cpp
Index: clang/test/SemaCXX/attr-on-lambda.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/attr-on-lambda.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// expected-no-diagnostics + +constexpr int get(const int A) { return A; } + +struct MyStruct { + const int Member = get(1); +}; + +void foo() { + + const int I = 10; + constexpr MyStruct S = {1}; + auto Outer = [=]() { + auto Inner1 = [&](int k) __attribute__((enable_if(I > k, "nope"))){}; + + auto Inner2 = [=]() __attribute__((enable_if(S.Member, "nope"))){}; + + auto Inner3 = [&](int k) __attribute__((enable_if(k > get(I), "nope"))){}; + }; +} + Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -2031,6 +2031,8 @@ !isCapturingReferenceToHostVarInCUDADeviceLambda(*this, VD) && VD->isUsableInConstantExpressions(Context)) return NOUR_Constant; + if (ExprEvalContexts.back().InAttributeArgsContext) + return NOUR_Constant; } // All remaining non-variable cases constitute an odr-use. For variables, we @@ -16932,12 +16934,13 @@ return TransformToPE(*this).TransformType(TInfo); } -void -Sema::PushExpressionEvaluationContext( +void Sema::PushExpressionEvaluationContext( ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl, - ExpressionEvaluationContextRecord::ExpressionKind ExprContext) { + ExpressionEvaluationContextRecord::ExpressionKind ExprContext, + bool InAttributeArgs) { ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup, - LambdaContextDecl, ExprContext); + LambdaContextDecl, ExprContext, + InAttributeArgs); // Discarded statements and immediate contexts nested in other // discarded statements or immediate context are themselves Index: clang/lib/Parse/ParseDecl.cpp =================================================================== --- clang/lib/Parse/ParseDecl.cpp +++ clang/lib/Parse/ParseDecl.cpp @@ -444,9 +444,11 @@ // General case. Parse all available expressions. bool Uneval = attributeParsedArgsUnevaluated(*AttrName); EnterExpressionEvaluationContext Unevaluated( - Actions, Uneval - ? Sema::ExpressionEvaluationContext::Unevaluated - : Sema::ExpressionEvaluationContext::ConstantEvaluated); + Actions, + Uneval ? Sema::ExpressionEvaluationContext::Unevaluated + : Sema::ExpressionEvaluationContext::ConstantEvaluated, + nullptr, Sema::ExpressionEvaluationContextRecord::EK_Other, true, + /* InAttributeArgs = */ true); CommaLocsTy CommaLocs; ExprVector ParsedExprs; Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -1311,15 +1311,19 @@ bool InDiscardedStatement; bool InImmediateFunctionContext; + bool InAttributeArgsContext; + ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context, unsigned NumCleanupObjects, CleanupInfo ParentCleanup, Decl *ManglingContextDecl, - ExpressionKind ExprContext) + ExpressionKind ExprContext, + bool InAttributeArgsContext = false) : Context(Context), ParentCleanup(ParentCleanup), NumCleanupObjects(NumCleanupObjects), NumTypos(0), ManglingContextDecl(ManglingContextDecl), ExprContext(ExprContext), - InDiscardedStatement(false), InImmediateFunctionContext(false) {} + InDiscardedStatement(false), InImmediateFunctionContext(false), + InAttributeArgsContext(InAttributeArgsContext) {} bool isUnevaluated() const { return Context == ExpressionEvaluationContext::Unevaluated || @@ -5094,7 +5098,8 @@ void PushExpressionEvaluationContext( ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl = nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type = - ExpressionEvaluationContextRecord::EK_Other); + ExpressionEvaluationContextRecord::EK_Other, + bool InAttributeArgs = false); enum ReuseLambdaContextDecl_t { ReuseLambdaContextDecl }; void PushExpressionEvaluationContext( ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t, @@ -13263,11 +13268,11 @@ Decl *LambdaContextDecl = nullptr, Sema::ExpressionEvaluationContextRecord::ExpressionKind ExprContext = Sema::ExpressionEvaluationContextRecord::EK_Other, - bool ShouldEnter = true) + bool ShouldEnter = true, bool InAttributeArgs = false) : Actions(Actions), Entered(ShouldEnter) { if (Entered) Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl, - ExprContext); + ExprContext, InAttributeArgs); } EnterExpressionEvaluationContext( Sema &Actions, Sema::ExpressionEvaluationContext NewContext,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits