diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-02-07 00:15:00 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-02-07 00:15:00 +0000 |
commit | 0a29422eb722c0ffbb98b98d8636042b19069f1a (patch) | |
tree | a05c8d41e8c6cdab329772107b7e7c23da654e10 /lib | |
parent | f9ea953f22d8e50cae7fd541406d6f563ef86cda (diff) |
Misc improvements to the diagnostic when a variable is odr-used in a context that is not allowed to capture variables.
Fixes PR11883.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149937 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 8afe0c25b9..c21979758d 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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) { |