summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2017-05-04 19:51:05 +0000
committerReid Kleckner <rnk@google.com>2017-05-04 19:51:05 +0000
commitf1deb837eee39ec6ddbe177be9de129f4fd59ee1 (patch)
treeda123b2ab5fec9c0a7ad332a4a5ff2a97cc1d2ea /clang/lib/Sema/SemaChecking.cpp
parentdea97cfbf9515b7732e54530649495172470bf55 (diff)
downloadbcm5719-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.cpp21
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;
}
OpenPOWER on IntegriCloud