summaryrefslogtreecommitdiff
path: root/lib/Parse
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2016-12-09 17:14:05 +0000
committerReid Kleckner <rnk@google.com>2016-12-09 17:14:05 +0000
commit3a67a19e28fc3380fb836a5ff9a33a55cf197547 (patch)
tree8954b85fc3617925f8a70e846bc3542e3c5b8780 /lib/Parse
parent153c995100ac3869ce54e68baa8ece8f97270ea4 (diff)
downloadclang-3a67a19e28fc3380fb836a5ff9a33a55cf197547.tar.gz
Store decls in prototypes on the declarator instead of in the AST
This saves two pointers from FunctionDecl that were being used for some rare and questionable C-only functionality. The DeclsInPrototypeScope ArrayRef was added in r151712 in order to parse this kind of C code: enum e {x, y}; int f(enum {y, x} n) { return x; // should return 1, not 0 } The challenge is that we parse 'int f(enum {y, x} n)' it its own function prototype scope that gets popped before we build the FunctionDecl for 'f'. The original change was doing two questionable things: 1. Saving all tag decls introduced in prototype scope on a TU-global Sema variable. This is problematic when you have cases like this, where 'x' and 'y' shouldn't be visible in 'f': void f(void (*fp)(enum { x, y } e)) { /* no x */ } This patch fixes that, so now 'f' can't see 'x', which is consistent with GCC. 2. Storing the decls in FunctionDecl in ActOnFunctionDeclarator so that they could be used in ActOnStartOfFunctionDef. This is just an inefficient way to move information around. The AST lives forever, but the list of non-parameter decls in prototype scope is short lived. Moving these things to the Declarator solves both of these issues. Reviewers: rsmith Subscribers: jmolloy, cfe-commits Differential Revision: https://reviews.llvm.org/D27279 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@289225 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse')
-rw-r--r--lib/Parse/ParseDecl.cpp16
-rw-r--r--lib/Parse/ParseExpr.cpp1
-rw-r--r--lib/Parse/ParseExprCXX.cpp2
3 files changed, 19 insertions, 0 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index ea7ab26770..9dda75e3f9 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -5827,6 +5827,21 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
}
}
+ // Collect non-parameter declarations from the prototype if this is a function
+ // declaration. They will be moved into the scope of the function. Only do
+ // this in C and not C++, where the decls will continue to live in the
+ // surrounding context.
+ SmallVector<NamedDecl *, 0> DeclsInPrototype;
+ if (getCurScope()->getFlags() & Scope::FunctionDeclarationScope &&
+ !getLangOpts().CPlusPlus) {
+ for (Decl *D : getCurScope()->decls()) {
+ NamedDecl *ND = dyn_cast<NamedDecl>(D);
+ if (!ND || isa<ParmVarDecl>(ND))
+ continue;
+ DeclsInPrototype.push_back(ND);
+ }
+ }
+
// Remember that we parsed a function type, and remember the attributes.
D.AddTypeInfo(DeclaratorChunk::getFunction(HasProto,
IsAmbiguous,
@@ -5846,6 +5861,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
NoexceptExpr.isUsable() ?
NoexceptExpr.get() : nullptr,
ExceptionSpecTokens,
+ DeclsInPrototype,
StartLoc, LocalEndLoc, D,
TrailingReturnType),
FnAttrs, EndLoc);
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 4b0a83446e..caf2320f8f 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -2842,6 +2842,7 @@ ExprResult Parser::ParseBlockLiteralExpression() {
/*NumExceptions=*/0,
/*NoexceptExpr=*/nullptr,
/*ExceptionSpecTokens=*/nullptr,
+ /*DeclsInPrototype=*/None,
CaretLoc, CaretLoc,
ParamInfo),
attrs, CaretLoc);
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 83e6ae4ef5..cabc7b5266 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -1244,6 +1244,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
NoexceptExpr.isUsable() ?
NoexceptExpr.get() : nullptr,
/*ExceptionSpecTokens*/nullptr,
+ /*DeclsInPrototype=*/None,
LParenLoc, FunLocalRangeEnd, D,
TrailingReturnType),
Attr, DeclEndLoc);
@@ -1313,6 +1314,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
/*NumExceptions=*/0,
/*NoexceptExpr=*/nullptr,
/*ExceptionSpecTokens=*/nullptr,
+ /*DeclsInPrototype=*/None,
DeclLoc, DeclEndLoc, D,
TrailingReturnType),
Attr, DeclEndLoc);