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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits