[cfe-commits] r126391 - in /cfe/trunk: include/clang/AST/NestedNameSpecifier.h include/clang/Sema/DeclSpec.h include/clang/Sema/ParsedTemplate.h include/clang/Sema/Sema.h lib/AST/NestedNameSpecifier.cpp lib/Parse/ParseDecl.cpp lib/Parse/ParseExprCXX.cpp lib/Parse/ParseTemplate.cpp lib/Parse/Parser.cpp lib/Sema/DeclSpec.cpp lib/Sema/SemaCXXScopeSpec.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp lib/Sema/TreeTransform.h

Douglas Gregor dgregor at apple.com
Thu Feb 24 09:54:51 PST 2011


Author: dgregor
Date: Thu Feb 24 11:54:50 2011
New Revision: 126391

URL: http://llvm.org/viewvc/llvm-project?rev=126391&view=rev
Log:
Retain complete source-location information for C++
nested-name-specifiers throughout the parser, and provide a new class
(NestedNameSpecifierLoc) that contains a nested-name-specifier along
with its type-source information.

Right now, this information is completely useless, because we don't
actually store the source-location information anywhere in the
AST. Call this Step 1/N.

Modified:
    cfe/trunk/include/clang/AST/NestedNameSpecifier.h
    cfe/trunk/include/clang/Sema/DeclSpec.h
    cfe/trunk/include/clang/Sema/ParsedTemplate.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/NestedNameSpecifier.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Parse/ParseTemplate.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/DeclSpec.cpp
    cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Sema/TreeTransform.h

Modified: cfe/trunk/include/clang/AST/NestedNameSpecifier.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/NestedNameSpecifier.h?rev=126391&r1=126390&r2=126391&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/NestedNameSpecifier.h (original)
+++ cfe/trunk/include/clang/AST/NestedNameSpecifier.h Thu Feb 24 11:54:50 2011
@@ -203,6 +203,76 @@
   void dump(const LangOptions &LO);
 };
 
+/// \brief A C++ nested-name-specifier augmented with source location
+/// information.
+class NestedNameSpecifierLoc {
+  NestedNameSpecifier *Qualifier;
+  void *Data;
+
+  /// \brief Determines the data length for the last component in the
+  /// given nested-name-specifier.
+  static unsigned getLocalDataLength(NestedNameSpecifier *Qualifier);
+
+  /// \brief Determines the data length for the entire
+  /// nested-name-specifier.
+  static unsigned getDataLength(NestedNameSpecifier *Qualifier);
+
+public:
+  /// \brief Construct an empty nested-name-specifier.
+  NestedNameSpecifierLoc() : Qualifier(0), Data(0) { }
+  
+  /// \brief Construct a nested-name-specifier with source location information
+  /// from 
+  NestedNameSpecifierLoc(NestedNameSpecifier *Qualifier, void *Data)
+    : Qualifier(Qualifier), Data(Data) { }
+  
+  /// \brief Evalutes true when this nested-name-specifier location is
+  /// non-empty.
+  operator bool() const { return Qualifier; }
+
+  /// \brief Retrieve the nested-name-specifier to which this instance
+  /// refers.
+  NestedNameSpecifier *getNestedNameSpecifier() const {
+    return Qualifier;
+  }
+
+  /// \brief Retrieve the opaque pointer that refers to source-location data.
+  void *getOpaqueData() const { return Data; }
+  
+  /// \brief Retrieve the source range covering the entirety of this
+  /// nested-name-specifier.
+  ///
+  /// For example, if this instance refers to a nested-name-specifier
+  /// \c ::std::vector<int>::, the returned source range would cover
+  /// from the initial '::' to the last '::'.
+  SourceRange getSourceRange();
+
+  /// \brief Retrieve the source range covering just the last part of
+  /// this nested-name-specifier, not including the prefix.
+  ///
+  /// For example, if this instance refers to a nested-name-specifier
+  /// \c ::std::vector<int>::, the returned source range would cover
+  /// from "vector" to the last '::'.
+  SourceRange getLocalSourceRange();
+
+  /// \brief Return the prefix of this nested-name-specifier.
+  ///
+  /// For example, if this instance refers to a nested-name-specifier
+  /// \c ::std::vector<int>::, the prefix is \c ::std::. Note that the
+  /// returned prefix may be empty, if this is the first component of
+  /// the nested-name-specifier.
+  NestedNameSpecifierLoc getPrefix() const {
+    if (!Qualifier)
+      return *this;
+
+    return NestedNameSpecifierLoc(Qualifier->getPrefix(), Data);
+  }
+  
+  /// \brief Determines the data length for the entire
+  /// nested-name-specifier.
+  unsigned getDataLength() const { return getDataLength(Qualifier); }
+};
+
 /// Insertion operator for diagnostics.  This allows sending NestedNameSpecifiers
 /// into a diagnostic with <<.
 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,

Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=126391&r1=126390&r2=126391&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Thu Feb 24 11:54:50 2011
@@ -37,6 +37,7 @@
   class NamespaceAliasDecl;
   class NamespaceDecl;
   class NestedNameSpecifier;
+  class NestedNameSpecifierLoc;
   class Preprocessor;
   class Declarator;
   struct TemplateIdAnnotation;
@@ -55,10 +56,30 @@
 class CXXScopeSpec {
   SourceRange Range;
   NestedNameSpecifier *ScopeRep;
-  
-public:
-  CXXScopeSpec() : Range(), ScopeRep() { }
 
+  /// \brief Buffer used to store source-location information for the
+  /// nested-name-specifier.
+  ///
+  /// Note that we explicitly manage the buffer (rather than using a 
+  /// SmallVector) because \c Declarator expects it to be possible to memcpy()
+  /// a \c CXXScopeSpec.
+  char *Buffer;
+  
+  /// \brief The size of the buffer used to store source-location information
+  /// for the nested-name-specifier.
+  unsigned BufferSize;
+  
+  /// \brief The capacity of the buffer used to store source-location 
+  /// information for the nested-name-specifier.
+  unsigned BufferCapacity;
+
+public:
+  CXXScopeSpec() : Range(), ScopeRep(), Buffer(0), BufferSize(0),
+                   BufferCapacity(0) { }
+  CXXScopeSpec(const CXXScopeSpec &Other);
+  CXXScopeSpec &operator=(const CXXScopeSpec &Other);
+  ~CXXScopeSpec();
+  
   const SourceRange &getRange() const { return Range; }
   void setRange(const SourceRange &R) { Range = R; }
   void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); }
@@ -129,13 +150,26 @@
   /// nested-name-specifier '::'.
   void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
   
-  /// \brief Adopt an existing nested-name-specifier and its source range
-  /// as our own.
-  void Adopt(NestedNameSpecifier *Qualifier, SourceRange R) {
-    ScopeRep = Qualifier;
-    Range = R;
-  }
-  
+  /// \brief Make a new nested-name-specifier from incomplete source-location
+  /// information.
+  ///
+  /// FIXME: This routine should be used very, very rarely, in cases where we
+  /// need to synthesize a nested-name-specifier. Most code should instead use
+  /// \c Adopt() with a proper \c NestedNameSpecifierLoc.
+  void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, 
+                   SourceRange R);
+  
+  /// \brief Adopt an existing nested-name-specifier (with source-range 
+  /// information).
+  void Adopt(NestedNameSpecifierLoc Other);
+  
+  /// \brief Retrieve a nested-name-specifier with location information, copied
+  /// into the given AST context.
+  ///
+  /// \param Context The context into which this nested-name-specifier will be
+  /// copied.
+  NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context);
+
   /// No scope specifier.
   bool isEmpty() const { return !Range.isValid(); }
   /// A scope specifier is present, but may be valid or invalid.
@@ -163,6 +197,13 @@
     Range = SourceRange();
     ScopeRep = 0;
   }
+
+  /// \brief Retrieve the data associated with the source-location information.
+  char *location_data() const { return Buffer; }
+  
+  /// \brief Retrieve the size of the data associated with source-location 
+  /// information.
+  unsigned location_size() const { return BufferSize; }
 };
 
 /// DeclSpec - This class captures information about "declaration specifiers",

Modified: cfe/trunk/include/clang/Sema/ParsedTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ParsedTemplate.h?rev=126391&r1=126390&r2=126391&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/ParsedTemplate.h (original)
+++ cfe/trunk/include/clang/Sema/ParsedTemplate.h Thu Feb 24 11:54:50 2011
@@ -177,6 +177,12 @@
       = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) +
                                       sizeof(ParsedTemplateArgument) * NumArgs);
       TemplateId->NumArgs = NumArgs;
+      
+      // Default-construct parsed template arguments.
+      ParsedTemplateArgument *TemplateArgs = TemplateId->getTemplateArgs();
+      for (unsigned I = 0; I != NumArgs; ++I)
+        new (TemplateArgs + I) ParsedTemplateArgument();
+      
       return TemplateId;
     }
     

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=126391&r1=126390&r2=126391&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Feb 24 11:54:50 2011
@@ -2679,6 +2679,30 @@
                                    SourceLocation CCLoc,
                                    CXXScopeSpec &SS);
 
+  /// \brief Given a C++ nested-name-specifier, produce an annotation value
+  /// that the parser can use later to reconstruct the given 
+  /// nested-name-specifier.
+  ///
+  /// \param SS A nested-name-specifier.
+  ///
+  /// \returns A pointer containing all of the information in the 
+  /// nested-name-specifier \p SS.
+  void *SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS);
+  
+  /// \brief Given an annotation pointer for a nested-name-specifier, restore 
+  /// the nested-name-specifier structure.
+  ///
+  /// \param Annotation The annotation pointer, produced by 
+  /// \c SaveNestedNameSpecifierAnnotation().
+  ///
+  /// \param AnnotationRange The source range corresponding to the annotation.
+  ///
+  /// \param SS The nested-name-specifier that will be updated with the contents
+  /// of the annotation pointer.
+  void RestoreNestedNameSpecifierAnnotation(void *Annotation, 
+                                            SourceRange AnnotationRange,
+                                            CXXScopeSpec &SS);
+  
   bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
 
   /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global

Modified: cfe/trunk/lib/AST/NestedNameSpecifier.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/NestedNameSpecifier.cpp?rev=126391&r1=126390&r2=126391&view=diff
==============================================================================
--- cfe/trunk/lib/AST/NestedNameSpecifier.cpp (original)
+++ cfe/trunk/lib/AST/NestedNameSpecifier.cpp Thu Feb 24 11:54:50 2011
@@ -17,6 +17,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cassert>
 
@@ -262,3 +263,94 @@
 void NestedNameSpecifier::dump(const LangOptions &LO) {
   print(llvm::errs(), PrintingPolicy(LO));
 }
+
+unsigned 
+NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
+  assert(Qualifier && "Expected a non-NULL qualifier");
+
+  // Location of the trailing '::'.
+  unsigned Length = sizeof(unsigned);
+
+  switch (Qualifier->getKind()) {
+  case NestedNameSpecifier::Global:
+    // Nothing more to add.
+    break;
+
+  case NestedNameSpecifier::Identifier:
+  case NestedNameSpecifier::Namespace:
+  case NestedNameSpecifier::NamespaceAlias:
+    // The location of the identifier or namespace name.
+    Length += sizeof(unsigned);
+    break;
+
+  case NestedNameSpecifier::TypeSpecWithTemplate:
+  case NestedNameSpecifier::TypeSpec:
+    // The "void*" that points at the TypeLoc data.
+    // Note: the 'template' keyword is part of the TypeLoc.
+    Length += sizeof(void *);
+    break;
+  }
+
+  return Length;
+}
+
+unsigned 
+NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
+  unsigned Length = 0;
+  for (; Qualifier; Qualifier = Qualifier->getPrefix())
+    Length += getLocalDataLength(Qualifier);
+  return Length;
+}
+
+namespace {
+  /// \brief Load a (possibly unaligned) source location from a given address
+  /// and offset.
+  SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
+    unsigned Raw;
+    memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned));
+    return SourceLocation::getFromRawEncoding(Raw);
+  }
+  
+  /// \brief Load a (possibly unaligned) pointer from a given address and
+  /// offset.
+  void *LoadPointer(void *Data, unsigned Offset) {
+    void *Result;
+    memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*));
+    return Result;
+  }
+}
+
+SourceRange NestedNameSpecifierLoc::getSourceRange() {
+  NestedNameSpecifierLoc First = *this;
+  while (NestedNameSpecifierLoc Prefix= First.getPrefix())
+    First = Prefix;
+  
+  return SourceRange(First.getLocalSourceRange().getBegin(), 
+                     getLocalSourceRange().getEnd());
+}
+
+SourceRange NestedNameSpecifierLoc::getLocalSourceRange() {
+  unsigned Offset = getDataLength(Qualifier->getPrefix());
+  switch (Qualifier->getKind()) {
+  case NestedNameSpecifier::Global:
+    return LoadSourceLocation(Data, Offset);
+
+  case NestedNameSpecifier::Identifier:
+  case NestedNameSpecifier::Namespace:
+  case NestedNameSpecifier::NamespaceAlias:
+    return SourceRange(LoadSourceLocation(Data, Offset),
+                       LoadSourceLocation(Data, Offset + sizeof(unsigned)));
+
+  case NestedNameSpecifier::TypeSpecWithTemplate:
+  case NestedNameSpecifier::TypeSpec: {
+    // The "void*" that points at the TypeLoc data.
+    // Note: the 'template' keyword is part of the TypeLoc.
+    void *TypeData = LoadPointer(Data, Offset);
+    TypeLoc TL(Qualifier->getAsType(), TypeData);
+    return SourceRange(TL.getBeginLoc(),
+                       LoadSourceLocation(Data, Offset + sizeof(void*)));
+  }
+  }
+  
+  return SourceRange();
+}

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=126391&r1=126390&r2=126391&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Feb 24 11:54:50 2011
@@ -956,8 +956,9 @@
         goto DoneWithDeclSpec;
 
       CXXScopeSpec SS;
-      SS.Adopt(static_cast<NestedNameSpecifier *>(Tok.getAnnotationValue()),
-               Tok.getAnnotationRange());
+      Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
+                                                   Tok.getAnnotationRange(),
+                                                   SS);
 
       // We are looking for a qualified typename.
       Token Next = NextToken();

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=126391&r1=126390&r2=126391&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Thu Feb 24 11:54:50 2011
@@ -65,8 +65,9 @@
          "Call sites of this function should be guarded by checking for C++");
 
   if (Tok.is(tok::annot_cxxscope)) {
-    SS.Adopt(static_cast<NestedNameSpecifier*>(Tok.getAnnotationValue()),
-             Tok.getAnnotationRange());
+    Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
+                                                 Tok.getAnnotationRange(),
+                                                 SS);
     ConsumeToken();
     return false;
   }
@@ -207,10 +208,8 @@
         assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
         SourceLocation CCLoc = ConsumeToken();
 
-        if (!HasScopeSpecifier) {
-          SS.setBeginLoc(TypeToken.getLocation());
+        if (!HasScopeSpecifier)
           HasScopeSpecifier = true;
-        }
 
         if (ParsedType T = getTypeAnnotation(TypeToken)) {
           if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), T, CCLoc, SS))

Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=126391&r1=126390&r2=126391&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Thu Feb 24 11:54:50 2011
@@ -829,7 +829,7 @@
     TemplateId->RAngleLoc = RAngleLoc;
     ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
     for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
-      Args[Arg] = TemplateArgs[Arg];
+      Args[Arg] = ParsedTemplateArgument(TemplateArgs[Arg]);
     Tok.setAnnotationValue(TemplateId);
     if (TemplateKWLoc.isValid())
       Tok.setLocation(TemplateKWLoc);

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=126391&r1=126390&r2=126391&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Thu Feb 24 11:54:50 2011
@@ -1163,7 +1163,7 @@
   else
     PP.EnterToken(Tok);
   Tok.setKind(tok::annot_cxxscope);
-  Tok.setAnnotationValue(SS.getScopeRep());
+  Tok.setAnnotationValue(Actions.SaveNestedNameSpecifierAnnotation(SS));
   Tok.setAnnotationRange(SS.getRange());
 
   // In case the tokens were cached, have Preprocessor replace them
@@ -1200,7 +1200,7 @@
   else
     PP.EnterToken(Tok);
   Tok.setKind(tok::annot_cxxscope);
-  Tok.setAnnotationValue(SS.getScopeRep());
+  Tok.setAnnotationValue(Actions.SaveNestedNameSpecifierAnnotation(SS));
   Tok.setAnnotationRange(SS.getRange());
 
   // In case the tokens were cached, have Preprocessor replace them with the

Modified: cfe/trunk/lib/Sema/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=126391&r1=126390&r2=126391&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/DeclSpec.cpp (original)
+++ cfe/trunk/lib/Sema/DeclSpec.cpp Thu Feb 24 11:54:50 2011
@@ -14,6 +14,7 @@
 #include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency!
 #include "clang/Sema/DeclSpec.h"
 #include "clang/Sema/ParsedTemplate.h"
+#include "clang/AST/ASTContext.h"
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Lex/Preprocessor.h"
@@ -46,6 +47,85 @@
   EndLocation = TemplateId->RAngleLoc;
 }
 
+CXXScopeSpec::CXXScopeSpec(const CXXScopeSpec &Other)
+  : Range(Other.Range), ScopeRep(Other.ScopeRep), Buffer(0), 
+    BufferSize(Other.BufferSize), BufferCapacity(Other.BufferSize) 
+{
+  if (BufferSize) {
+    Buffer = static_cast<char *>(malloc(BufferSize));
+    memcpy(Buffer, Other.Buffer, BufferSize);
+  }
+}
+
+CXXScopeSpec &CXXScopeSpec::operator=(const CXXScopeSpec &Other) {
+  Range = Other.Range;
+  ScopeRep = Other.ScopeRep;
+  if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) {
+    // Re-use our storage.
+    BufferSize = Other.BufferSize;
+    memcpy(Buffer, Other.Buffer, BufferSize);
+    return *this;
+  }
+  
+  if (BufferCapacity)
+    free(Buffer);
+  if (Other.Buffer) {
+    BufferSize = Other.BufferSize;
+    BufferCapacity = BufferSize;
+    Buffer = static_cast<char *>(malloc(BufferSize));
+    memcpy(Buffer, Other.Buffer, BufferSize);
+  } else {
+    Buffer = 0;
+    BufferSize = 0;
+    BufferCapacity = 0;
+  }
+  return *this;
+}
+
+CXXScopeSpec::~CXXScopeSpec() {
+  if (BufferCapacity)
+    free(Buffer);
+}
+
+namespace {
+  void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
+              unsigned &BufferCapacity) {
+    if (BufferSize + (End - Start) > BufferCapacity) {
+      // Reallocate the buffer.
+      unsigned NewCapacity 
+        = std::max((unsigned)(BufferCapacity? BufferCapacity * 2 
+                                            : sizeof(void*) * 2),
+                   (unsigned)(BufferSize + (End - Start)));
+      char *NewBuffer = static_cast<char *>(malloc(NewCapacity));
+      memcpy(NewBuffer, Buffer, BufferSize);
+      
+      if (BufferCapacity)
+        free(Buffer);
+      Buffer = NewBuffer;
+      BufferCapacity = NewCapacity;
+    }
+    
+    memcpy(Buffer + BufferSize, Start, End - Start);
+    BufferSize += End-Start;
+  }
+  
+  /// \brief Save a source location to the given buffer.
+  void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
+                          unsigned &BufferSize, unsigned &BufferCapacity) {
+    unsigned Raw = Loc.getRawEncoding();
+    Append(reinterpret_cast<char *>(&Raw),
+           reinterpret_cast<char *>(&Raw) + sizeof(unsigned),
+           Buffer, BufferSize, BufferCapacity);
+  }
+  
+  /// \brief Save a pointer to the given buffer.
+  void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
+                   unsigned &BufferCapacity) {
+    Append(reinterpret_cast<char *>(&Ptr),
+           reinterpret_cast<char *>(&Ptr) + sizeof(void *),
+           Buffer, BufferSize, BufferCapacity);
+  }
+}
 void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc, 
                           TypeLoc TL, SourceLocation ColonColonLoc) {
   ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, 
@@ -54,6 +134,13 @@
   if (Range.getBegin().isInvalid())
     Range.setBegin(TL.getBeginLoc());
   Range.setEnd(ColonColonLoc);
+
+  // Push source-location info into the buffer.
+  SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
+  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+
+  assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+         "NestedNameSpecifierLoc range computation incorrect");
 }
 
 void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier,
@@ -63,6 +150,13 @@
   if (Range.getBegin().isInvalid())
     Range.setBegin(IdentifierLoc);
   Range.setEnd(ColonColonLoc);
+  
+  // Push source-location info into the buffer.
+  SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity);
+  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+  
+  assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+         "NestedNameSpecifierLoc range computation incorrect");
 }
 
 void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace,
@@ -72,6 +166,13 @@
   if (Range.getBegin().isInvalid())
     Range.setBegin(NamespaceLoc);
   Range.setEnd(ColonColonLoc);
+
+  // Push source-location info into the buffer.
+  SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);
+  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+  
+  assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+         "NestedNameSpecifierLoc range computation incorrect");
 }
 
 void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
@@ -81,6 +182,13 @@
   if (Range.getBegin().isInvalid())
     Range.setBegin(AliasLoc);
   Range.setEnd(ColonColonLoc);
+
+  // Push source-location info into the buffer.
+  SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity);
+  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+  
+  assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+         "NestedNameSpecifierLoc range computation incorrect");
 }
 
 void CXXScopeSpec::MakeGlobal(ASTContext &Context, 
@@ -88,6 +196,87 @@
   assert(!ScopeRep && "Already have a nested-name-specifier!?");
   ScopeRep = NestedNameSpecifier::GlobalSpecifier(Context);
   Range = SourceRange(ColonColonLoc);
+  
+  // Push source-location info into the buffer.
+  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+  
+  assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+         "NestedNameSpecifierLoc range computation incorrect");
+}
+
+void CXXScopeSpec::MakeTrivial(ASTContext &Context, 
+                               NestedNameSpecifier *Qualifier, SourceRange R) {
+  ScopeRep = Qualifier;
+  Range = R;
+
+  // Construct bogus (but well-formed) source information for the 
+  // nested-name-specifier.
+  BufferSize = 0;
+  llvm::SmallVector<NestedNameSpecifier *, 4> Stack;
+  for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix())
+    Stack.push_back(NNS);
+  while (!Stack.empty()) {
+    NestedNameSpecifier *NNS = Stack.back();
+    Stack.pop_back();
+    switch (NNS->getKind()) {
+    case NestedNameSpecifier::Identifier:
+    case NestedNameSpecifier::Namespace:
+    case NestedNameSpecifier::NamespaceAlias:
+      SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
+      break;
+
+    case NestedNameSpecifier::TypeSpec:
+    case NestedNameSpecifier::TypeSpecWithTemplate: {
+      TypeSourceInfo *TSInfo
+        = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0),
+                                           R.getBegin());
+      SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize, 
+                  BufferCapacity);
+      break;
+    }
+        
+    case NestedNameSpecifier::Global:
+      break;
+    }
+
+    // Save the location of the '::'.
+    SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(), 
+                       Buffer, BufferSize, BufferCapacity);
+  }
+}
+
+void CXXScopeSpec::Adopt(NestedNameSpecifierLoc Other) {
+  if (!Other) {
+    Range = SourceRange();
+    ScopeRep = 0;
+    return;
+  }
+    
+  if (BufferCapacity)
+    free(Buffer);
+  
+  // Rather than copying the data (which is wasteful), "adopt" the 
+  // pointer (which points into the ASTContext) but set the capacity to zero to
+  // indicate that we don't own it.
+  Range = Other.getSourceRange();
+  ScopeRep = Other.getNestedNameSpecifier();
+  Buffer = static_cast<char *>(Other.getOpaqueData());
+  BufferSize = Other.getDataLength();
+  BufferCapacity = 0;
+}
+
+NestedNameSpecifierLoc CXXScopeSpec::getWithLocInContext(ASTContext &Context) {
+  if (isEmpty() || isInvalid())
+    return NestedNameSpecifierLoc();
+  
+  // If we adopted our data pointer from elsewhere in the AST context, there's
+  // no need to copy the memory.
+  if (BufferCapacity == 0)
+    return NestedNameSpecifierLoc(ScopeRep, Buffer);
+  
+  void *Mem = Context.Allocate(BufferSize, llvm::alignOf<void *>());
+  memcpy(Mem, Buffer, BufferSize);
+  return NestedNameSpecifierLoc(ScopeRep, Mem);
 }
 
 /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.

Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=126391&r1=126390&r2=126391&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Thu Feb 24 11:54:50 2011
@@ -658,6 +658,41 @@
   return false;
 }
 
+namespace {
+  /// \brief A structure that stores a nested-name-specifier annotation,
+  /// including both the nested-name-specifier 
+  struct NestedNameSpecifierAnnotation {
+    NestedNameSpecifier *NNS;
+  };
+}
+
+void *Sema::SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS) {
+  if (SS.isEmpty() || SS.isInvalid())
+    return 0;
+  
+  void *Mem = Context.Allocate((sizeof(NestedNameSpecifierAnnotation) +
+                                                        SS.location_size()),
+                               llvm::alignOf<NestedNameSpecifierAnnotation>());
+  NestedNameSpecifierAnnotation *Annotation
+    = new (Mem) NestedNameSpecifierAnnotation;
+  Annotation->NNS = SS.getScopeRep();
+  memcpy(Annotation + 1, SS.location_data(), SS.location_size());
+  return Annotation;
+}
+
+void Sema::RestoreNestedNameSpecifierAnnotation(void *AnnotationPtr, 
+                                                SourceRange AnnotationRange,
+                                                CXXScopeSpec &SS) {
+  if (!AnnotationPtr) {
+    SS.SetInvalid(AnnotationRange);
+    return;
+  }
+  
+  NestedNameSpecifierAnnotation *Annotation
+    = static_cast<NestedNameSpecifierAnnotation *>(AnnotationPtr);
+  SS.Adopt(NestedNameSpecifierLoc(Annotation->NNS, Annotation + 1));
+}
+
 bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
   assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
 

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=126391&r1=126390&r2=126391&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Feb 24 11:54:50 2011
@@ -5085,8 +5085,10 @@
     // reference to operator=; this is required to suppress the virtual
     // call mechanism.
     CXXScopeSpec SS;
-    SS.Adopt(NestedNameSpecifier::Create(S.Context, 0, false, T.getTypePtr()),
-             Loc);
+    SS.MakeTrivial(S.Context, 
+                   NestedNameSpecifier::Create(S.Context, 0, false, 
+                                               T.getTypePtr()),
+                   Loc);
     
     // Create the reference to operator=.
     ExprResult OpEqualRef

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=126391&r1=126390&r2=126391&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Feb 24 11:54:50 2011
@@ -107,7 +107,7 @@
       // Nothing left to do.
     } else if (LookAtPrefix && (Prefix = NNS->getPrefix())) {
       CXXScopeSpec PrefixSS;
-      PrefixSS.Adopt(Prefix, SS.getRange());
+      PrefixSS.MakeTrivial(Context, Prefix, SS.getRange());
       LookupCtx = computeDeclContext(PrefixSS, EnteringContext);
       isDependent = isDependentScopeSpecifier(PrefixSS);
     } else if (ObjectTypePtr) {

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=126391&r1=126390&r2=126391&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Feb 24 11:54:50 2011
@@ -7594,7 +7594,8 @@
 
   CXXScopeSpec SS;
   if (ULE->getQualifier())
-    SS.Adopt(ULE->getQualifier(), ULE->getQualifierRange());
+    SS.MakeTrivial(SemaRef.Context, 
+                   ULE->getQualifier(), ULE->getQualifierRange());
 
   TemplateArgumentListInfo TABuffer;
   const TemplateArgumentListInfo *ExplicitTemplateArgs = 0;

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=126391&r1=126390&r2=126391&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Feb 24 11:54:50 2011
@@ -3611,7 +3611,7 @@
         = NestedNameSpecifier::Create(Context, 0, false,
                                       ClassType.getTypePtr());
       CXXScopeSpec SS;
-      SS.Adopt(Qualifier, Loc);
+      SS.MakeTrivial(Context, Qualifier, Loc);
 
       // The actual value-ness of this is unimportant, but for
       // internal consistency's sake, references to instance methods
@@ -5998,7 +5998,7 @@
                         SourceLocation KeywordLoc, SourceRange NNSRange,
                         SourceLocation IILoc) {
   CXXScopeSpec SS;
-  SS.Adopt(NNS, NNSRange);
+  SS.MakeTrivial(Context, NNS, NNSRange);
 
   DeclContext *Ctx = computeDeclContext(SS);
   if (!Ctx) {
@@ -6177,7 +6177,7 @@
     Rebuilder.TransformNestedNameSpecifier(NNS, SS.getRange());
   if (!Rebuilt) return true;
 
-  SS.Adopt(Rebuilt, SS.getRange());
+  SS.MakeTrivial(Context, Rebuilt, SS.getRange());
   return false;
 }
 

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=126391&r1=126390&r2=126391&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Feb 24 11:54:50 2011
@@ -670,7 +670,7 @@
   if (isFriend) {
     if (Qualifier) {
       CXXScopeSpec SS;
-      SS.Adopt(Qualifier, Pattern->getQualifierRange());
+      SS.MakeTrivial(SemaRef.Context, Qualifier, Pattern->getQualifierRange());
       DC = SemaRef.computeDeclContext(SS);
       if (!DC) return 0;
     } else {
@@ -983,7 +983,7 @@
     DC = Owner;
   else if (isFriend && Qualifier) {
     CXXScopeSpec SS;
-    SS.Adopt(Qualifier, D->getQualifierRange());
+    SS.MakeTrivial(SemaRef.Context, Qualifier, D->getQualifierRange());
     DC = SemaRef.computeDeclContext(SS);
     if (!DC) return 0;
   } else {
@@ -1272,7 +1272,7 @@
   if (isFriend) {
     if (Qualifier) {
       CXXScopeSpec SS;
-      SS.Adopt(Qualifier, D->getQualifierRange());
+      SS.MakeTrivial(SemaRef.Context, Qualifier, D->getQualifierRange());
       DC = SemaRef.computeDeclContext(SS);
 
       if (DC && SemaRef.RequireCompleteDeclContext(SS, DC))
@@ -1688,7 +1688,7 @@
                                        D->isTypeName());
 
   CXXScopeSpec SS;
-  SS.Adopt(NNS, D->getNestedNameRange());
+  SS.MakeTrivial(SemaRef.Context, NNS, D->getNestedNameRange());
 
   if (CheckRedeclaration) {
     Prev.setHideTags(false);
@@ -1756,7 +1756,7 @@
     return 0;
 
   CXXScopeSpec SS;
-  SS.Adopt(NNS, D->getTargetNestedNameRange());
+  SS.MakeTrivial(SemaRef.Context, NNS, D->getTargetNestedNameRange());
 
   // Since NameInfo refers to a typename, it cannot be a C++ special name.
   // Hence, no tranformation is required for it.
@@ -1782,7 +1782,7 @@
     return 0;
 
   CXXScopeSpec SS;
-  SS.Adopt(NNS, D->getTargetNestedNameRange());
+  SS.MakeTrivial(SemaRef.Context, NNS, D->getTargetNestedNameRange());
 
   DeclarationNameInfo NameInfo
     = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=126391&r1=126390&r2=126391&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Feb 24 11:54:50 2011
@@ -759,7 +759,7 @@
                                     SourceRange NNSRange,
                                     SourceLocation IdLoc) {
     CXXScopeSpec SS;
-    SS.Adopt(NNS, NNSRange);
+    SS.MakeTrivial(SemaRef.Context, NNS, NNSRange);
 
     if (NNS->isDependent()) {
       // If the name is still dependent, just build a new dependent name type.
@@ -1252,7 +1252,7 @@
                                 const DeclarationNameInfo &NameInfo,
                                 TemplateArgumentListInfo *TemplateArgs) {
     CXXScopeSpec SS;
-    SS.Adopt(Qualifier, QualifierRange);
+    SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
 
     // FIXME: loses template args.
 
@@ -1391,7 +1391,7 @@
 
     CXXScopeSpec SS;
     if (Qualifier) {
-      SS.Adopt(Qualifier, QualifierRange);
+      SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
     }
 
     getSema().DefaultFunctionArrayConversion(Base);
@@ -1882,7 +1882,7 @@
                                        const DeclarationNameInfo &NameInfo,
                               const TemplateArgumentListInfo *TemplateArgs) {
     CXXScopeSpec SS;
-    SS.Adopt(NNS, QualifierRange);
+    SS.MakeTrivial(SemaRef.Context, NNS, QualifierRange);
 
     if (TemplateArgs)
       return getSema().BuildQualifiedTemplateIdExpr(SS, NameInfo,
@@ -1967,7 +1967,7 @@
                                    const DeclarationNameInfo &MemberNameInfo,
                               const TemplateArgumentListInfo *TemplateArgs) {
     CXXScopeSpec SS;
-    SS.Adopt(Qualifier, QualifierRange);
+    SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
 
     return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType,
                                             OperatorLoc, IsArrow,
@@ -1990,7 +1990,7 @@
                                                LookupResult &R,
                                 const TemplateArgumentListInfo *TemplateArgs) {
     CXXScopeSpec SS;
-    SS.Adopt(Qualifier, QualifierRange);
+    SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
 
     return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType,
                                             OperatorLoc, IsArrow,
@@ -6467,7 +6467,7 @@
     // Look for a destructor known with the given name.
     CXXScopeSpec SS;
     if (Qualifier)
-      SS.Adopt(Qualifier, E->getQualifierRange());
+      SS.MakeTrivial(SemaRef.Context, Qualifier, E->getQualifierRange());
     
     ParsedType T = SemaRef.getDestructorName(E->getTildeLoc(),
                                               *E->getDestroyedTypeIdentifier(),
@@ -6550,7 +6550,7 @@
     if (!Qualifier)
       return ExprError();
     
-    SS.Adopt(Qualifier, Old->getQualifierRange());
+    SS.MakeTrivial(SemaRef.Context, Qualifier, Old->getQualifierRange());
   } 
   
   if (Old->getNamingClass()) {
@@ -7571,7 +7571,7 @@
                                                    NamedDecl *FirstQualifierInScope) {
   CXXScopeSpec SS;
   // FIXME: The source location information is all wrong.
-  SS.Adopt(Prefix, Range);
+  SS.MakeTrivial(SemaRef.Context, Prefix, Range);
   if (SemaRef.BuildCXXNestedNameSpecifier(0, II, /*FIXME:*/Range.getBegin(),
                                           /*FIXME:*/Range.getEnd(),
                                           ObjectType, false,
@@ -7632,7 +7632,7 @@
                                             QualType ObjectType,
                                             NamedDecl *FirstQualifierInScope) {
   CXXScopeSpec SS;
-  SS.Adopt(Qualifier, QualifierRange);
+  SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
   UnqualifiedId Name;
   Name.setIdentifier(&II, /*FIXME:*/getDerived().getBaseLocation());
   Sema::TemplateTy Template;
@@ -7652,7 +7652,7 @@
                                             OverloadedOperatorKind Operator,
                                             QualType ObjectType) {
   CXXScopeSpec SS;
-  SS.Adopt(Qualifier, SourceRange(getDerived().getBaseLocation()));
+  SS.MakeTrivial(SemaRef.Context, Qualifier, SourceRange(getDerived().getBaseLocation()));
   UnqualifiedId Name;
   SourceLocation SymbolLocations[3]; // FIXME: Bogus location information.
   Name.setOperatorFunctionId(/*FIXME:*/getDerived().getBaseLocation(),
@@ -7766,7 +7766,7 @@
                                         PseudoDestructorTypeStorage Destroyed) {
   CXXScopeSpec SS;
   if (Qualifier)
-    SS.Adopt(Qualifier, QualifierRange);
+    SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange);
 
   QualType BaseType = Base->getType();
   if (Base->isTypeDependent() || Destroyed.getIdentifier() ||





More information about the cfe-commits mailing list