[cfe-commits] r126716 - in /cfe/trunk: include/clang/AST/NestedNameSpecifier.h include/clang/Sema/DeclSpec.h lib/AST/NestedNameSpecifier.cpp lib/Sema/DeclSpec.cpp lib/Serialization/ASTReader.cpp

Douglas Gregor dgregor at apple.com
Mon Feb 28 15:58:31 PST 2011


Author: dgregor
Date: Mon Feb 28 17:58:31 2011
New Revision: 126716

URL: http://llvm.org/viewvc/llvm-project?rev=126716&view=rev
Log:
Refactor the construction of nested-name-specifiers with
source-location information into a NestedNameSpecifierLocBuilder
class, which lives within the AST library and centralize all knowledge
of the format of nested-name-specifier location information here.

No functionality change.

Modified:
    cfe/trunk/include/clang/AST/NestedNameSpecifier.h
    cfe/trunk/include/clang/Sema/DeclSpec.h
    cfe/trunk/lib/AST/NestedNameSpecifier.cpp
    cfe/trunk/lib/Sema/DeclSpec.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp

Modified: cfe/trunk/include/clang/AST/NestedNameSpecifier.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/NestedNameSpecifier.h?rev=126716&r1=126715&r2=126716&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/NestedNameSpecifier.h (original)
+++ cfe/trunk/include/clang/AST/NestedNameSpecifier.h Mon Feb 28 17:58:31 2011
@@ -312,6 +312,146 @@
   }
 };
 
+/// \brief Class that aids in the construction of nested-name-specifiers along
+/// with source-location information for all of the components of the
+/// nested-name-specifier.
+class NestedNameSpecifierLocBuilder {
+  /// \brief The current representation of the nested-name-specifier we're 
+  /// building.
+  NestedNameSpecifier *Representation;
+  
+  /// \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, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder.
+  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:
+  NestedNameSpecifierLocBuilder();
+  
+  NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other);
+  
+  NestedNameSpecifierLocBuilder &
+  operator=(const NestedNameSpecifierLocBuilder &Other);
+  
+  ~NestedNameSpecifierLocBuilder();
+  
+  /// \brief Retrieve the representation of the nested-name-specifier.
+  NestedNameSpecifier *getRepresentation() const { return Representation; }
+  
+  /// \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::'.
+  ///
+  /// \param Context The AST context in which this nested-name-specifier
+  /// resides.
+  ///
+  /// \param Namespace The namespace.
+  ///
+  /// \param NamespaceLoc The location of the namespace name.
+  ///
+  /// \param ColonColonLoc The location of the trailing '::'.
+  void Extend(ASTContext &Context, NamespaceDecl *Namespace,
+              SourceLocation NamespaceLoc, SourceLocation ColonColonLoc);
+  
+  /// \brief Extend the current nested-name-specifier by another 
+  /// nested-name-specifier component of the form 'namespace-alias::'.
+  ///
+  /// \param Context The AST context in which this nested-name-specifier
+  /// resides.
+  ///
+  /// \param Alias The namespace alias.
+  ///
+  /// \param AliasLoc The location of the namespace alias 
+  /// name.
+  ///
+  /// \param ColonColonLoc The location of the trailing '::'.
+  void Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
+              SourceLocation AliasLoc, SourceLocation ColonColonLoc);
+  
+  /// \brief Turn this (empty) nested-name-specifier into the global
+  /// nested-name-specifier '::'.
+  void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
+  
+  /// \brief Make a new nested-name-specifier from incomplete source-location
+  /// information.
+  ///
+  /// 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 the source range covered by this nested-name-specifier.
+  SourceRange getSourceRange() const {
+    return NestedNameSpecifierLoc(Representation, Buffer).getSourceRange();
+  }
+    
+  /// \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) const;
+
+  /// \brief Clear out this builder, and prepare it to build another
+  /// nested-name-specifier with source-location information.
+  void Clear() {
+    Representation = 0;
+    BufferSize = 0;
+  }
+  
+  /// \brief Retrieve the underlying buffer.
+  ///
+  /// \returns A pair containing a pointer to the buffer of source-location
+  /// data and the size of the source-location data that resides in that
+  /// buffer.
+  std::pair<char *, unsigned> getBuffer() const {
+    return std::make_pair(Buffer, BufferSize);
+  }
+};
+  
 /// 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=126716&r1=126715&r2=126716&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Mon Feb 28 17:58:31 2011
@@ -22,6 +22,7 @@
 
 #include "clang/Sema/AttributeList.h"
 #include "clang/Sema/Ownership.h"
+#include "clang/AST/NestedNameSpecifier.h"
 #include "clang/Lex/Token.h"
 #include "clang/Basic/OperatorKinds.h"
 #include "clang/Basic/Specifiers.h"
@@ -54,32 +55,10 @@
 ///
 /// The actual scope is described by getScopeRep().
 class CXXScopeSpec {
-  SourceRange Range;
-  NestedNameSpecifier *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;
+  SourceRange Range;  
+  NestedNameSpecifierLocBuilder Builder;
 
 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); }
@@ -87,7 +66,10 @@
   SourceLocation getBeginLoc() const { return Range.getBegin(); }
   SourceLocation getEndLoc() const { return Range.getEnd(); }
 
-  NestedNameSpecifier *getScopeRep() const { return ScopeRep; }
+  /// \brief Retrieve the representation of the nested-name-specifier.
+  NestedNameSpecifier *getScopeRep() const { 
+    return Builder.getRepresentation(); 
+  }
 
   /// \brief Extend the current nested-name-specifier by another
   /// nested-name-specifier component of the form 'type::'.
@@ -176,9 +158,9 @@
   bool isNotEmpty() const { return !isEmpty(); }
 
   /// An error occured during parsing of the scope specifier.
-  bool isInvalid() const { return isNotEmpty() && ScopeRep == 0; }
+  bool isInvalid() const { return isNotEmpty() && getScopeRep() == 0; }
   /// A scope specifier is present, and it refers to a real scope.
-  bool isValid() const { return isNotEmpty() && ScopeRep != 0; }
+  bool isValid() const { return isNotEmpty() && getScopeRep() != 0; }
 
   /// \brief Indicate that this nested-name-specifier is invalid.
   void SetInvalid(SourceRange R) { 
@@ -186,24 +168,24 @@
     if (Range.getBegin().isInvalid())
       Range.setBegin(R.getBegin());
     Range.setEnd(R.getEnd());
-    ScopeRep = 0;
+    Builder.Clear();
   }
   
   /// Deprecated.  Some call sites intend isNotEmpty() while others intend
   /// isValid().
-  bool isSet() const { return ScopeRep != 0; }
+  bool isSet() const { return getScopeRep() != 0; }
 
   void clear() {
     Range = SourceRange();
-    ScopeRep = 0;
+    Builder.Clear();
   }
 
   /// \brief Retrieve the data associated with the source-location information.
-  char *location_data() const { return Buffer; }
+  char *location_data() const { return Builder.getBuffer().first; }
   
   /// \brief Retrieve the size of the data associated with source-location 
   /// information.
-  unsigned location_size() const { return BufferSize; }
+  unsigned location_size() const { return Builder.getBuffer().second; }
 };
 
 /// DeclSpec - This class captures information about "declaration specifiers",

Modified: cfe/trunk/lib/AST/NestedNameSpecifier.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/NestedNameSpecifier.cpp?rev=126716&r1=126715&r2=126716&view=diff
==============================================================================
--- cfe/trunk/lib/AST/NestedNameSpecifier.cpp (original)
+++ cfe/trunk/lib/AST/NestedNameSpecifier.cpp Mon Feb 28 17:58:31 2011
@@ -371,3 +371,249 @@
   void *TypeData = LoadPointer(Data, Offset);
   return TypeLoc(Qualifier->getAsType(), TypeData);
 }
+
+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);
+  }
+}
+
+NestedNameSpecifierLocBuilder::NestedNameSpecifierLocBuilder()
+  : Representation(0), Buffer(0), BufferSize(0), BufferCapacity(0) { }
+
+NestedNameSpecifierLocBuilder::
+NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other) 
+  : Representation(Other.Representation), Buffer(0),
+    BufferSize(0), BufferCapacity(0)
+{
+  if (!Other.Buffer)
+    return;
+  
+  if (Other.BufferCapacity == 0) {
+    // Shallow copy is okay.
+    Buffer = Other.Buffer;
+    BufferSize = Other.BufferSize;
+    return;
+  }
+  
+  // Deep copy
+  BufferSize = Other.BufferSize;
+  BufferCapacity = Other.BufferSize;
+  Buffer = static_cast<char *>(malloc(BufferCapacity));
+  memcpy(Buffer, Other.Buffer, BufferSize);
+}
+
+NestedNameSpecifierLocBuilder &
+NestedNameSpecifierLocBuilder::
+operator=(const NestedNameSpecifierLocBuilder &Other) {
+  Representation = Other.Representation;
+  
+  if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) {
+    // Re-use our storage.
+    BufferSize = Other.BufferSize;
+    memcpy(Buffer, Other.Buffer, BufferSize);
+    return *this;
+  }
+  
+  // Free our storage, if we have any.
+  if (BufferCapacity) {
+    free(Buffer);
+    BufferCapacity = 0;
+  }
+  
+  if (!Other.Buffer) {
+    // Empty.
+    Buffer = 0;
+    BufferSize = 0;
+    return *this;
+  }
+  
+  if (Other.BufferCapacity == 0) {
+    // Shallow copy is okay.
+    Buffer = Other.Buffer;
+    BufferSize = Other.BufferSize;
+    return *this;
+  }
+  
+  // Deep copy.
+  BufferSize = Other.BufferSize;
+  BufferCapacity = BufferSize;
+  Buffer = static_cast<char *>(malloc(BufferSize));
+  memcpy(Buffer, Other.Buffer, BufferSize);
+  return *this;
+}
+
+NestedNameSpecifierLocBuilder::~NestedNameSpecifierLocBuilder() {
+  if (BufferCapacity)
+    free(Buffer);
+}
+
+void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 
+                                           SourceLocation TemplateKWLoc, 
+                                           TypeLoc TL, 
+                                           SourceLocation ColonColonLoc) {
+  Representation = NestedNameSpecifier::Create(Context, Representation, 
+                                               TemplateKWLoc.isValid(), 
+                                               TL.getTypePtr());
+  
+  // Push source-location info into the buffer.
+  SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
+  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+}
+
+void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 
+                                           IdentifierInfo *Identifier,
+                                           SourceLocation IdentifierLoc, 
+                                           SourceLocation ColonColonLoc) {
+  Representation = NestedNameSpecifier::Create(Context, Representation, 
+                                               Identifier);
+  
+  // Push source-location info into the buffer.
+  SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity);
+  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+}
+
+void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 
+                                           NamespaceDecl *Namespace,
+                                           SourceLocation NamespaceLoc, 
+                                           SourceLocation ColonColonLoc) {
+  Representation = NestedNameSpecifier::Create(Context, Representation, 
+                                               Namespace);
+  
+  // Push source-location info into the buffer.
+  SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);
+  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+}
+
+void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
+                                           NamespaceAliasDecl *Alias,
+                                           SourceLocation AliasLoc, 
+                                           SourceLocation ColonColonLoc) {
+  Representation = NestedNameSpecifier::Create(Context, Representation, Alias);
+  
+  // Push source-location info into the buffer.
+  SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity);
+  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+}
+
+void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context, 
+                                               SourceLocation ColonColonLoc) {
+  assert(!Representation && "Already have a nested-name-specifier!?");
+  Representation = NestedNameSpecifier::GlobalSpecifier(Context);
+  
+  // Push source-location info into the buffer.
+  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+}
+
+void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context, 
+                                                NestedNameSpecifier *Qualifier, 
+                                                SourceRange R) {
+  Representation = Qualifier;
+  
+  // 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 NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) {
+  if (BufferCapacity)
+    free(Buffer);
+
+  if (!Other) {
+    Representation = 0;
+    BufferSize = 0;
+    return;
+  }
+  
+  // 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.
+  Representation = Other.getNestedNameSpecifier();
+  Buffer = static_cast<char *>(Other.getOpaqueData());
+  BufferSize = Other.getDataLength();
+  BufferCapacity = 0;
+}
+
+NestedNameSpecifierLoc 
+NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const {
+  if (!Representation)
+    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(Representation, Buffer);
+  
+  // FIXME: After copying the source-location information, should we free
+  // our (temporary) buffer and adopt the ASTContext-allocated memory?
+  // Doing so would optimize repeated calls to getWithLocInContext().
+  void *Mem = Context.Allocate(BufferSize, llvm::alignOf<void *>());
+  memcpy(Mem, Buffer, BufferSize);
+  return NestedNameSpecifierLoc(Representation, Mem);
+}
+

Modified: cfe/trunk/lib/Sema/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=126716&r1=126715&r2=126716&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/DeclSpec.cpp (original)
+++ cfe/trunk/lib/Sema/DeclSpec.cpp Mon Feb 28 17:58:31 2011
@@ -47,222 +47,81 @@
   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, 
-                                         TemplateKWLoc.isValid(), 
-                                         TL.getTypePtr());
+  Builder.Extend(Context, TemplateKWLoc, TL, ColonColonLoc);
   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() &&
+  assert(Range == Builder.getSourceRange() &&
          "NestedNameSpecifierLoc range computation incorrect");
 }
 
 void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier,
                           SourceLocation IdentifierLoc, 
                           SourceLocation ColonColonLoc) {
-  ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Identifier);
+  Builder.Extend(Context, Identifier, IdentifierLoc, ColonColonLoc);
+  
   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() &&
+  assert(Range == Builder.getSourceRange() &&
          "NestedNameSpecifierLoc range computation incorrect");
 }
 
 void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace,
                           SourceLocation NamespaceLoc, 
                           SourceLocation ColonColonLoc) {
-  ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Namespace);
+  Builder.Extend(Context, Namespace, NamespaceLoc, ColonColonLoc);
+  
   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() &&
+  assert(Range == Builder.getSourceRange() &&
          "NestedNameSpecifierLoc range computation incorrect");
 }
 
 void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
                           SourceLocation AliasLoc, 
                           SourceLocation ColonColonLoc) {
-  ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Alias);
+  Builder.Extend(Context, Alias, AliasLoc, ColonColonLoc);
+  
   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() &&
+  assert(Range == Builder.getSourceRange() &&
          "NestedNameSpecifierLoc range computation incorrect");
 }
 
 void CXXScopeSpec::MakeGlobal(ASTContext &Context, 
                               SourceLocation ColonColonLoc) {
-  assert(!ScopeRep && "Already have a nested-name-specifier!?");
-  ScopeRep = NestedNameSpecifier::GlobalSpecifier(Context);
-  Range = SourceRange(ColonColonLoc);
+  Builder.MakeGlobal(Context, ColonColonLoc);
   
-  // Push source-location info into the buffer.
-  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
+  Range = SourceRange(ColonColonLoc);
   
-  assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() &&
+  assert(Range == Builder.getSourceRange() &&
          "NestedNameSpecifierLoc range computation incorrect");
 }
 
 void CXXScopeSpec::MakeTrivial(ASTContext &Context, 
                                NestedNameSpecifier *Qualifier, SourceRange R) {
-  ScopeRep = Qualifier;
+  Builder.MakeTrivial(Context, Qualifier, R);
   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;
+    Builder.Clear();
     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;
+  Builder.Adopt(Other);
 }
 
 NestedNameSpecifierLoc 
@@ -270,14 +129,7 @@
   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);
+  return Builder.getWithLocInContext(Context);
 }
 
 /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=126716&r1=126715&r2=126716&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Mon Feb 28 17:58:31 2011
@@ -23,6 +23,7 @@
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/Type.h"
 #include "clang/AST/TypeLocVisitor.h"
 #include "clang/Lex/MacroInfo.h"
@@ -4762,103 +4763,57 @@
 ASTReader::ReadNestedNameSpecifierLoc(PerFileData &F, const RecordData &Record, 
                                       unsigned &Idx) {
   unsigned N = Record[Idx++];
-  NestedNameSpecifier *NNS = 0, *Prev = 0;
-  llvm::SmallVector<char, 32> LocationData;
+  NestedNameSpecifierLocBuilder Builder;
   for (unsigned I = 0; I != N; ++I) {
     NestedNameSpecifier::SpecifierKind Kind
       = (NestedNameSpecifier::SpecifierKind)Record[Idx++];
     switch (Kind) {
     case NestedNameSpecifier::Identifier: {
-      // Nested-name-specifier
-      IdentifierInfo *II = GetIdentifierInfo(Record, Idx);
-      NNS = NestedNameSpecifier::Create(*Context, Prev, II);
-      
-      // Location information
+      IdentifierInfo *II = GetIdentifierInfo(Record, Idx);      
       SourceRange Range = ReadSourceRange(F, Record, Idx);
-      unsigned RawStart = Range.getBegin().getRawEncoding();
-      unsigned RawEnd = Range.getEnd().getRawEncoding();
-      LocationData.append(reinterpret_cast<char*>(&RawStart),
-                          reinterpret_cast<char*>(&RawStart) +sizeof(unsigned));
-      LocationData.append(reinterpret_cast<char*>(&RawEnd),
-                          reinterpret_cast<char*>(&RawEnd) + sizeof(unsigned));
+      Builder.Extend(*Context, II, Range.getBegin(), Range.getEnd());
       break;
     }
 
     case NestedNameSpecifier::Namespace: {
-      // Nested-name-specifier
       NamespaceDecl *NS = cast<NamespaceDecl>(GetDecl(Record[Idx++]));
-      NNS = NestedNameSpecifier::Create(*Context, Prev, NS);
-
-      // Location information
       SourceRange Range = ReadSourceRange(F, Record, Idx);
-      unsigned RawStart = Range.getBegin().getRawEncoding();
-      unsigned RawEnd = Range.getEnd().getRawEncoding();
-      LocationData.append(reinterpret_cast<char*>(&RawStart),
-                          reinterpret_cast<char*>(&RawStart) +sizeof(unsigned));
-      LocationData.append(reinterpret_cast<char*>(&RawEnd),
-                          reinterpret_cast<char*>(&RawEnd) + sizeof(unsigned));
+      Builder.Extend(*Context, NS, Range.getBegin(), Range.getEnd());
       break;
     }
 
     case NestedNameSpecifier::NamespaceAlias: {
-      // Nested-name-specifier
       NamespaceAliasDecl *Alias
         = cast<NamespaceAliasDecl>(GetDecl(Record[Idx++]));
-      NNS = NestedNameSpecifier::Create(*Context, Prev, Alias);
-      
-      // Location information
       SourceRange Range = ReadSourceRange(F, Record, Idx);
-      unsigned RawStart = Range.getBegin().getRawEncoding();
-      unsigned RawEnd = Range.getEnd().getRawEncoding();
-      LocationData.append(reinterpret_cast<char*>(&RawStart),
-                          reinterpret_cast<char*>(&RawStart) +sizeof(unsigned));
-      LocationData.append(reinterpret_cast<char*>(&RawEnd),
-                          reinterpret_cast<char*>(&RawEnd) + sizeof(unsigned));
-
+      Builder.Extend(*Context, Alias, Range.getBegin(), Range.getEnd());
       break;
     }
 
     case NestedNameSpecifier::TypeSpec:
     case NestedNameSpecifier::TypeSpecWithTemplate: {
-      // Nested-name-specifier
       bool Template = Record[Idx++];
       TypeSourceInfo *T = GetTypeSourceInfo(F, Record, Idx);
       if (!T)
         return NestedNameSpecifierLoc();
-      NNS = NestedNameSpecifier::Create(*Context, Prev, Template, 
-                                        T->getType().getTypePtr());
-
-      // Location information.
       SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx);
-      unsigned RawLocation = ColonColonLoc.getRawEncoding();
-      void *OpaqueTypeData = T->getTypeLoc().getOpaqueData();
-      LocationData.append(reinterpret_cast<char*>(&OpaqueTypeData),
-                          (reinterpret_cast<char*>(&OpaqueTypeData) 
-                             + sizeof(void *)));
-      LocationData.append(reinterpret_cast<char*>(&RawLocation),
-                          (reinterpret_cast<char*>(&RawLocation) +
-                             sizeof(unsigned)));
+
+      // FIXME: 'template' keyword location not saved anywhere, so we fake it.
+      Builder.Extend(*Context, 
+                     Template? T->getTypeLoc().getBeginLoc() : SourceLocation(),
+                     T->getTypeLoc(), ColonColonLoc);
       break;
     }
 
     case NestedNameSpecifier::Global: {
-      // Nested-name-specifier
-      NNS = NestedNameSpecifier::GlobalSpecifier(*Context);
-
       SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx);
-      unsigned RawLocation = ColonColonLoc.getRawEncoding();
-      LocationData.append(reinterpret_cast<char*>(&RawLocation),
-                          (reinterpret_cast<char*>(&RawLocation) +
-                             sizeof(unsigned)));
+      Builder.MakeGlobal(*Context, ColonColonLoc);
       break;
     }
     }
-    Prev = NNS;
   }
   
-  void *Mem = Context->Allocate(LocationData.size(), llvm::alignOf<void*>());
-  memcpy(Mem, LocationData.data(), LocationData.size());
-  return NestedNameSpecifierLoc(NNS, Mem);
+  return Builder.getWithLocInContext(*Context);
 }
 
 SourceRange





More information about the cfe-commits mailing list