diff options
author | Reid Kleckner <rnk@google.com> | 2017-05-04 19:51:05 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2017-05-04 19:51:05 +0000 |
commit | f1deb837eee39ec6ddbe177be9de129f4fd59ee1 (patch) | |
tree | da123b2ab5fec9c0a7ad332a4a5ff2a97cc1d2ea /clang/lib/Sema/SemaChecking.cpp | |
parent | dea97cfbf9515b7732e54530649495172470bf55 (diff) | |
download | bcm5719-llvm-f1deb837eee39ec6ddbe177be9de129f4fd59ee1.tar.gz bcm5719-llvm-f1deb837eee39ec6ddbe177be9de129f4fd59ee1.zip |
Fix bugs checking va_start in lambdas and erroneous contexts
Summary:
First, getCurFunction looks through blocks and lambdas, which is wrong.
Inside a lambda, va_start should refer to the lambda call operator
prototype. This fixes PR32737.
Second, we shouldn't use any of the getCur* methods, because they look
through contexts that we don't want to look through (EnumDecl,
CapturedStmtDecl). We can use CurContext directly as the calling
context.
Finally, this code assumed that CallExprs would never appear outside of
code contexts (block, function, obj-c method), which is wrong. Struct
member initializers are an easy way to create and parse exprs in a
non-code context.
Reviewers: rsmith
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D32761
llvm-svn: 302188
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index a206100b89e..14dd6267b85 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3652,22 +3652,29 @@ static bool checkVAStartIsInVariadicFunction(Sema &S, Expr *Fn, // and get its parameter list. bool IsVariadic = false; ArrayRef<ParmVarDecl *> Params; - if (BlockScopeInfo *CurBlock = S.getCurBlock()) { - IsVariadic = CurBlock->TheDecl->isVariadic(); - Params = CurBlock->TheDecl->parameters(); - } else if (FunctionDecl *FD = S.getCurFunctionDecl()) { + DeclContext *Caller = S.CurContext; + if (auto *Block = dyn_cast<BlockDecl>(Caller)) { + IsVariadic = Block->isVariadic(); + Params = Block->parameters(); + } else if (auto *FD = dyn_cast<FunctionDecl>(Caller)) { IsVariadic = FD->isVariadic(); Params = FD->parameters(); - } else if (ObjCMethodDecl *MD = S.getCurMethodDecl()) { + } else if (auto *MD = dyn_cast<ObjCMethodDecl>(Caller)) { IsVariadic = MD->isVariadic(); // FIXME: This isn't correct for methods (results in bogus warning). Params = MD->parameters(); + } else if (isa<CapturedDecl>(Caller)) { + // We don't support va_start in a CapturedDecl. + S.Diag(Fn->getLocStart(), diag::err_va_start_captured_stmt); + return true; } else { - llvm_unreachable("unknown va_start context"); + // This must be some other declcontext that parses exprs. + S.Diag(Fn->getLocStart(), diag::err_va_start_outside_function); + return true; } if (!IsVariadic) { - S.Diag(Fn->getLocStart(), diag::err_va_start_used_in_non_variadic_function); + S.Diag(Fn->getLocStart(), diag::err_va_start_fixed_function); return true; } |