Index: cfe/trunk/include/clang/Sema/Scope.h =================================================================== --- cfe/trunk/include/clang/Sema/Scope.h +++ cfe/trunk/include/clang/Sema/Scope.h @@ -124,6 +124,9 @@ /// 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 @@ -429,6 +432,11 @@ /// \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 Index: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp +++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp @@ -518,7 +518,8 @@ // 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)) { Index: cfe/trunk/lib/Parse/ParseDecl.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseDecl.cpp +++ cfe/trunk/lib/Parse/ParseDecl.cpp @@ -1388,7 +1388,9 @@ // 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); Index: cfe/trunk/lib/Parse/ParseExpr.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseExpr.cpp +++ cfe/trunk/lib/Parse/ParseExpr.cpp @@ -2881,7 +2881,7 @@ // 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()); Index: cfe/trunk/lib/Parse/ParseExprCXX.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseExprCXX.cpp +++ cfe/trunk/lib/Parse/ParseExprCXX.cpp @@ -1281,7 +1281,8 @@ // 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()); Index: cfe/trunk/lib/Parse/ParseObjc.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseObjc.cpp +++ cfe/trunk/lib/Parse/ParseObjc.cpp @@ -2478,7 +2478,7 @@ 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(); @@ -2514,7 +2514,7 @@ } StmtVector CatchStmts; StmtResult FinallyStmt; - ParseScope TryScope(this, Scope::DeclScope); + ParseScope TryScope(this, Scope::DeclScope | Scope::CompoundStmtScope); StmtResult TryBody(ParseCompoundStatementBody()); TryScope.Exit(); if (TryBody.isInvalid()) @@ -2535,7 +2535,9 @@ 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); @@ -2579,7 +2581,8 @@ } 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)) @@ -2616,7 +2619,7 @@ } // 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()); @@ -3650,11 +3653,10 @@ 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) Index: cfe/trunk/lib/Parse/ParseOpenMP.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseOpenMP.cpp +++ cfe/trunk/lib/Parse/ParseOpenMP.cpp @@ -302,6 +302,7 @@ for (auto *D : DRD.get()) { TentativeParsingAction TPA(*this); ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | + Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope); // Parse expression. Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D); @@ -337,6 +338,7 @@ 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); @@ -405,8 +407,9 @@ // 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); } @@ -813,8 +816,8 @@ SmallVector Clauses; SmallVector, 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; Index: cfe/trunk/lib/Parse/ParsePragma.cpp =================================================================== --- cfe/trunk/lib/Parse/ParsePragma.cpp +++ cfe/trunk/lib/Parse/ParsePragma.cpp @@ -533,7 +533,8 @@ 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); Index: cfe/trunk/lib/Parse/ParseStmt.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseStmt.cpp +++ cfe/trunk/lib/Parse/ParseStmt.cpp @@ -453,9 +453,10 @@ 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; @@ -840,7 +841,8 @@ } StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) { - return ParseCompoundStatement(isStmtExpr, Scope::DeclScope); + return ParseCompoundStatement(isStmtExpr, + Scope::DeclScope | Scope::CompoundStmtScope); } /// ParseCompoundStatement - Parse a "{}" block. @@ -2085,9 +2087,10 @@ 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; Index: cfe/trunk/lib/Parse/ParseTemplate.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseTemplate.cpp +++ cfe/trunk/lib/Parse/ParseTemplate.cpp @@ -1380,7 +1380,8 @@ // 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, Index: cfe/trunk/lib/Parse/Parser.cpp =================================================================== --- cfe/trunk/lib/Parse/Parser.cpp +++ cfe/trunk/lib/Parse/Parser.cpp @@ -1075,8 +1075,9 @@ 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); @@ -1106,7 +1107,8 @@ (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); @@ -1124,7 +1126,8 @@ } // 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. Index: cfe/trunk/lib/Sema/SemaDecl.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp +++ cfe/trunk/lib/Sema/SemaDecl.cpp @@ -12677,12 +12677,16 @@ 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(ActOnDeclarator(TUScope, D)); + FunctionDecl *FD = cast(ActOnDeclarator(S, D)); FD->setImplicit(); CurContext = PrevDC; Index: cfe/trunk/test/Sema/implicit-decl-c90.c =================================================================== --- cfe/trunk/test/Sema/implicit-decl-c90.c +++ cfe/trunk/test/Sema/implicit-decl-c90.c @@ -0,0 +1,39 @@ +// 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 */ Index: cfe/trunk/test/Sema/implicit-decl.c =================================================================== --- cfe/trunk/test/Sema/implicit-decl.c +++ cfe/trunk/test/Sema/implicit-decl.c @@ -9,8 +9,7 @@ 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}} \ @@ -18,7 +17,7 @@ __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; }