forked from OSchip/llvm-project
Misc improvements to the diagnostic when a variable is odr-used in a context that is not allowed to capture variables.
Fixes PR11883. llvm-svn: 149937
This commit is contained in:
parent
9972958a89
commit
dd053f6fba
|
@ -4636,7 +4636,14 @@ def ext_ms_anonymous_struct : ExtWarn<
|
|||
|
||||
// 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<
|
||||
|
|
|
@ -9471,29 +9471,47 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) {
|
|||
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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ void f()
|
|||
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(); }
|
||||
|
|
|
@ -24,7 +24,7 @@ void f2() {
|
|||
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'}}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -73,10 +73,11 @@ void test_accept_array(int N) {
|
|||
}
|
||||
|
||||
// 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}}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue