/// We are currently in the filter expression of an SEH except block.
SEHFilterScope = 0x200000,
+
+ /// This is a compound statement scope.
+ CompoundStmtScope = 0x400000,
};
private:
/// The parent scope for this scope. This is null for the translation-unit
/// \brief Determine whether this scope is a SEH '__except' block.
bool isSEHExceptScope() const { return getFlags() & Scope::SEHExceptScope; }
+ /// \brief Determine whether this scope is a compound statement scope.
+ bool isCompoundStmtScope() const {
+ return getFlags() & Scope::CompoundStmtScope;
+ }
+
/// \brief Returns if rhs has a higher scope depth than this.
///
/// The caller is responsible for calling this only if one of the two scopes
// Parse the method body. Function body parsing code is similar enough
// to be re-used for method bodies as well.
- ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
+ ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope);
Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D);
if (Tok.is(tok::kw_try)) {
// If the Decl is on a function, add function parameters to the scope.
bool HasFunScope = EnterScope && D->isFunctionOrFunctionTemplate();
- ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope, HasFunScope);
+ ParseScope FnScope(
+ this, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope,
+ HasFunScope);
if (HasFunScope)
Actions.ActOnReenterFunctionContext(Actions.CurScope, D);
// allows determining whether a variable reference inside the block is
// within or outside of the block.
ParseScope BlockScope(this, Scope::BlockScope | Scope::FnScope |
- Scope::DeclScope);
+ Scope::CompoundStmtScope | Scope::DeclScope);
// Inform sema that we are starting a block.
Actions.ActOnBlockStart(CaretLoc, getCurScope());
// FIXME: Rename BlockScope -> ClosureScope if we decide to continue using
// it.
- unsigned ScopeFlags = Scope::BlockScope | Scope::FnScope | Scope::DeclScope;
+ unsigned ScopeFlags = Scope::BlockScope | Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope;
ParseScope BodyScope(this, ScopeFlags);
Actions.ActOnStartOfLambdaDefinition(Intro, D, getCurScope());
operand = Actions.ActOnObjCAtSynchronizedOperand(atLoc, operand.get());
// Parse the compound statement within a new scope.
- ParseScope bodyScope(this, Scope::DeclScope);
+ ParseScope bodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope);
StmtResult body(ParseCompoundStatementBody());
bodyScope.Exit();
}
StmtVector CatchStmts;
StmtResult FinallyStmt;
- ParseScope TryScope(this, Scope::DeclScope);
+ ParseScope TryScope(this, Scope::DeclScope | Scope::CompoundStmtScope);
StmtResult TryBody(ParseCompoundStatementBody());
TryScope.Exit();
if (TryBody.isInvalid())
ConsumeToken(); // consume catch
if (Tok.is(tok::l_paren)) {
ConsumeParen();
- ParseScope CatchScope(this, Scope::DeclScope|Scope::AtCatchScope);
+ ParseScope CatchScope(this, Scope::DeclScope |
+ Scope::CompoundStmtScope |
+ Scope::AtCatchScope);
if (Tok.isNot(tok::ellipsis)) {
DeclSpec DS(AttrFactory);
ParseDeclarationSpecifiers(DS);
} else {
assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?");
ConsumeToken(); // consume finally
- ParseScope FinallyScope(this, Scope::DeclScope);
+ ParseScope FinallyScope(this,
+ Scope::DeclScope | Scope::CompoundStmtScope);
StmtResult FinallyBody(true);
if (Tok.is(tok::l_brace))
}
// Enter a scope to hold everything within the compound stmt. Compound
// statements can always hold declarations.
- ParseScope BodyScope(this, Scope::DeclScope);
+ ParseScope BodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope);
StmtResult AutoreleasePoolBody(ParseCompoundStatementBody());
assert(Tok.isOneOf(tok::l_brace, tok::kw_try, tok::colon) &&
"Inline objective-c method not starting with '{' or 'try' or ':'");
// Enter a scope for the method or c-function body.
- ParseScope BodyScope(this,
- parseMethod
- ? Scope::ObjCMethodScope|Scope::FnScope|Scope::DeclScope
- : Scope::FnScope|Scope::DeclScope);
-
+ ParseScope BodyScope(this, (parseMethod ? Scope::ObjCMethodScope : 0) |
+ Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope);
+
// Tell the actions module that we have entered a method or c-function definition
// with the specified Declarator for the method/function.
if (parseMethod)
for (auto *D : DRD.get()) {
TentativeParsingAction TPA(*this);
ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope |
Scope::OpenMPDirectiveScope);
// Parse <combiner> expression.
Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
IsCorrect;
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope |
Scope::OpenMPDirectiveScope);
// Parse expression.
Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(), D);
// If the Decl is on a function, add function parameters to the scope.
HasFunScope = D->isFunctionOrFunctionTemplate();
- FnScope = new Parser::ParseScope(&P, Scope::FnScope | Scope::DeclScope,
- HasFunScope);
+ FnScope = new Parser::ParseScope(
+ &P, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope,
+ HasFunScope);
if (HasFunScope)
Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
}
SmallVector<OMPClause *, 5> Clauses;
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
FirstClauses(OMPC_unknown + 1);
- unsigned ScopeFlags =
- Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope;
+ unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
auto DKind = ParseOpenMPDirectiveKind(*this);
OpenMPDirectiveKind CancelRegion = OMPD_unknown;
SourceLocation Loc = Tok.getLocation();
- ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
+ ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope);
Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
/*NumParams=*/1);
if (Tok.isNot(tok::l_brace))
return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
- StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false,
- Scope::DeclScope | Scope::SEHTryScope));
- if(TryBlock.isInvalid())
+ StmtResult TryBlock(ParseCompoundStatement(
+ /*isStmtExpr=*/false,
+ Scope::DeclScope | Scope::CompoundStmtScope | Scope::SEHTryScope));
+ if (TryBlock.isInvalid())
return TryBlock;
StmtResult Handler;
}
StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {
- return ParseCompoundStatement(isStmtExpr, Scope::DeclScope);
+ return ParseCompoundStatement(isStmtExpr,
+ Scope::DeclScope | Scope::CompoundStmtScope);
}
/// ParseCompoundStatement - Parse a "{}" block.
if (Tok.isNot(tok::l_brace))
return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
- StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false,
- Scope::DeclScope | Scope::TryScope |
- (FnTry ? Scope::FnTryCatchScope : 0)));
+ StmtResult TryBlock(ParseCompoundStatement(
+ /*isStmtExpr=*/false, Scope::DeclScope | Scope::TryScope |
+ Scope::CompoundStmtScope |
+ (FnTry ? Scope::FnTryCatchScope : 0)));
if (TryBlock.isInvalid())
return TryBlock;
// Parse the method body. Function body parsing code is similar enough
// to be re-used for method bodies as well.
- ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
+ ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope);
// Recreate the containing function DeclContext.
Sema::ContextRAII FunctionSavedContext(Actions,
TemplateInfo.Kind == ParsedTemplateInfo::Template &&
Actions.canDelayFunctionBody(D)) {
MultiTemplateParamsArg TemplateParameterLists(*TemplateInfo.TemplateParams);
-
- ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
+
+ ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope);
Scope *ParentScope = getCurScope()->getParent();
D.setFunctionDefinitionKind(FDK_Definition);
(Tok.is(tok::l_brace) || Tok.is(tok::kw_try) ||
Tok.is(tok::colon)) &&
Actions.CurContext->isTranslationUnit()) {
- ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
+ ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope);
Scope *ParentScope = getCurScope()->getParent();
D.setFunctionDefinitionKind(FDK_Definition);
}
// Enter a scope for the function body.
- ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
+ ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope);
// Tell the actions module that we have entered a function definition with the
// specified Declarator for the function.
SourceLocation());
D.SetIdentifier(&II, Loc);
- // Insert this function into translation-unit scope.
+ // Insert this function into the enclosing block scope.
+ while (S && !S->isCompoundStmtScope())
+ S = S->getParent();
+ if (S == nullptr)
+ S = TUScope;
DeclContext *PrevDC = CurContext;
CurContext = Context.getTranslationUnitDecl();
- FunctionDecl *FD = cast<FunctionDecl>(ActOnDeclarator(TUScope, D));
+ FunctionDecl *FD = cast<FunctionDecl>(ActOnDeclarator(S, D));
FD->setImplicit();
CurContext = PrevDC;
--- /dev/null
+// RUN: %clang_cc1 %s -std=c90 -verify -fsyntax-only
+void t0(int x) {
+ int (*p)();
+ if(x > 0)
+ x = g() + 1;
+ p = g;
+ if(x < 0) {
+ extern void u(int (*)[h()]);
+ int (*q)() = h;
+ }
+ p = h; /* expected-error {{use of undeclared identifier 'h'}} */
+}
+
+void t1(int x) {
+ int (*p)();
+ switch (x) {
+ g();
+ case 0:
+ x = h() + 1;
+ break;
+ case 1:
+ p = g;
+ p = h;
+ break;
+ }
+ p = g; /* expected-error {{use of undeclared identifier 'g'}} */
+ p = h; /* expected-error {{use of undeclared identifier 'h'}} */
+}
+
+int t2(int x) {
+ int y = ({ if (x > 0) x = g() + 1; 2*x; });
+ int (*p)() = g; /* expected-error {{use of undeclared identifier 'g'}} */
+ return y;
+}
+
+int (*p)() = g; /* expected-error {{use of undeclared identifier 'g'}} */
+int (*q)() = h; /* expected-error {{use of undeclared identifier 'h'}} */
+
+float g(); /* not expecting conflicting types diagnostics here */
int32_t *vector[16];
const char compDesc[16 + 1];
int32_t compCount = 0;
- if (_CFCalendarDecomposeAbsoluteTimeV(compDesc, vector, compCount)) { // expected-note {{previous implicit declaration is here}} \
- expected-error {{implicit declaration of function '_CFCalendarDecomposeAbsoluteTimeV' is invalid in C99}}
+ if (_CFCalendarDecomposeAbsoluteTimeV(compDesc, vector, compCount)) { // expected-error {{implicit declaration of function '_CFCalendarDecomposeAbsoluteTimeV' is invalid in C99}}
}
printg("Hello, World!\n"); // expected-error{{implicit declaration of function 'printg' is invalid in C99}} \
__builtin_is_les(1, 3); // expected-error{{use of unknown builtin '__builtin_is_les'}}
}
-Boolean _CFCalendarDecomposeAbsoluteTimeV(const char *componentDesc, int32_t **vector, int32_t count) { // expected-error{{conflicting types for '_CFCalendarDecomposeAbsoluteTimeV'}}
+Boolean _CFCalendarDecomposeAbsoluteTimeV(const char *componentDesc, int32_t **vector, int32_t count) {
return 0;
}