]> granicus.if.org Git - clang/blobdiff - include/clang/AST/ExternalASTSource.h
Header guard canonicalization, clang part.
[clang] / include / clang / AST / ExternalASTSource.h
index 94b756773b56ce0c44e0259b136b8afb4c79f994..ff1d180ee8c611a568b5d0de36b86e209f1ab8c3 100644 (file)
 //  construction of AST nodes from some external source.
 //
 //===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
-#define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
+#ifndef LLVM_CLANG_AST_EXTERNALASTSOURCE_H
+#define LLVM_CLANG_AST_EXTERNALASTSOURCE_H
 
+#include "clang/AST/CharUnits.h"
 #include "clang/AST/DeclBase.h"
+#include "llvm/ADT/DenseMap.h"
 
 namespace clang {
 
@@ -22,7 +24,10 @@ class ASTConsumer;
 class CXXBaseSpecifier;
 class DeclarationName;
 class ExternalSemaSource; // layering violation required for downcasting
+class FieldDecl;
+class Module;
 class NamedDecl;
+class RecordDecl;
 class Selector;
 class Stmt;
 class TagDecl;
@@ -40,7 +45,7 @@ enum ExternalLoadResult {
   /// no additional processing is required.
   ELR_AlreadyLoaded
 };
-  
+
 /// \brief Abstract interface for external sources of AST nodes.
 ///
 /// External AST sources provide AST nodes constructed from some
@@ -48,7 +53,11 @@ enum ExternalLoadResult {
 /// sources can resolve types and declarations from abstract IDs into
 /// actual type and declaration nodes, and read parts of declaration
 /// contexts.
-class ExternalASTSource {
+class ExternalASTSource : public RefCountedBase<ExternalASTSource> {
+  /// Generation number for this external AST source. Must be increased
+  /// whenever we might have added new redeclarations for existing decls.
+  uint32_t CurrentGeneration;
+
   /// \brief Whether this AST source also provides information for
   /// semantic analysis.
   bool SemaSource;
@@ -56,7 +65,7 @@ class ExternalASTSource {
   friend class ExternalSemaSource;
 
 public:
-  ExternalASTSource() : SemaSource(false) { }
+  ExternalASTSource() : CurrentGeneration(0), SemaSource(false) { }
 
   virtual ~ExternalASTSource();
 
@@ -74,6 +83,11 @@ public:
     }
   };
 
+  /// \brief Get the current generation of this AST source. This number
+  /// is incremented each time the AST source lazily extends an existing
+  /// entity.
+  uint32_t getGeneration() const { return CurrentGeneration; }
+
   /// \brief Resolve a declaration ID into a declaration, potentially
   /// building a new declaration.
   ///
@@ -113,17 +127,28 @@ public:
   /// The default implementation of this method is a no-op.
   virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset);
 
-  /// \brief Finds all declarations with the given name in the
-  /// given context.
-  ///
-  /// Generally the final step of this method is either to call
-  /// SetExternalVisibleDeclsForName or to recursively call lookup on
-  /// the DeclContext after calling SetExternalVisibleDecls.
+  /// \brief Update an out-of-date identifier.
+  virtual void updateOutOfDateIdentifier(IdentifierInfo &II) { }
+
+  /// \brief Find all declarations with the given name in the given context,
+  /// and add them to the context by calling SetExternalVisibleDeclsForName
+  /// or SetNoExternalVisibleDeclsForName.
+  /// \return \c true if any declarations might have been found, \c false if
+  /// we definitely have no declarations with tbis name.
   ///
-  /// The default implementation of this method is a no-op.
-  virtual DeclContextLookupResult
+  /// The default implementation of this method is a no-op returning \c false.
+  virtual bool
   FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name);
 
+  /// \brief Ensures that the table of all visible declarations inside this
+  /// context is up to date.
+  ///
+  /// The default implementation of this function is a no-op.
+  virtual void completeVisibleDeclsMap(const DeclContext *DC);
+
+  /// \brief Retrieve the module that corresponds to the given module ID.
+  virtual Module *getModule(unsigned ID) { return nullptr; }
+
   /// \brief Finds all declarations lexically contained within the given
   /// DeclContext, after applying an optional filter predicate.
   ///
@@ -144,7 +169,7 @@ public:
   /// \return true if an error occurred
   ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
                                 SmallVectorImpl<Decl*> &Result) {
-    return FindExternalLexicalDecls(DC, 0, Result);
+    return FindExternalLexicalDecls(DC, nullptr, Result);
   }
 
   template <typename DeclTy>
@@ -153,36 +178,52 @@ public:
     return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result);
   }
 
+  /// \brief Get the decls that are contained in a file in the Offset/Length
+  /// range. \p Length can be 0 to indicate a point at \p Offset instead of
+  /// a range.
+  virtual void FindFileRegionDecls(FileID File, unsigned Offset,
+                                   unsigned Length,
+                                   SmallVectorImpl<Decl *> &Decls);
+
+  /// \brief Gives the external AST source an opportunity to complete
+  /// the redeclaration chain for a declaration. Called each time we
+  /// need the most recent declaration of a declaration after the
+  /// generation count is incremented.
+  virtual void CompleteRedeclChain(const Decl *D);
+
   /// \brief Gives the external AST source an opportunity to complete
   /// an incomplete type.
-  virtual void CompleteType(TagDecl *Tag) {}
+  virtual void CompleteType(TagDecl *Tag);
 
   /// \brief Gives the external AST source an opportunity to complete an
   /// incomplete Objective-C class.
   ///
   /// This routine will only be invoked if the "externally completed" bit is
-  /// set on the ObjCInterfaceDecl via the function 
+  /// set on the ObjCInterfaceDecl via the function
   /// \c ObjCInterfaceDecl::setExternallyCompleted().
-  virtual void CompleteType(ObjCInterfaceDecl *Class) { }
+  virtual void CompleteType(ObjCInterfaceDecl *Class);
+
+  /// \brief Loads comment ranges.
+  virtual void ReadComments();
 
   /// \brief Notify ExternalASTSource that we started deserialization of
   /// a decl or type so until FinishedDeserializing is called there may be
   /// decls that are initializing. Must be paired with FinishedDeserializing.
   ///
   /// The default implementation of this method is a no-op.
-  virtual void StartedDeserializing() { }
+  virtual void StartedDeserializing();
 
   /// \brief Notify ExternalASTSource that we finished the deserialization of
   /// a decl or type. Must be paired with StartedDeserializing.
   ///
   /// The default implementation of this method is a no-op.
-  virtual void FinishedDeserializing() { }
+  virtual void FinishedDeserializing();
 
   /// \brief Function that will be invoked when we begin parsing a new
   /// translation unit involving this external AST source.
   ///
   /// The default implementation of this method is a no-op.
-  virtual void StartTranslationUnit(ASTConsumer *Consumer) { }
+  virtual void StartTranslationUnit(ASTConsumer *Consumer);
 
   /// \brief Print any statistics that have been gathered regarding
   /// the external AST source.
@@ -190,6 +231,40 @@ public:
   /// The default implementation of this method is a no-op.
   virtual void PrintStats();
   
+  
+  /// \brief Perform layout on the given record.
+  ///
+  /// This routine allows the external AST source to provide an specific 
+  /// layout for a record, overriding the layout that would normally be
+  /// constructed. It is intended for clients who receive specific layout
+  /// details rather than source code (such as LLDB). The client is expected
+  /// to fill in the field offsets, base offsets, virtual base offsets, and
+  /// complete object size.
+  ///
+  /// \param Record The record whose layout is being requested.
+  ///
+  /// \param Size The final size of the record, in bits.
+  ///
+  /// \param Alignment The final alignment of the record, in bits.
+  ///
+  /// \param FieldOffsets The offset of each of the fields within the record,
+  /// expressed in bits. All of the fields must be provided with offsets.
+  ///
+  /// \param BaseOffsets The offset of each of the direct, non-virtual base
+  /// classes. If any bases are not given offsets, the bases will be laid 
+  /// out according to the ABI.
+  ///
+  /// \param VirtualBaseOffsets The offset of each of the virtual base classes
+  /// (either direct or not). If any bases are not given offsets, the bases will be laid 
+  /// out according to the ABI.
+  /// 
+  /// \returns true if the record layout was provided, false otherwise.
+  virtual bool layoutRecordType(
+      const RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
+      llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets,
+      llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets,
+      llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets);
+
   //===--------------------------------------------------------------------===//
   // Queries for performance analysis.
   //===--------------------------------------------------------------------===//
@@ -216,11 +291,14 @@ protected:
   static DeclContextLookupResult
   SetExternalVisibleDeclsForName(const DeclContext *DC,
                                  DeclarationName Name,
-                                 SmallVectorImpl<NamedDecl*> &Decls);
+                                 ArrayRef<NamedDecl*> Decls);
 
   static DeclContextLookupResult
   SetNoExternalVisibleDeclsForName(const DeclContext *DC,
                                    DeclarationName Name);
+
+  /// \brief Increment the current generation.
+  uint32_t incrementGeneration(ASTContext &C);
 };
 
 /// \brief A lazy pointer to an AST node (of base type T) that resides
@@ -266,7 +344,12 @@ public:
   /// \brief Whether this pointer is non-NULL.
   ///
   /// This operation does not require the AST node to be deserialized.
-  operator bool() const { return Ptr != 0; }
+  LLVM_EXPLICIT operator bool() const { return Ptr != 0; }
+
+  /// \brief Whether this pointer is non-NULL.
+  ///
+  /// This operation does not require the AST node to be deserialized.
+  bool isValid() const { return Ptr != 0; }
 
   /// \brief Whether this pointer is currently stored as an offset.
   bool isOffset() const { return Ptr & 0x01; }
@@ -286,6 +369,100 @@ public:
   }
 };
 
+/// \brief A lazy value (of type T) that is within an AST node of type Owner,
+/// where the value might change in later generations of the external AST
+/// source.
+template<typename Owner, typename T, void (ExternalASTSource::*Update)(Owner)>
+struct LazyGenerationalUpdatePtr {
+  /// A cache of the value of this pointer, in the most recent generation in
+  /// which we queried it.
+  struct LazyData {
+    LazyData(ExternalASTSource *Source, T Value)
+        : ExternalSource(Source), LastGeneration(0), LastValue(Value) {}
+    ExternalASTSource *ExternalSource;
+    uint32_t LastGeneration;
+    T LastValue;
+  };
+
+  // Our value is represented as simply T if there is no external AST source.
+  typedef llvm::PointerUnion<T, LazyData*> ValueType;
+  ValueType Value;
+
+  LazyGenerationalUpdatePtr(ValueType V) : Value(V) {}
+
+  // Defined in ASTContext.h
+  static ValueType makeValue(const ASTContext &Ctx, T Value);
+
+public:
+  explicit LazyGenerationalUpdatePtr(const ASTContext &Ctx, T Value = T())
+      : Value(makeValue(Ctx, Value)) {}
+
+  /// Create a pointer that is not potentially updated by later generations of
+  /// the external AST source.
+  enum NotUpdatedTag { NotUpdated };
+  LazyGenerationalUpdatePtr(NotUpdatedTag, T Value = T())
+      : Value(Value) {}
+
+  /// Forcibly set this pointer (which must be lazy) as needing updates.
+  void markIncomplete() {
+    Value.template get<LazyData *>()->LastGeneration = 0;
+  }
+
+  /// Set the value of this pointer, in the current generation.
+  void set(T NewValue) {
+    if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>()) {
+      LazyVal->LastValue = NewValue;
+      return;
+    }
+    Value = NewValue;
+  }
+
+  /// Set the value of this pointer, for this and all future generations.
+  void setNotUpdated(T NewValue) { Value = NewValue; }
+
+  /// Get the value of this pointer, updating its owner if necessary.
+  T get(Owner O) {
+    if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>()) {
+      if (LazyVal->LastGeneration != LazyVal->ExternalSource->getGeneration()) {
+        LazyVal->LastGeneration = LazyVal->ExternalSource->getGeneration();
+        (LazyVal->ExternalSource->*Update)(O);
+      }
+      return LazyVal->LastValue;
+    }
+    return Value.template get<T>();
+  }
+
+  /// Get the most recently computed value of this pointer without updating it.
+  T getNotUpdated() const {
+    if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>())
+      return LazyVal->LastValue;
+    return Value.template get<T>();
+  }
+
+  void *getOpaqueValue() { return Value.getOpaqueValue(); }
+  static LazyGenerationalUpdatePtr getFromOpaqueValue(void *Ptr) {
+    return LazyGenerationalUpdatePtr(ValueType::getFromOpaqueValue(Ptr));
+  }
+};
+} // end namespace clang
+
+/// Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be
+/// placed into a PointerUnion.
+namespace llvm {
+template<typename Owner, typename T,
+         void (clang::ExternalASTSource::*Update)(Owner)>
+struct PointerLikeTypeTraits<
+    clang::LazyGenerationalUpdatePtr<Owner, T, Update>> {
+  typedef clang::LazyGenerationalUpdatePtr<Owner, T, Update> Ptr;
+  static void *getAsVoidPointer(Ptr P) { return P.getOpaqueValue(); }
+  static Ptr getFromVoidPointer(void *P) { return Ptr::getFromOpaqueValue(P); }
+  enum {
+    NumLowBitsAvailable = PointerLikeTypeTraits<T>::NumLowBitsAvailable - 1
+  };
+};
+}
+
+namespace clang {
 /// \brief Represents a lazily-loaded vector of data.
 ///
 /// The lazily-loaded vector of data contains data that is partially loaded
@@ -451,7 +628,7 @@ public:
     
     if (From.Position < 0) {
       Loaded.erase(Loaded.end() + From.Position, Loaded.end());
-      From = begin(0, true);
+      From = begin(nullptr, true);
     }
     
     Local.erase(Local.begin() + From.Position, Local.begin() + To.Position);
@@ -473,4 +650,4 @@ typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t,
 
 } // end namespace clang
 
-#endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
+#endif