[cfe-commits] r126346 - in /cfe/trunk: include/clang/Sema/DeclSpec.h include/clang/Sema/Sema.h lib/Parse/ParseExprCXX.cpp lib/Sema/DeclSpec.cpp lib/Sema/SemaCXXScopeSpec.cpp lib/Sema/TreeTransform.h lib/Sema/TypeLocBuilder.h

Douglas Gregor dgregor at apple.com
Wed Feb 23 16:17:56 PST 2011


Author: dgregor
Date: Wed Feb 23 18:17:56 2011
New Revision: 126346

URL: http://llvm.org/viewvc/llvm-project?rev=126346&view=rev
Log:
Teach CXXScopeSpec to handle the extension of a nested-name-specifier
with another component in the nested-name-specifiers, updating its
representation (a NestedNameSpecifier) and source-location information
(currently a SourceRange) simultaneously. This is groundwork for
adding source-location information to nested-name-specifiers.


Modified:
    cfe/trunk/include/clang/Sema/DeclSpec.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/DeclSpec.cpp
    cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Sema/TypeLocBuilder.h

Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=126346&r1=126345&r2=126346&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Wed Feb 23 18:17:56 2011
@@ -29,9 +29,12 @@
 #include "llvm/Support/ErrorHandling.h"
 
 namespace clang {
+  class ASTContext;
+  class TypeLoc;
   class LangOptions;
   class Diagnostic;
   class IdentifierInfo;
+  class NamespaceDecl;
   class NestedNameSpecifier;
   class Preprocessor;
   class Declarator;
@@ -51,7 +54,7 @@
 class CXXScopeSpec {
   SourceRange Range;
   NestedNameSpecifier *ScopeRep;
-
+  
 public:
   CXXScopeSpec() : Range(), ScopeRep() { }
 
@@ -65,6 +68,54 @@
   NestedNameSpecifier *getScopeRep() const { return ScopeRep; }
   void setScopeRep(NestedNameSpecifier *S) { ScopeRep = S; }
 
+  /// \brief Extend the current nested-name-specifier by another
+  /// nested-name-specifier component of the form 'type::'.
+  ///
+  /// \param Context The AST context in which this nested-name-specifier
+  /// resides.
+  ///
+  /// \param TemplateKWLoc The location of the 'template' keyword, if present.
+  ///
+  /// \param TL The TypeLoc that describes the type preceding the '::'.
+  ///
+  /// \param ColonColonLoc The location of the trailing '::'.
+  void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL,
+              SourceLocation ColonColonLoc);
+
+  /// \brief Extend the current nested-name-specifier by another 
+  /// nested-name-specifier component of the form 'identifier::'.
+  ///
+  /// \param Context The AST context in which this nested-name-specifier
+  /// resides.
+  ///
+  /// \param Identifier The identifier.
+  ///
+  /// \param IdentifierLoc The location of the identifier.
+  ///
+  /// \param ColonColonLoc The location of the trailing '::'.
+  void Extend(ASTContext &Context, IdentifierInfo *Identifier,
+              SourceLocation IdentifierLoc, SourceLocation ColonColonLoc);
+
+  /// \brief Extend the current nested-name-specifier by another 
+  /// nested-name-specifier component of the form 'namespace-or-alias::'.
+  ///
+  /// \param Context The AST context in which this nested-name-specifier
+  /// resides.
+  ///
+  /// \param Namespace The namespace.
+  /// FIXME: This should also permit a namespace alias.
+  ///
+  /// \param NamespaceLoc The location of the namespace or namespace alias 
+  /// name.
+  ///
+  /// \param ColonColonLoc The location of the trailing '::'.
+  void Extend(ASTContext &Context, NamespaceDecl *Namespace,
+              SourceLocation NamespaceLoc, SourceLocation ColonColonLoc);
+
+  /// \brief Turn this (empty) nested-name-specifier into the global
+  /// nested-name-specifier '::'.
+  void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
+  
   /// No scope specifier.
   bool isEmpty() const { return !Range.isValid(); }
   /// A scope specifier is present, but may be valid or invalid.
@@ -75,6 +126,15 @@
   /// A scope specifier is present, and it refers to a real scope.
   bool isValid() const { return isNotEmpty() && ScopeRep != 0; }
 
+  /// \brief Indicate that this nested-name-specifier is invalid.
+  void SetInvalid(SourceRange R) { 
+    assert(R.isValid() && "Must have a valid source range");
+    if (Range.getBegin().isInvalid())
+      Range.setBegin(R.getBegin());
+    Range.setEnd(R.getEnd());
+    ScopeRep = 0;
+  }
+  
   /// Deprecated.  Some call sites intend isNotEmpty() while others intend
   /// isValid().
   bool isSet() const { return ScopeRep != 0; }

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=126346&r1=126345&r2=126346&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Feb 23 18:17:56 2011
@@ -2591,11 +2591,19 @@
   CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS);
   bool isUnknownSpecialization(const CXXScopeSpec &SS);
 
-  /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
-  /// global scope ('::').
-  NestedNameSpecifier *
-  ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc);
-
+  /// \brief The parser has parsed a global nested-name-specifier '::'.
+  ///
+  /// \param S The scope in which this nested-name-specifier occurs.
+  ///
+  /// \param CCLoc The location of the '::'.
+  ///
+  /// \param SS The nested-name-specifier, which will be updated in-place
+  /// to reflect the parsed nested-name-specifier.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc,
+                                    CXXScopeSpec &SS);
+  
   bool isAcceptableNestedNameSpecifier(NamedDecl *SD);
   NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
 
@@ -2604,42 +2612,72 @@
                                     IdentifierInfo &II,
                                     ParsedType ObjectType);
 
-  NestedNameSpecifier *BuildCXXNestedNameSpecifier(Scope *S,
-                                                   CXXScopeSpec &SS,
-                                                   SourceLocation IdLoc,
-                                                   SourceLocation CCLoc,
-                                                   IdentifierInfo &II,
-                                                   QualType ObjectType,
-                                                   NamedDecl *ScopeLookupResult,
-                                                   bool EnteringContext,
-                                                   bool ErrorRecoveryLookup);
-
-  NestedNameSpecifier *ActOnCXXNestedNameSpecifier(Scope *S,
-                                                   CXXScopeSpec &SS,
-                                                   SourceLocation IdLoc,
-                                                   SourceLocation CCLoc,
-                                                   IdentifierInfo &II,
-                                                   ParsedType ObjectType,
-                                                   bool EnteringContext);
+  bool BuildCXXNestedNameSpecifier(Scope *S,
+                                   IdentifierInfo &Identifier,
+                                   SourceLocation IdentifierLoc,
+                                   SourceLocation CCLoc,
+                                   QualType ObjectType,
+                                   bool EnteringContext,
+                                   CXXScopeSpec &SS,
+                                   NamedDecl *ScopeLookupResult,
+                                   bool ErrorRecoveryLookup);
+
+  /// \brief The parser has parsed a nested-name-specifier 'identifier::'.
+  ///
+  /// \param S The scope in which this nested-name-specifier occurs.
+  ///
+  /// \param Identifier The identifier preceding the '::'.
+  ///
+  /// \param IdentifierLoc The location of the identifier.
+  ///
+  /// \param CCLoc The location of the '::'.
+  ///
+  /// \param ObjectType The type of the object, if we're parsing 
+  /// nested-name-specifier in a member access expression.
+  ///
+  /// \param EnteringContext Whether we're entering the context nominated by
+  /// this nested-name-specifier.
+  ///
+  /// \param SS The nested-name-specifier, which is both an input
+  /// parameter (the nested-name-specifier before this type) and an
+  /// output parameter (containing the full nested-name-specifier,
+  /// including this new type).
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool ActOnCXXNestedNameSpecifier(Scope *S,
+                                   IdentifierInfo &Identifier,
+                                   SourceLocation IdentifierLoc,
+                                   SourceLocation CCLoc,
+                                   ParsedType ObjectType,
+                                   bool EnteringContext,
+                                   CXXScopeSpec &SS);
 
   bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
-                                 IdentifierInfo &II,
+                                 IdentifierInfo &Identifier,
+                                 SourceLocation IdentifierLoc,
+                                 SourceLocation ColonLoc,
                                  ParsedType ObjectType,
                                  bool EnteringContext);
 
-  /// ActOnCXXNestedNameSpecifier - Called during parsing of a
-  /// nested-name-specifier that involves a template-id, e.g.,
-  /// "foo::bar<int, float>::", and now we need to build a scope
-  /// specifier. \p SS is empty or the previously parsed nested-name
-  /// part ("foo::"), \p Type is the already-parsed class template
-  /// specialization (or other template-id that names a type), \p
-  /// TypeRange is the source range where the type is located, and \p
-  /// CCLoc is the location of the trailing '::'.
-  CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S,
-                                          const CXXScopeSpec &SS,
-                                          ParsedType Type,
-                                          SourceRange TypeRange,
-                                          SourceLocation CCLoc);
+  /// \brief The parser has parsed a nested-name-specifier 'type::'.
+  ///
+  /// \param S The scope in which this nested-name-specifier occurs.
+  ///
+  /// \param Type The type, which will be a template specialization
+  /// type, preceding the '::'.
+  ///
+  /// \param CCLoc The location of the '::'.
+  ///
+  /// \param SS The nested-name-specifier, which is both an input
+  /// parameter (the nested-name-specifier before this type) and an
+  /// output parameter (containing the full nested-name-specifier,
+  /// including this new type).
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool ActOnCXXNestedNameSpecifier(Scope *S,
+                                   ParsedType Type,
+                                   SourceLocation CCLoc,
+                                   CXXScopeSpec &SS);
 
   bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
 

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=126346&r1=126345&r2=126346&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Wed Feb 23 18:17:56 2011
@@ -80,10 +80,9 @@
       return false;
 
     // '::' - Global scope qualifier.
-    SourceLocation CCLoc = ConsumeToken();
-    SS.setBeginLoc(CCLoc);
-    SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(getCurScope(), CCLoc));
-    SS.setEndLoc(CCLoc);
+    if (Actions.ActOnCXXGlobalScopeSpecifier(getCurScope(), ConsumeToken(), SS))
+      return true;
+    
     HasScopeSpecifier = true;
   }
 
@@ -214,14 +213,14 @@
         }
 
         if (ParsedType T = getTypeAnnotation(TypeToken)) {
-          CXXScopeTy *Scope =
-            Actions.ActOnCXXNestedNameSpecifier(getCurScope(), SS, T,
-                                                TypeToken.getAnnotationRange(),
-                                                CCLoc);
-          SS.setScopeRep(Scope);
-        } else
-          SS.setScopeRep(0);
-        SS.setEndLoc(CCLoc);
+          if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), T, CCLoc, SS))
+            SS.SetInvalid(SourceRange(SS.getBeginLoc(), CCLoc));
+          
+          continue;
+        } else {
+          SS.SetInvalid(SourceRange(SS.getBeginLoc(), CCLoc));
+        }
+        
         continue;
       }
 
@@ -245,7 +244,9 @@
     // If we get foo:bar, this is almost certainly a typo for foo::bar.  Recover
     // and emit a fixit hint for it.
     if (Next.is(tok::colon) && !ColonIsSacred) {
-      if (Actions.IsInvalidUnlessNestedName(getCurScope(), SS, II, ObjectType, 
+      if (Actions.IsInvalidUnlessNestedName(getCurScope(), SS, II, 
+                                            Tok.getLocation(), 
+                                            Next.getLocation(), ObjectType,
                                             EnteringContext) &&
           // If the token after the colon isn't an identifier, it's still an
           // error, but they probably meant something else strange so don't
@@ -274,16 +275,11 @@
              "NextToken() not working properly!");
       SourceLocation CCLoc = ConsumeToken();
 
-      if (!HasScopeSpecifier) {
-        SS.setBeginLoc(IdLoc);
-        HasScopeSpecifier = true;
-      }
-
-      if (!SS.isInvalid())
-        SS.setScopeRep(
-            Actions.ActOnCXXNestedNameSpecifier(getCurScope(), SS, IdLoc, CCLoc, II,
-                                                ObjectType, EnteringContext));
-      SS.setEndLoc(CCLoc);
+      HasScopeSpecifier = true;
+      if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), II, IdLoc, CCLoc,
+                                              ObjectType, EnteringContext, SS))
+        SS.SetInvalid(SourceRange(IdLoc, CCLoc));
+      
       continue;
     }
 

Modified: cfe/trunk/lib/Sema/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=126346&r1=126345&r2=126346&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/DeclSpec.cpp (original)
+++ cfe/trunk/lib/Sema/DeclSpec.cpp Wed Feb 23 18:17:56 2011
@@ -14,6 +14,8 @@
 #include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency!
 #include "clang/Sema/DeclSpec.h"
 #include "clang/Sema/ParsedTemplate.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/TypeLoc.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Basic/LangOptions.h"
 #include "llvm/ADT/STLExtras.h"
@@ -44,6 +46,41 @@
   EndLocation = TemplateId->RAngleLoc;
 }
 
+void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc, 
+                          TypeLoc TL, SourceLocation ColonColonLoc) {
+  ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, 
+                                         TemplateKWLoc.isValid(), 
+                                         TL.getTypePtr());
+  if (Range.getBegin().isInvalid())
+    Range.setBegin(TL.getBeginLoc());
+  Range.setEnd(ColonColonLoc);
+}
+
+void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier,
+                          SourceLocation IdentifierLoc, 
+                          SourceLocation ColonColonLoc) {
+  ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Identifier);
+  if (Range.getBegin().isInvalid())
+    Range.setBegin(IdentifierLoc);
+  Range.setEnd(ColonColonLoc);
+}
+
+void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace,
+                          SourceLocation NamespaceLoc, 
+                          SourceLocation ColonColonLoc) {
+  ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Namespace);
+  if (Range.getBegin().isInvalid())
+    Range.setBegin(NamespaceLoc);
+  Range.setEnd(ColonColonLoc);
+}
+
+void CXXScopeSpec::MakeGlobal(ASTContext &Context, 
+                              SourceLocation ColonColonLoc) {
+  assert(!ScopeRep && "Already have a nested-name-specifier!?");
+  ScopeRep = NestedNameSpecifier::GlobalSpecifier(Context);
+  Range = SourceRange(ColonColonLoc);
+}
+
 /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
 /// "TheDeclarator" is the declarator that this will be added to.
 DeclaratorChunk DeclaratorChunk::getFunction(const ParsedAttributes &attrs,

Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=126346&r1=126345&r2=126346&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Wed Feb 23 18:17:56 2011
@@ -19,6 +19,7 @@
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/Basic/PartialDiagnostic.h"
 #include "clang/Sema/DeclSpec.h"
+#include "TypeLocBuilder.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/raw_ostream.h"
 using namespace clang;
@@ -219,7 +220,7 @@
                             Context.getTypeDeclType(Tag),
                             PDiag(diag::err_incomplete_nested_name_spec)
                               << SS.getRange())) {
-      SS.setScopeRep(0);  // Mark the ScopeSpec invalid.
+      SS.SetInvalid(SS.getRange());
       return true;
     }
   }
@@ -227,11 +228,10 @@
   return false;
 }
 
-/// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
-/// global scope ('::').
-Sema::CXXScopeTy *Sema::ActOnCXXGlobalScopeSpecifier(Scope *S,
-                                                     SourceLocation CCLoc) {
-  return NestedNameSpecifier::GlobalSpecifier(Context);
+bool Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc,
+                                        CXXScopeSpec &SS) {
+  SS.MakeGlobal(Context, CCLoc);
+  return false;
 }
 
 /// \brief Determines whether the given declaration is an valid acceptable
@@ -352,22 +352,21 @@
 ///
 /// If ErrorRecoveryLookup is true, then this call is used to improve error
 /// recovery.  This means that it should not emit diagnostics, it should
-/// just return null on failure.  It also means it should only return a valid
+/// just return true on failure.  It also means it should only return a valid
 /// scope if it *knows* that the result is correct.  It should not return in a
-/// dependent context, for example.
-Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
-                                                    CXXScopeSpec &SS,
-                                                    SourceLocation IdLoc,
-                                                    SourceLocation CCLoc,
-                                                    IdentifierInfo &II,
-                                                    QualType ObjectType,
-                                                  NamedDecl *ScopeLookupResult,
-                                                    bool EnteringContext,
-                                                    bool ErrorRecoveryLookup) {
-  NestedNameSpecifier *Prefix
-    = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
-
-  LookupResult Found(*this, &II, IdLoc, LookupNestedNameSpecifierName);
+/// dependent context, for example. Nor will it extend \p SS with the scope
+/// specifier.
+bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
+                                       IdentifierInfo &Identifier,
+                                       SourceLocation IdentifierLoc,
+                                       SourceLocation CCLoc,
+                                       QualType ObjectType,
+                                       bool EnteringContext,
+                                       CXXScopeSpec &SS,
+                                       NamedDecl *ScopeLookupResult,
+                                       bool ErrorRecoveryLookup) {
+  LookupResult Found(*this, &Identifier, IdentifierLoc, 
+                     LookupNestedNameSpecifierName);
 
   // Determine where to perform name lookup
   DeclContext *LookupCtx = 0;
@@ -397,7 +396,7 @@
     // The declaration context must be complete.
     if (!LookupCtx->isDependentContext() &&
         RequireCompleteDeclContext(SS, LookupCtx))
-      return 0;
+      return true;
 
     LookupQualifiedName(Found, LookupCtx);
 
@@ -442,16 +441,14 @@
          !cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()))) {
     // Don't speculate if we're just trying to improve error recovery.
     if (ErrorRecoveryLookup)
-      return 0;
+      return true;
     
     // We were not able to compute the declaration context for a dependent
     // base object type or prior nested-name-specifier, so this
     // nested-name-specifier refers to an unknown specialization. Just build
     // a dependent nested-name-specifier.
-    if (!Prefix)
-      return NestedNameSpecifier::Create(Context, &II);
-
-    return NestedNameSpecifier::Create(Context, Prefix, &II);
+    SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc);
+    return false;
   } 
   
   // FIXME: Deal with ambiguities cleanly.
@@ -480,7 +477,7 @@
           << ND->getDeclName();
     } else {
       Found.clear();
-      Found.setLookupName(&II);
+      Found.setLookupName(&Identifier);
     }
   }
 
@@ -497,7 +494,8 @@
       // scope, reconstruct the result from the template instantiation itself.
       NamedDecl *OuterDecl;
       if (S) {
-        LookupResult FoundOuter(*this, &II, IdLoc, LookupNestedNameSpecifierName);
+        LookupResult FoundOuter(*this, &Identifier, IdentifierLoc, 
+                                LookupNestedNameSpecifierName);
         LookupName(FoundOuter, S);
         OuterDecl = FoundOuter.getAsSingle<NamedDecl>();
       } else
@@ -509,39 +507,75 @@
            !Context.hasSameType(
                             Context.getTypeDeclType(cast<TypeDecl>(OuterDecl)),
                                Context.getTypeDeclType(cast<TypeDecl>(SD))))) {
-             if (ErrorRecoveryLookup)
-               return 0;
-             
-             Diag(IdLoc, diag::err_nested_name_member_ref_lookup_ambiguous)
-               << &II;
-             Diag(SD->getLocation(), diag::note_ambig_member_ref_object_type)
-               << ObjectType;
-             Diag(OuterDecl->getLocation(), diag::note_ambig_member_ref_scope);
-
-             // Fall through so that we'll pick the name we found in the object
-             // type, since that's probably what the user wanted anyway.
-           }
+         if (ErrorRecoveryLookup)
+           return true;
+
+         Diag(IdentifierLoc, 
+              diag::err_nested_name_member_ref_lookup_ambiguous)
+           << &Identifier;
+         Diag(SD->getLocation(), diag::note_ambig_member_ref_object_type)
+           << ObjectType;
+         Diag(OuterDecl->getLocation(), diag::note_ambig_member_ref_scope);
+
+         // Fall through so that we'll pick the name we found in the object
+         // type, since that's probably what the user wanted anyway.
+       }
     }
 
-    if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD))
-      return NestedNameSpecifier::Create(Context, Prefix, Namespace);
+    // If we're just performing this lookup for error-recovery purposes, 
+    // don't extend the nested-name-specifier. Just return now.
+    if (ErrorRecoveryLookup)
+      return false;
+    
+    if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD)) {
+      SS.Extend(Context, Namespace, IdentifierLoc, CCLoc);
+      return false;
+    }
 
     // FIXME: It would be nice to maintain the namespace alias name, then
     // see through that alias when resolving the nested-name-specifier down to
     // a declaration context.
-    if (NamespaceAliasDecl *Alias = dyn_cast<NamespaceAliasDecl>(SD))
-      return NestedNameSpecifier::Create(Context, Prefix,
-                                         Alias->getNamespace());
+    if (NamespaceAliasDecl *Alias = dyn_cast<NamespaceAliasDecl>(SD)) {
+      SS.Extend(Context, Alias->getNamespace(), IdentifierLoc, CCLoc);
+      return false;
+    }
 
     QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD));
-    return NestedNameSpecifier::Create(Context, Prefix, false,
-                                       T.getTypePtr());
+    TypeLocBuilder TLB;
+    if (isa<InjectedClassNameType>(T)) {
+      InjectedClassNameTypeLoc InjectedTL
+        = TLB.push<InjectedClassNameTypeLoc>(T);
+      InjectedTL.setNameLoc(IdentifierLoc);
+    } else if (isa<RecordDecl>(SD)) {
+      RecordTypeLoc RecordTL = TLB.push<RecordTypeLoc>(T);
+      RecordTL.setNameLoc(IdentifierLoc);
+    } else if (isa<TypedefDecl>(SD)) {
+      TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(T);
+      TypedefTL.setNameLoc(IdentifierLoc);
+    } else if (isa<EnumDecl>(SD)) {
+      EnumTypeLoc EnumTL = TLB.push<EnumTypeLoc>(T);
+      EnumTL.setNameLoc(IdentifierLoc);
+    } else if (isa<TemplateTypeParmDecl>(SD)) {
+      TemplateTypeParmTypeLoc TemplateTypeTL
+        = TLB.push<TemplateTypeParmTypeLoc>(T);
+      TemplateTypeTL.setNameLoc(IdentifierLoc);
+    } else {
+      assert(isa<UnresolvedUsingTypenameDecl>(SD) && 
+             "Unhandled TypeDecl node in nested-name-specifier");
+      UnresolvedUsingTypeLoc UnresolvedTL
+        = TLB.push<UnresolvedUsingTypeLoc>(T);
+      UnresolvedTL.setNameLoc(IdentifierLoc);
+    }
+
+    SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T),
+              CCLoc);
+    return false;
   }
 
   // Otherwise, we have an error case.  If we don't want diagnostics, just
   // return an error now.
   if (ErrorRecoveryLookup)
-    return 0;
+    return true;
 
   // If we didn't find anything during our lookup, try again with
   // ordinary name lookup, which can help us produce better error
@@ -555,36 +589,34 @@
   if (!Found.empty())
     DiagID = diag::err_expected_class_or_namespace;
   else if (SS.isSet()) {
-    Diag(IdLoc, diag::err_no_member) << &II << LookupCtx << SS.getRange();
-    return 0;
+    Diag(IdentifierLoc, diag::err_no_member) 
+      << &Identifier << LookupCtx << SS.getRange();
+    return true;
   } else
     DiagID = diag::err_undeclared_var_use;
 
   if (SS.isSet())
-    Diag(IdLoc, DiagID) << &II << SS.getRange();
+    Diag(IdentifierLoc, DiagID) << &Identifier << SS.getRange();
   else
-    Diag(IdLoc, DiagID) << &II;
+    Diag(IdentifierLoc, DiagID) << &Identifier;
 
-  return 0;
+  return true;
 }
 
-/// ActOnCXXNestedNameSpecifier - Called during parsing of a
-/// nested-name-specifier. e.g. for "foo::bar::" we parsed "foo::" and now
-/// we want to resolve "bar::". 'SS' is empty or the previously parsed
-/// nested-name part ("foo::"), 'IdLoc' is the source location of 'bar',
-/// 'CCLoc' is the location of '::' and 'II' is the identifier for 'bar'.
-/// Returns a CXXScopeTy* object representing the C++ scope.
-Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
-                                                    CXXScopeSpec &SS,
-                                                    SourceLocation IdLoc,
-                                                    SourceLocation CCLoc,
-                                                    IdentifierInfo &II,
-                                                    ParsedType ObjectTypePtr,
-                                                    bool EnteringContext) {
-  return BuildCXXNestedNameSpecifier(S, SS, IdLoc, CCLoc, II,
-                                     GetTypeFromParser(ObjectTypePtr),
-                                     /*ScopeLookupResult=*/0, EnteringContext,
-                                     false);
+bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
+                                       IdentifierInfo &Identifier,
+                                       SourceLocation IdentifierLoc,
+                                       SourceLocation CCLoc,
+                                       ParsedType ObjectType,
+                                       bool EnteringContext,
+                                       CXXScopeSpec &SS) {
+  if (SS.isInvalid())
+    return true;
+  
+  return BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, CCLoc,
+                                     GetTypeFromParser(ObjectType),
+                                     EnteringContext, SS, 
+                                     /*ScopeLookupResult=*/0, false);
 }
 
 /// IsInvalidUnlessNestedName - This method is used for error recovery
@@ -594,23 +626,36 @@
 ///
 /// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier.
 bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
-                                     IdentifierInfo &II, ParsedType ObjectType,
+                                     IdentifierInfo &Identifier, 
+                                     SourceLocation IdentifierLoc,
+                                     SourceLocation ColonLoc,
+                                     ParsedType ObjectType,
                                      bool EnteringContext) {
-  return BuildCXXNestedNameSpecifier(S, SS, SourceLocation(), SourceLocation(),
-                                     II, GetTypeFromParser(ObjectType),
-                                     /*ScopeLookupResult=*/0, EnteringContext,
-                                     true);
+  if (SS.isInvalid())
+    return false;
+  
+  return !BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, ColonLoc,
+                                      GetTypeFromParser(ObjectType),
+                                      EnteringContext, SS, 
+                                      /*ScopeLookupResult=*/0, true);
 }
 
-Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
-                                                    const CXXScopeSpec &SS,
-                                                    ParsedType Ty,
-                                                    SourceRange TypeRange,
-                                                    SourceLocation CCLoc) {
-  NestedNameSpecifier *Prefix = SS.getScopeRep();
-  QualType T = GetTypeFromParser(Ty);
-  return NestedNameSpecifier::Create(Context, Prefix, /*FIXME:*/false,
-                                     T.getTypePtr());
+bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
+                                       ParsedType Type,
+                                       SourceLocation CCLoc,
+                                       CXXScopeSpec &SS) {
+  if (SS.isInvalid())
+    return true;
+  
+  TypeSourceInfo *TSInfo;
+  QualType T = GetTypeFromParser(Type, &TSInfo);
+  if (T.isNull())
+    return true;
+
+  assert(TSInfo && "Not TypeSourceInfo in nested-name-specifier?");
+  // FIXME: location of the 'template' keyword?
+  SS.Extend(Context, SourceLocation(), TSInfo->getTypeLoc(), CCLoc);
+  return false;
 }
 
 bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=126346&r1=126345&r2=126346&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Wed Feb 23 18:17:56 2011
@@ -7559,12 +7559,14 @@
   // FIXME: The source location information is all wrong.
   SS.setRange(Range);
   SS.setScopeRep(Prefix);
-  return static_cast<NestedNameSpecifier *>(
-                    SemaRef.BuildCXXNestedNameSpecifier(0, SS, Range.getEnd(),
-                                                        Range.getEnd(), II,
-                                                        ObjectType,
-                                                        FirstQualifierInScope,
-                                                        false, false));
+  if (SemaRef.BuildCXXNestedNameSpecifier(0, II, /*FIXME:*/Range.getBegin(),
+                                          /*FIXME:*/Range.getEnd(),
+                                          ObjectType, false,
+                                          SS, FirstQualifierInScope,
+                                          false))
+    return 0;
+  
+  return SS.getScopeRep();
 }
 
 template<typename Derived>

Modified: cfe/trunk/lib/Sema/TypeLocBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TypeLocBuilder.h?rev=126346&r1=126345&r2=126346&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TypeLocBuilder.h (original)
+++ cfe/trunk/lib/Sema/TypeLocBuilder.h Wed Feb 23 18:17:56 2011
@@ -107,6 +107,19 @@
     return DI;
   }
 
+  /// \brief Copies the type-location information to the given AST context and 
+  /// returns a \c TypeLoc referring into the AST context.
+  TypeLoc getTypeLocInContext(ASTContext &Context, QualType T) {
+#ifndef NDEBUG
+    assert(T == LastTy && "type doesn't match last type pushed!");
+#endif
+    
+    size_t FullDataSize = Capacity - Index;
+    void *Mem = Context.Allocate(FullDataSize);
+    memcpy(Mem, &Buffer[Index], FullDataSize);
+    return TypeLoc(T, Mem);
+  }
+
 private:
   TypeLoc pushImpl(QualType T, size_t LocalSize) {
 #ifndef NDEBUG





More information about the cfe-commits mailing list