Skip to content

Commit 57c681f

Browse files
committedAug 10, 2017
Place implictly declared functions at block scope
Such implicitly declared functions behave as if the enclosing block contained the declaration extern int name() (C90, 6.3.3.2 Function calls), thus their names should have block scope (C90, 6.1.2.1 Scope of identifiers). This patch fixes https://bugs.llvm.org/show_bug.cgi?id=33224 Differential Revision: https://reviews.llvm.org/D33676 llvm-svn: 310616
1 parent c717041 commit 57c681f

14 files changed

+103
-36
lines changed
 

Diff for: ‎clang/include/clang/Sema/Scope.h

+8
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ class Scope {
124124

125125
/// We are currently in the filter expression of an SEH except block.
126126
SEHFilterScope = 0x200000,
127+
128+
/// This is a compound statement scope.
129+
CompoundStmtScope = 0x400000,
127130
};
128131
private:
129132
/// The parent scope for this scope. This is null for the translation-unit
@@ -429,6 +432,11 @@ class Scope {
429432
/// \brief Determine whether this scope is a SEH '__except' block.
430433
bool isSEHExceptScope() const { return getFlags() & Scope::SEHExceptScope; }
431434

435+
/// \brief Determine whether this scope is a compound statement scope.
436+
bool isCompoundStmtScope() const {
437+
return getFlags() & Scope::CompoundStmtScope;
438+
}
439+
432440
/// \brief Returns if rhs has a higher scope depth than this.
433441
///
434442
/// The caller is responsible for calling this only if one of the two scopes

Diff for: ‎clang/lib/Parse/ParseCXXInlineMethods.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,8 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
518518

519519
// Parse the method body. Function body parsing code is similar enough
520520
// to be re-used for method bodies as well.
521-
ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
521+
ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope |
522+
Scope::CompoundStmtScope);
522523
Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D);
523524

524525
if (Tok.is(tok::kw_try)) {

Diff for: ‎clang/lib/Parse/ParseDecl.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -1388,7 +1388,9 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
13881388

13891389
// If the Decl is on a function, add function parameters to the scope.
13901390
bool HasFunScope = EnterScope && D->isFunctionOrFunctionTemplate();
1391-
ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope, HasFunScope);
1391+
ParseScope FnScope(
1392+
this, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope,
1393+
HasFunScope);
13921394
if (HasFunScope)
13931395
Actions.ActOnReenterFunctionContext(Actions.CurScope, D);
13941396

Diff for: ‎clang/lib/Parse/ParseExpr.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -2881,7 +2881,7 @@ ExprResult Parser::ParseBlockLiteralExpression() {
28812881
// allows determining whether a variable reference inside the block is
28822882
// within or outside of the block.
28832883
ParseScope BlockScope(this, Scope::BlockScope | Scope::FnScope |
2884-
Scope::DeclScope);
2884+
Scope::CompoundStmtScope | Scope::DeclScope);
28852885

28862886
// Inform sema that we are starting a block.
28872887
Actions.ActOnBlockStart(CaretLoc, getCurScope());

Diff for: ‎clang/lib/Parse/ParseExprCXX.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1281,7 +1281,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
12811281

12821282
// FIXME: Rename BlockScope -> ClosureScope if we decide to continue using
12831283
// it.
1284-
unsigned ScopeFlags = Scope::BlockScope | Scope::FnScope | Scope::DeclScope;
1284+
unsigned ScopeFlags = Scope::BlockScope | Scope::FnScope | Scope::DeclScope |
1285+
Scope::CompoundStmtScope;
12851286
ParseScope BodyScope(this, ScopeFlags);
12861287

12871288
Actions.ActOnStartOfLambdaDefinition(Intro, D, getCurScope());

Diff for: ‎clang/lib/Parse/ParseObjc.cpp

+12-10
Original file line numberDiff line numberDiff line change
@@ -2478,7 +2478,7 @@ Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
24782478
operand = Actions.ActOnObjCAtSynchronizedOperand(atLoc, operand.get());
24792479

24802480
// Parse the compound statement within a new scope.
2481-
ParseScope bodyScope(this, Scope::DeclScope);
2481+
ParseScope bodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope);
24822482
StmtResult body(ParseCompoundStatementBody());
24832483
bodyScope.Exit();
24842484

@@ -2514,7 +2514,7 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
25142514
}
25152515
StmtVector CatchStmts;
25162516
StmtResult FinallyStmt;
2517-
ParseScope TryScope(this, Scope::DeclScope);
2517+
ParseScope TryScope(this, Scope::DeclScope | Scope::CompoundStmtScope);
25182518
StmtResult TryBody(ParseCompoundStatementBody());
25192519
TryScope.Exit();
25202520
if (TryBody.isInvalid())
@@ -2535,7 +2535,9 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
25352535
ConsumeToken(); // consume catch
25362536
if (Tok.is(tok::l_paren)) {
25372537
ConsumeParen();
2538-
ParseScope CatchScope(this, Scope::DeclScope|Scope::AtCatchScope);
2538+
ParseScope CatchScope(this, Scope::DeclScope |
2539+
Scope::CompoundStmtScope |
2540+
Scope::AtCatchScope);
25392541
if (Tok.isNot(tok::ellipsis)) {
25402542
DeclSpec DS(AttrFactory);
25412543
ParseDeclarationSpecifiers(DS);
@@ -2579,7 +2581,8 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
25792581
} else {
25802582
assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?");
25812583
ConsumeToken(); // consume finally
2582-
ParseScope FinallyScope(this, Scope::DeclScope);
2584+
ParseScope FinallyScope(this,
2585+
Scope::DeclScope | Scope::CompoundStmtScope);
25832586

25842587
StmtResult FinallyBody(true);
25852588
if (Tok.is(tok::l_brace))
@@ -2616,7 +2619,7 @@ Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) {
26162619
}
26172620
// Enter a scope to hold everything within the compound stmt. Compound
26182621
// statements can always hold declarations.
2619-
ParseScope BodyScope(this, Scope::DeclScope);
2622+
ParseScope BodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope);
26202623

26212624
StmtResult AutoreleasePoolBody(ParseCompoundStatementBody());
26222625

@@ -3650,11 +3653,10 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
36503653
assert(Tok.isOneOf(tok::l_brace, tok::kw_try, tok::colon) &&
36513654
"Inline objective-c method not starting with '{' or 'try' or ':'");
36523655
// Enter a scope for the method or c-function body.
3653-
ParseScope BodyScope(this,
3654-
parseMethod
3655-
? Scope::ObjCMethodScope|Scope::FnScope|Scope::DeclScope
3656-
: Scope::FnScope|Scope::DeclScope);
3657-
3656+
ParseScope BodyScope(this, (parseMethod ? Scope::ObjCMethodScope : 0) |
3657+
Scope::FnScope | Scope::DeclScope |
3658+
Scope::CompoundStmtScope);
3659+
36583660
// Tell the actions module that we have entered a method or c-function definition
36593661
// with the specified Declarator for the method/function.
36603662
if (parseMethod)

Diff for: ‎clang/lib/Parse/ParseOpenMP.cpp

+7-4
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
302302
for (auto *D : DRD.get()) {
303303
TentativeParsingAction TPA(*this);
304304
ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
305+
Scope::CompoundStmtScope |
305306
Scope::OpenMPDirectiveScope);
306307
// Parse <combiner> expression.
307308
Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
@@ -337,6 +338,7 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
337338
IsCorrect;
338339
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
339340
ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
341+
Scope::CompoundStmtScope |
340342
Scope::OpenMPDirectiveScope);
341343
// Parse expression.
342344
Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(), D);
@@ -405,8 +407,9 @@ class FNContextRAII final {
405407

406408
// If the Decl is on a function, add function parameters to the scope.
407409
HasFunScope = D->isFunctionOrFunctionTemplate();
408-
FnScope = new Parser::ParseScope(&P, Scope::FnScope | Scope::DeclScope,
409-
HasFunScope);
410+
FnScope = new Parser::ParseScope(
411+
&P, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope,
412+
HasFunScope);
410413
if (HasFunScope)
411414
Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
412415
}
@@ -813,8 +816,8 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
813816
SmallVector<OMPClause *, 5> Clauses;
814817
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
815818
FirstClauses(OMPC_unknown + 1);
816-
unsigned ScopeFlags =
817-
Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope;
819+
unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
820+
Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
818821
SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
819822
auto DKind = ParseOpenMPDirectiveKind(*this);
820823
OpenMPDirectiveKind CancelRegion = OMPD_unknown;

Diff for: ‎clang/lib/Parse/ParsePragma.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,8 @@ StmtResult Parser::HandlePragmaCaptured()
533533

534534
SourceLocation Loc = Tok.getLocation();
535535

536-
ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
536+
ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
537+
Scope::CompoundStmtScope);
537538
Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
538539
/*NumParams=*/1);
539540

Diff for: ‎clang/lib/Parse/ParseStmt.cpp

+10-7
Original file line numberDiff line numberDiff line change
@@ -453,9 +453,10 @@ StmtResult Parser::ParseSEHTryBlock() {
453453
if (Tok.isNot(tok::l_brace))
454454
return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
455455

456-
StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false,
457-
Scope::DeclScope | Scope::SEHTryScope));
458-
if(TryBlock.isInvalid())
456+
StmtResult TryBlock(ParseCompoundStatement(
457+
/*isStmtExpr=*/false,
458+
Scope::DeclScope | Scope::CompoundStmtScope | Scope::SEHTryScope));
459+
if (TryBlock.isInvalid())
459460
return TryBlock;
460461

461462
StmtResult Handler;
@@ -840,7 +841,8 @@ StmtResult Parser::ParseDefaultStatement() {
840841
}
841842

842843
StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {
843-
return ParseCompoundStatement(isStmtExpr, Scope::DeclScope);
844+
return ParseCompoundStatement(isStmtExpr,
845+
Scope::DeclScope | Scope::CompoundStmtScope);
844846
}
845847

846848
/// ParseCompoundStatement - Parse a "{}" block.
@@ -2085,9 +2087,10 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) {
20852087
if (Tok.isNot(tok::l_brace))
20862088
return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
20872089

2088-
StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false,
2089-
Scope::DeclScope | Scope::TryScope |
2090-
(FnTry ? Scope::FnTryCatchScope : 0)));
2090+
StmtResult TryBlock(ParseCompoundStatement(
2091+
/*isStmtExpr=*/false, Scope::DeclScope | Scope::TryScope |
2092+
Scope::CompoundStmtScope |
2093+
(FnTry ? Scope::FnTryCatchScope : 0)));
20912094
if (TryBlock.isInvalid())
20922095
return TryBlock;
20932096

Diff for: ‎clang/lib/Parse/ParseTemplate.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1380,7 +1380,8 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
13801380

13811381
// Parse the method body. Function body parsing code is similar enough
13821382
// to be re-used for method bodies as well.
1383-
ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
1383+
ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope |
1384+
Scope::CompoundStmtScope);
13841385

13851386
// Recreate the containing function DeclContext.
13861387
Sema::ContextRAII FunctionSavedContext(Actions,

Diff for: ‎clang/lib/Parse/Parser.cpp

+7-4
Original file line numberDiff line numberDiff line change
@@ -1075,8 +1075,9 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
10751075
TemplateInfo.Kind == ParsedTemplateInfo::Template &&
10761076
Actions.canDelayFunctionBody(D)) {
10771077
MultiTemplateParamsArg TemplateParameterLists(*TemplateInfo.TemplateParams);
1078-
1079-
ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
1078+
1079+
ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope |
1080+
Scope::CompoundStmtScope);
10801081
Scope *ParentScope = getCurScope()->getParent();
10811082

10821083
D.setFunctionDefinitionKind(FDK_Definition);
@@ -1106,7 +1107,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
11061107
(Tok.is(tok::l_brace) || Tok.is(tok::kw_try) ||
11071108
Tok.is(tok::colon)) &&
11081109
Actions.CurContext->isTranslationUnit()) {
1109-
ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
1110+
ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope |
1111+
Scope::CompoundStmtScope);
11101112
Scope *ParentScope = getCurScope()->getParent();
11111113

11121114
D.setFunctionDefinitionKind(FDK_Definition);
@@ -1124,7 +1126,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
11241126
}
11251127

11261128
// Enter a scope for the function body.
1127-
ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
1129+
ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope |
1130+
Scope::CompoundStmtScope);
11281131

11291132
// Tell the actions module that we have entered a function definition with the
11301133
// specified Declarator for the function.

Diff for: ‎clang/lib/Sema/SemaDecl.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -12677,12 +12677,16 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
1267712677
SourceLocation());
1267812678
D.SetIdentifier(&II, Loc);
1267912679

12680-
// Insert this function into translation-unit scope.
12680+
// Insert this function into the enclosing block scope.
12681+
while (S && !S->isCompoundStmtScope())
12682+
S = S->getParent();
12683+
if (S == nullptr)
12684+
S = TUScope;
1268112685

1268212686
DeclContext *PrevDC = CurContext;
1268312687
CurContext = Context.getTranslationUnitDecl();
1268412688

12685-
FunctionDecl *FD = cast<FunctionDecl>(ActOnDeclarator(TUScope, D));
12689+
FunctionDecl *FD = cast<FunctionDecl>(ActOnDeclarator(S, D));
1268612690
FD->setImplicit();
1268712691

1268812692
CurContext = PrevDC;

Diff for: ‎clang/test/Sema/implicit-decl-c90.c

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %clang_cc1 %s -std=c90 -verify -fsyntax-only
2+
void t0(int x) {
3+
int (*p)();
4+
if(x > 0)
5+
x = g() + 1;
6+
p = g;
7+
if(x < 0) {
8+
extern void u(int (*)[h()]);
9+
int (*q)() = h;
10+
}
11+
p = h; /* expected-error {{use of undeclared identifier 'h'}} */
12+
}
13+
14+
void t1(int x) {
15+
int (*p)();
16+
switch (x) {
17+
g();
18+
case 0:
19+
x = h() + 1;
20+
break;
21+
case 1:
22+
p = g;
23+
p = h;
24+
break;
25+
}
26+
p = g; /* expected-error {{use of undeclared identifier 'g'}} */
27+
p = h; /* expected-error {{use of undeclared identifier 'h'}} */
28+
}
29+
30+
int t2(int x) {
31+
int y = ({ if (x > 0) x = g() + 1; 2*x; });
32+
int (*p)() = g; /* expected-error {{use of undeclared identifier 'g'}} */
33+
return y;
34+
}
35+
36+
int (*p)() = g; /* expected-error {{use of undeclared identifier 'g'}} */
37+
int (*q)() = h; /* expected-error {{use of undeclared identifier 'h'}} */
38+
39+
float g(); /* not expecting conflicting types diagnostics here */

Diff for: ‎clang/test/Sema/implicit-decl.c

+2-3
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,15 @@ void func() {
99
int32_t *vector[16];
1010
const char compDesc[16 + 1];
1111
int32_t compCount = 0;
12-
if (_CFCalendarDecomposeAbsoluteTimeV(compDesc, vector, compCount)) { // expected-note {{previous implicit declaration is here}} \
13-
expected-error {{implicit declaration of function '_CFCalendarDecomposeAbsoluteTimeV' is invalid in C99}}
12+
if (_CFCalendarDecomposeAbsoluteTimeV(compDesc, vector, compCount)) { // expected-error {{implicit declaration of function '_CFCalendarDecomposeAbsoluteTimeV' is invalid in C99}}
1413
}
1514

1615
printg("Hello, World!\n"); // expected-error{{implicit declaration of function 'printg' is invalid in C99}} \
1716
// expected-note{{did you mean 'printf'?}}
1817

1918
__builtin_is_les(1, 3); // expected-error{{use of unknown builtin '__builtin_is_les'}}
2019
}
21-
Boolean _CFCalendarDecomposeAbsoluteTimeV(const char *componentDesc, int32_t **vector, int32_t count) { // expected-error{{conflicting types for '_CFCalendarDecomposeAbsoluteTimeV'}}
20+
Boolean _CFCalendarDecomposeAbsoluteTimeV(const char *componentDesc, int32_t **vector, int32_t count) {
2221
return 0;
2322
}
2423

0 commit comments

Comments
 (0)
Please sign in to comment.