The attached patch fixes PR11797. The problem is that
Tracker.consumeClose will check what is after the '}'. If it is a
#pragma, it will be handled before ActOnFinishNamespaceDef.
This caused Sema to view the testcase in the PR as
namespace std __attribute__ ((__visibility__ ("default"))) {
#pragma GCC visibility push(default)
}
void foo() {
}
#pragma GCC visibility pop
This patch swaps the order of the calls, which unfortunately means that
we now have to call setRBraceLoc from outside Sema::ActOnFinishNamespaceDef.
Is the patch OK?
Cheers,
Rafael
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 31b5022..0ae96c2 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -2004,7 +2004,8 @@ private:
std::vector<SourceLocation>& NamespaceLoc,
unsigned int index, SourceLocation& InlineLoc,
ParsedAttributes& attrs,
- BalancedDelimiterTracker &Tracker);
+ BalancedDelimiterTracker &Tracker,
+ Decl *OuterNamespaceDecl);
Decl *ParseLinkage(ParsingDeclSpec &DS, unsigned Context);
Decl *ParseUsingDirectiveOrDeclaration(unsigned Context,
const ParsedTemplateInfo
&TemplateInfo,
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 238b0ed..d6dd70a 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -2724,7 +2724,7 @@ public:
IdentifierInfo *Ident,
SourceLocation LBrace,
AttributeList *AttrList);
- void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace);
+ void ActOnFinishNamespaceDef(Decl *Dcl);
NamespaceDecl *getStdNamespace() const;
NamespaceDecl *getOrCreateStdNamespace();
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index c31c55b..60c22e4 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -166,13 +166,12 @@ Decl *Parser::ParseNamespace(unsigned Context,
// Parse the contents of the namespace. This includes parsing recovery on
// any improperly nested namespaces.
ParseInnerNamespace(ExtraIdentLoc, ExtraIdent, ExtraNamespaceLoc, 0,
- InlineLoc, attrs, T);
+ InlineLoc, attrs, T, NamespcDecl);
// Leave the namespace scope.
NamespaceScope.Exit();
DeclEnd = T.getCloseLocation();
- Actions.ActOnFinishNamespaceDef(NamespcDecl, DeclEnd);
return NamespcDecl;
}
@@ -183,7 +182,8 @@ void
Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc,
std::vector<SourceLocation>& NamespaceLoc,
unsigned int index, SourceLocation& InlineLoc,
ParsedAttributes& attrs,
- BalancedDelimiterTracker &Tracker) {
+ BalancedDelimiterTracker &Tracker,
+ Decl *OuterNamespaceDecl) {
if (index == Ident.size()) {
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
ParsedAttributesWithRange attrs(AttrFactory);
@@ -192,10 +192,16 @@ void
Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc,
ParseExternalDeclaration(attrs);
}
+ // ActOnFinishNamespaceDef must come before consumeClose, as it can
+ // interfere with any #pragma just after the '}'
+ Actions.ActOnFinishNamespaceDef(OuterNamespaceDecl);
+
// The caller is what called check -- we are simply calling
// the close for it.
Tracker.consumeClose();
+ NamespaceDecl *Namespc = cast<NamespaceDecl>(OuterNamespaceDecl);
+ Namespc->setRBraceLoc(Tracker.getCloseLocation());
return;
}
@@ -208,11 +214,9 @@ void
Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc,
attrs.getList());
ParseInnerNamespace(IdentLoc, Ident, NamespaceLoc, ++index, InlineLoc,
- attrs, Tracker);
+ attrs, Tracker, NamespcDecl);
NamespaceScope.Exit();
-
- Actions.ActOnFinishNamespaceDef(NamespcDecl, Tracker.getCloseLocation());
}
/// ParseNamespaceAlias - Parse the part after the '=' in a namespace
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 9693c18..dc233c5 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -5731,10 +5731,9 @@ static inline NamespaceDecl *getNamespaceDecl(NamedDecl
*D) {
/// ActOnFinishNamespaceDef - This callback is called after a namespace is
/// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef.
-void Sema::ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace) {
+void Sema::ActOnFinishNamespaceDef(Decl *Dcl) {
NamespaceDecl *Namespc = dyn_cast_or_null<NamespaceDecl>(Dcl);
assert(Namespc && "Invalid parameter, expected NamespaceDecl");
- Namespc->setRBraceLoc(RBrace);
PopDeclContext();
if (Namespc->hasAttr<VisibilityAttr>())
PopPragmaVisibility();
diff --git a/test/CodeGenCXX/pr11797.cpp b/test/CodeGenCXX/pr11797.cpp
new file mode 100644
index 0000000..0727580
--- /dev/null
+++ b/test/CodeGenCXX/pr11797.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 %s -fvisibility hidden -emit-llvm -o - | FileCheck %s
+
+namespace std __attribute__ ((__visibility__ ("default"))) {}
+#pragma GCC visibility push(default)
+void foo() {
+}
+#pragma GCC visibility pop
+// CHECK: define void @_Z3foov()
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits