[cfe-commits] r149937 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaExpr.cpp test/CXX/class/class.local/p1-0x.cpp test/CXX/class/class.local/p1.cpp test/CXX/class/class.local/p3.cpp test/SemaCXX/c99-variable-length-array.cpp
Eli Friedman
eli.friedman at gmail.com
Mon Feb 6 16:15:00 PST 2012
Author: efriedma
Date: Mon Feb 6 18:15:00 2012
New Revision: 149937
URL: http://llvm.org/viewvc/llvm-project?rev=149937&view=rev
Log:
Misc improvements to the diagnostic when a variable is odr-used in a context that is not allowed to capture variables.
Fixes PR11883.
Added:
cfe/trunk/test/CXX/class/class.local/p1-0x.cpp
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/test/CXX/class/class.local/p1.cpp
cfe/trunk/test/CXX/class/class.local/p3.cpp
cfe/trunk/test/SemaCXX/c99-variable-length-array.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=149937&r1=149936&r2=149937&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Feb 6 18:15:00 2012
@@ -4636,7 +4636,14 @@
// C++ local classes
def err_reference_to_local_var_in_enclosing_function : Error<
- "reference to local variable %0 declared in enclosed function %1">;
+ "reference to local variable %0 declared in enclosing function %1">;
+def err_reference_to_local_var_in_enclosing_block : Error<
+ "reference to local variable %0 declared in enclosing block literal">;
+def err_reference_to_local_var_in_enclosing_lambda : Error<
+ "reference to local variable %0 declared in enclosing lambda expression">;
+def err_reference_to_local_var_in_enclosing_context : Error<
+ "reference to local variable %0 declared in enclosing context">;
+
def note_local_variable_declared_here : Note<
"%0 declared here">;
def err_static_data_member_not_allowed_in_local_class : Error<
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=149937&r1=149936&r2=149937&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Feb 6 18:15:00 2012
@@ -9471,29 +9471,47 @@
static void
diagnoseUncapturableValueReference(Sema &S, SourceLocation loc,
VarDecl *var, DeclContext *DC) {
+ DeclContext *VarDC = var->getDeclContext();
+
// If the parameter still belongs to the translation unit, then
// we're actually just using one parameter in the declaration of
// the next.
if (isa<ParmVarDecl>(var) &&
- isa<TranslationUnitDecl>(var->getDeclContext()))
+ isa<TranslationUnitDecl>(VarDC))
return;
- // Don't diagnose about capture if we're not actually in code right
- // now; in general, there are more appropriate places that will
- // diagnose this.
- // FIXME: We incorrectly skip diagnosing C++11 member initializers.
- if (!S.CurContext->isFunctionOrMethod())
+ // For C code, don't diagnose about capture if we're not actually in code
+ // right now; it's impossible to write a non-constant expression outside of
+ // function context, so we'll get other (more useful) diagnostics later.
+ //
+ // For C++, things get a bit more nasty... it would be nice to suppress this
+ // diagnostic for certain cases like using a local variable in an array bound
+ // for a member of a local class, but the correct predicate is not obvious.
+ if (!S.getLangOptions().CPlusPlus && !S.CurContext->isFunctionOrMethod())
return;
- DeclarationName functionName;
- if (FunctionDecl *fn = dyn_cast<FunctionDecl>(var->getDeclContext()))
- functionName = fn->getDeclName();
- // FIXME: variable from enclosing block that we couldn't capture from!
+ if (isa<CXXMethodDecl>(VarDC) &&
+ cast<CXXRecordDecl>(VarDC->getParent())->isLambda()) {
+ S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_lambda)
+ << var->getIdentifier();
+ } else if (FunctionDecl *fn = dyn_cast<FunctionDecl>(VarDC)) {
+ S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_function)
+ << var->getIdentifier() << fn->getDeclName();
+ } else if (isa<BlockDecl>(VarDC)) {
+ S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_block)
+ << var->getIdentifier();
+ } else {
+ // FIXME: Is there any other context where a local variable can be
+ // declared?
+ S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_context)
+ << var->getIdentifier();
+ }
- S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_function)
- << var->getIdentifier() << functionName;
S.Diag(var->getLocation(), diag::note_local_variable_declared_here)
<< var->getIdentifier();
+
+ // FIXME: Add additional diagnostic info about class etc. which prevents
+ // capture.
}
static bool shouldAddConstForScope(CapturingScopeInfo *CSI, VarDecl *VD) {
Added: cfe/trunk/test/CXX/class/class.local/p1-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.local/p1-0x.cpp?rev=149937&view=auto
==============================================================================
--- cfe/trunk/test/CXX/class/class.local/p1-0x.cpp (added)
+++ cfe/trunk/test/CXX/class/class.local/p1-0x.cpp Mon Feb 6 18:15:00 2012
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
+void f() {
+ int x = 3; // expected-note{{'x' declared here}}
+ const int c = 2;
+ struct C {
+ int& x2 = x; // expected-error{{reference to local variable 'x' declared in enclosing function 'f'}}
+ int cc = c;
+ };
+ []() mutable { // expected-error {{not supported yet}}
+ int x = 3; // expected-note{{'x' declared here}}
+ struct C {
+ int& x2 = x; // expected-error{{reference to local variable 'x' declared in enclosing lambda expression}}
+ };
+ }
+ C();
+}
+
Modified: cfe/trunk/test/CXX/class/class.local/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.local/p1.cpp?rev=149937&r1=149936&r2=149937&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class/class.local/p1.cpp (original)
+++ cfe/trunk/test/CXX/class/class.local/p1.cpp Mon Feb 6 18:15:00 2012
@@ -8,7 +8,7 @@
extern int g();
struct local {
- int g() { return x; } // expected-error{{reference to local variable 'x' declared in enclosed function 'f'}}
+ int g() { return x; } // expected-error{{reference to local variable 'x' declared in enclosing function 'f'}}
int h() { return s; }
int k() { return :: x; }
int l() { return g(); }
Modified: cfe/trunk/test/CXX/class/class.local/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.local/p3.cpp?rev=149937&r1=149936&r2=149937&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class/class.local/p3.cpp (original)
+++ cfe/trunk/test/CXX/class/class.local/p3.cpp Mon Feb 6 18:15:00 2012
@@ -24,7 +24,7 @@
void f3(int a) { // expected-note{{'a' declared here}}
struct X {
struct Y {
- int f() { return a; } // expected-error{{reference to local variable 'a' declared in enclosed function 'f3'}}
+ int f() { return a; } // expected-error{{reference to local variable 'a' declared in enclosing function 'f3'}}
};
};
}
Modified: cfe/trunk/test/SemaCXX/c99-variable-length-array.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/c99-variable-length-array.cpp?rev=149937&r1=149936&r2=149937&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/c99-variable-length-array.cpp (original)
+++ cfe/trunk/test/SemaCXX/c99-variable-length-array.cpp Mon Feb 6 18:15:00 2012
@@ -73,10 +73,11 @@
}
// Variably-modified types cannot be used in local classes.
-void local_classes(int N) {
+void local_classes(int N) { // expected-note {{declared here}}
struct X {
int size;
int array[N]; // expected-error{{fields must have a constant size: 'variable length array in structure' extension will never be supported}} \
+ // expected-error{{reference to local variable 'N' declared in enclosing function 'local_classes'}} \
// expected-warning{{variable length arrays are a C99 feature}}
};
}
More information about the cfe-commits
mailing list