]> granicus.if.org Git - clang/commitdiff
Tighten up the conditions under which we consider ourselves to be
authorDouglas Gregor <dgregor@apple.com>
Mon, 7 Nov 2011 17:33:42 +0000 (17:33 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 7 Nov 2011 17:33:42 +0000 (17:33 +0000)
entering the context of a nested-name-specifier. Fixes
<rdar://problem/10397846>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143967 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Parser.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
lib/Parse/ParseExpr.cpp
lib/Parse/ParseExprCXX.cpp
lib/Parse/Parser.cpp
test/SemaTemplate/instantiate-member-class.cpp

index 673b5df0933551fc36ad93b31cf107e3030ff90c..dba7ffb4788005febe360e513a391ba0d732138b 100644 (file)
@@ -1997,6 +1997,7 @@ private:
                            DeclSpec &DS,
                 const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
                            AccessSpecifier AS = AS_none,
+                           bool EnteringContext = false,
                            bool SuppressDeclarations = false);
   void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
                                    Decl *TagDecl);
index 07a52586e9f8ec772f07c5f943c453b4d5f2de84..3bddd3de13d06a49389aca61a76fa6ef3eb0b061 100644 (file)
@@ -1652,6 +1652,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
     DS.SetRangeEnd(Tok.getLocation());
   }
   
+  bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level);
   while (1) {
     bool isInvalid = false;
     const char *PrevSpec = 0;
@@ -2208,7 +2209,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
     case tok::kw_union: {
       tok::TokenKind Kind = Tok.getKind();
       ConsumeToken();
-      ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS);
+      ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS, EnteringContext);
       continue;
     }
 
@@ -2500,6 +2501,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
     tok::TokenKind Kind = Tok.getKind();
     ConsumeToken();
     ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS_none,
+                        /*EnteringContext=*/false,
                         SuppressDeclarations);
     return true;
   }
@@ -2862,7 +2864,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
     // if a fixed underlying type is allowed.
     ColonProtectionRAIIObject X(*this, AllowFixedUnderlyingType);
     
-    if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false))
+    if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), 
+                                       /*EnteringContext=*/false))
       return;
 
     if (SS.isSet() && Tok.isNot(tok::identifier)) {
@@ -3483,7 +3486,8 @@ bool Parser::isConstructorDeclarator() {
 
   // Parse the C++ scope specifier.
   CXXScopeSpec SS;
-  if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), true)) {
+  if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), 
+                                     /*EnteringContext=*/true)) {
     TPA.Revert();
     return false;
   }
@@ -3681,8 +3685,10 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
   if (getLang().CPlusPlus &&
       (Tok.is(tok::coloncolon) || Tok.is(tok::identifier) ||
        Tok.is(tok::annot_cxxscope))) {
+    bool EnteringContext = D.getContext() == Declarator::FileContext ||
+                           D.getContext() == Declarator::MemberContext;
     CXXScopeSpec SS;
-    ParseOptionalCXXScopeSpecifier(SS, ParsedType(), true); // ignore fail
+    ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext);
 
     if (SS.isNotEmpty()) {
       if (Tok.isNot(tok::star)) {
@@ -3848,7 +3854,10 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
   if (getLang().CPlusPlus && D.mayHaveIdentifier()) {
     // ParseDeclaratorInternal might already have parsed the scope.
     if (D.getCXXScopeSpec().isEmpty()) {
-      ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), ParsedType(), true);
+      bool EnteringContext = D.getContext() == Declarator::FileContext ||
+                             D.getContext() == Declarator::MemberContext;
+      ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), ParsedType(), 
+                                     EnteringContext);
     }
 
     if (D.getCXXScopeSpec().isValid()) {
index 1ba1cbfbd66df06c78c7b64f6337ef9cdc4b86ac..721d185f5392d8713c9e789f58dae0e3f09291c4 100644 (file)
@@ -234,7 +234,7 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
 
   CXXScopeSpec SS;
   // Parse (optional) nested-name-specifier.
-  ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+  ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
 
   if (SS.isInvalid() || Tok.isNot(tok::identifier)) {
     Diag(Tok, diag::err_expected_namespace_name);
@@ -382,7 +382,7 @@ Decl *Parser::ParseUsingDirective(unsigned Context,
 
   CXXScopeSpec SS;
   // Parse (optional) nested-name-specifier.
-  ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+  ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
 
   IdentifierInfo *NamespcName = 0;
   SourceLocation IdentLoc = SourceLocation();
@@ -450,7 +450,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
     IsTypeName = false;
 
   // Parse nested-name-specifier.
-  ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+  ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
 
   // Check nested-name specifier.
   if (SS.isInvalid()) {
@@ -876,7 +876,9 @@ Parser::TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
 void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
                                  SourceLocation StartLoc, DeclSpec &DS,
                                  const ParsedTemplateInfo &TemplateInfo,
-                                 AccessSpecifier AS, bool SuppressDeclarations){
+                                 AccessSpecifier AS, 
+                                 bool EnteringContext,
+                                 bool SuppressDeclarations){
   DeclSpec::TST TagType;
   if (TagTokKind == tok::kw_struct)
     TagType = DeclSpec::TST_struct;
@@ -955,7 +957,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
     // "FOO : BAR" is not a potential typo for "FOO::BAR".
     ColonProtectionRAIIObject X(*this);
 
-    if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), true))
+    if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext))
       DS.SetTypeSpecError();
     if (SS.isSet())
       if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
@@ -1637,7 +1639,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
     if (isAccessDecl) {
       // Collect the scope specifier token we annotated earlier.
       CXXScopeSpec SS;
-      ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+      ParseOptionalCXXScopeSpecifier(SS, ParsedType(), 
+                                     /*EnteringContext=*/false);
 
       // Try to parse an unqualified-id.
       UnqualifiedId Name;
@@ -2335,7 +2338,7 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) {
 Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
   // parse '::'[opt] nested-name-specifier[opt]
   CXXScopeSpec SS;
-  ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+  ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
   ParsedType TemplateTypeTy;
   if (Tok.is(tok::annot_template_id)) {
     TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
index f77d8eaf2a18f39b714459040dcede77cbee94c6..4b8fd76269abef71560e2f57aa393b748b6f0c75 100644 (file)
@@ -974,7 +974,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
         // type, translate it into a type and continue parsing as a
         // cast expression.
         CXXScopeSpec SS;
-        ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+        ParseOptionalCXXScopeSpecifier(SS, ParsedType(), 
+                                       /*EnteringContext=*/false);
         AnnotateTemplateIdTokenAsType();
         return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
                                    NotCastExpr, isTypeCast);
@@ -1333,7 +1334,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
         if (LHS.isInvalid())
           break;
 
-        ParseOptionalCXXScopeSpecifier(SS, ObjectType, false,
+        ParseOptionalCXXScopeSpecifier(SS, ObjectType, 
+                                       /*EnteringContext=*/false,
                                        &MayBePseudoDestructor);
         if (SS.isNotEmpty())
           ObjectType = ParsedType();
index 2bfb6158739fee9806d1ae06c01c4cb68403610f..dfc77e17d4959362f86fc1ba095cbd9db009868a 100644 (file)
@@ -487,7 +487,7 @@ ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
   //   '::' unqualified-id
   //
   CXXScopeSpec SS;
-  ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+  ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
   
   UnqualifiedId Name;
   if (ParseUnqualifiedId(SS, 
index fabb8e2a594a72b1376f8ec3df556033a3bf1eb3..6e84e429684694f1aba57dc203f00e0dc61040c2 100644 (file)
@@ -1205,7 +1205,8 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) {
     //            simple-template-id
     SourceLocation TypenameLoc = ConsumeToken();
     CXXScopeSpec SS;
-    if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/ParsedType(), false,
+    if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/ParsedType(), 
+                                       /*EnteringContext=*/false,
                                        0, /*IsTypename*/true))
       return true;
     if (!SS.isSet()) {
@@ -1484,7 +1485,8 @@ bool Parser::ParseMicrosoftIfExistsCondition(IfExistsCondition& Result) {
   }
   
   // Parse nested-name-specifier.
-  ParseOptionalCXXScopeSpecifier(Result.SS, ParsedType(), false);
+  ParseOptionalCXXScopeSpecifier(Result.SS, ParsedType(), 
+                                 /*EnteringContext=*/false);
 
   // Check nested-name specifier.
   if (Result.SS.isInvalid()) {
index c67eb4022a47b8fabd5d0f6982092345081232df..bb6427670c3ee733d649e52513a6bd5a188532ba 100644 (file)
@@ -118,3 +118,25 @@ namespace AliasTagDef {
   int m = F<int>::S().g();
   int n = F<int>::U().g();
 }
+
+namespace rdar10397846 {
+  template<int I> struct A
+  {
+    struct B
+    {
+      struct C { C() { int *ptr = I; } }; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}}
+    };
+  };
+
+  template<int N> void foo()
+  {
+    class A<N>::B::C X; // expected-note{{in instantiation of member function}}
+    int A<N+1>::B::C::*member = 0;
+  }
+
+  void bar()
+  {
+    foo<0>();
+    foo<1>(); // expected-note{{in instantiation of function template}}
+  }
+}