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

Reply via email to