diff options
Diffstat (limited to 'include/clang/AST')
42 files changed, 3651 insertions, 867 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 96e41c5..8fd7d6e 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -27,6 +27,7 @@ #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "clang/AST/CanonicalType.h" +#include "clang/AST/RawCommentList.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" @@ -51,7 +52,6 @@ namespace clang { class ASTMutationListener; class IdentifierTable; class SelectorTable; - class SourceManager; class TargetInfo; class CXXABI; // Decls @@ -80,6 +80,10 @@ namespace clang { namespace Builtin { class Context; } + namespace comments { + class FullComment; + } + /// ASTContext - This class holds long-lived AST nodes (such as types and /// decls) that can be referred to throughout the semantic analysis of a file. class ASTContext : public RefCountedBase<ASTContext> { @@ -198,10 +202,9 @@ class ASTContext : public RefCountedBase<ASTContext> { /// \brief The typedef for the __uint128_t type. mutable TypedefDecl *UInt128Decl; - /// BuiltinVaListType - built-in va list type. - /// This is initially null and set by Sema::LazilyCreateBuiltin when - /// a builtin that takes a valist is encountered. - QualType BuiltinVaListType; + /// \brief The typedef for the target specific predefined + /// __builtin_va_list type. + mutable TypedefDecl *BuiltinVaListDecl; /// \brief The typedef for the predefined 'id' type. mutable TypedefDecl *ObjCIdDecl; @@ -392,6 +395,11 @@ public: SourceManager& getSourceManager() { return SourceMgr; } const SourceManager& getSourceManager() const { return SourceMgr; } + + llvm::BumpPtrAllocator &getAllocator() const { + return BumpAlloc; + } + void *Allocate(unsigned Size, unsigned Align = 8) const { return BumpAlloc.Allocate(Size, Align); } @@ -419,6 +427,85 @@ public: return FullSourceLoc(Loc,SourceMgr); } + /// \brief All comments in this translation unit. + RawCommentList Comments; + + /// \brief True if comments are already loaded from ExternalASTSource. + mutable bool CommentsLoaded; + + class RawCommentAndCacheFlags { + public: + enum Kind { + /// We searched for a comment attached to the particular declaration, but + /// didn't find any. + /// + /// getRaw() == 0. + NoCommentInDecl = 0, + + /// We have found a comment attached to this particular declaration. + /// + /// getRaw() != 0. + FromDecl, + + /// This declaration does not have an attached comment, and we have + /// searched the redeclaration chain. + /// + /// If getRaw() == 0, the whole redeclaration chain does not have any + /// comments. + /// + /// If getRaw() != 0, it is a comment propagated from other + /// redeclaration. + FromRedecl + }; + + Kind getKind() const LLVM_READONLY { + return Data.getInt(); + } + + void setKind(Kind K) { + Data.setInt(K); + } + + const RawComment *getRaw() const LLVM_READONLY { + return Data.getPointer(); + } + + void setRaw(const RawComment *RC) { + Data.setPointer(RC); + } + + private: + llvm::PointerIntPair<const RawComment *, 2, Kind> Data; + }; + + /// \brief Mapping from declarations to comments attached to any + /// redeclaration. + /// + /// Raw comments are owned by Comments list. This mapping is populated + /// lazily. + mutable llvm::DenseMap<const Decl *, RawCommentAndCacheFlags> RedeclComments; + + /// \brief Return the documentation comment attached to a given declaration, + /// without looking into cache. + RawComment *getRawCommentForDeclNoCache(const Decl *D) const; + +public: + RawCommentList &getRawCommentList() { + return Comments; + } + + void addComment(const RawComment &RC) { + Comments.addComment(RC, BumpAlloc); + } + + /// \brief Return the documentation comment attached to a given declaration. + /// Returns NULL if no comment is attached. + const RawComment *getRawCommentForAnyRedecl(const Decl *D) const; + + /// Return parsed documentation comment attached to a given declaration. + /// Returns NULL if no comment is attached. + comments::FullComment *getCommentForDecl(const Decl *D) const; + /// \brief Retrieve the attributes for the given declaration. AttrVec& getDeclAttrs(const Decl *D); @@ -557,6 +644,7 @@ public: CanQualType BoolTy; CanQualType CharTy; CanQualType WCharTy; // [C++ 3.9.1p5], integer type in C99. + CanQualType WIntTy; // [C99 7.24.1], integer type unchanged by default promotions. CanQualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99. CanQualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99. CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty; @@ -575,6 +663,10 @@ public: mutable QualType AutoDeductTy; // Deduction against 'auto'. mutable QualType AutoRRefDeductTy; // Deduction against 'auto &&'. + // Type used to help define __builtin_va_list for some targets. + // The type is built when constructing 'BuiltinVaListDecl'. + mutable QualType VaListTagTy; + ASTContext(LangOptions& LOpts, SourceManager &SM, const TargetInfo *t, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins, @@ -929,6 +1021,10 @@ public: /// Used when in C++, as a GCC extension. QualType getUnsignedWCharType() const; + /// getWIntType - In C99, this returns a type compatible with the type + /// defined in <stddef.h> as defined by the target. + QualType getWIntType() const { return WIntTy; } + /// getPointerDiffType - Return the unique type for "ptrdiff_t" (C99 7.17) /// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9). QualType getPointerDiffType() const; @@ -1148,8 +1244,19 @@ public: return getObjCInterfaceType(getObjCProtocolDecl()); } - void setBuiltinVaListType(QualType T); - QualType getBuiltinVaListType() const { return BuiltinVaListType; } + /// \brief Retrieve the C type declaration corresponding to the predefined + /// __builtin_va_list type. + TypedefDecl *getBuiltinVaListDecl() const; + + /// \brief Retrieve the type of the __builtin_va_list type. + QualType getBuiltinVaListType() const { + return getTypeDeclType(getBuiltinVaListDecl()); + } + + /// \brief Retrieve the C type declaration corresponding to the predefined + /// __va_list_tag type used to help define the __builtin_va_list type for + /// some targets. + QualType getVaListTagType() const; /// getCVRQualifiedType - Returns a type with additional const, /// volatile, or restrict qualifiers. @@ -1210,10 +1317,10 @@ public: const TemplateArgument &ArgPack) const; enum GetBuiltinTypeError { - GE_None, //< No error - GE_Missing_stdio, //< Missing a type from <stdio.h> - GE_Missing_setjmp, //< Missing a type from <setjmp.h> - GE_Missing_ucontext //< Missing a type from <ucontext.h> + GE_None, ///< No error + GE_Missing_stdio, ///< Missing a type from <stdio.h> + GE_Missing_setjmp, ///< Missing a type from <setjmp.h> + GE_Missing_ucontext ///< Missing a type from <ucontext.h> }; /// GetBuiltinType - Return the type for the specified builtin. If @@ -1440,15 +1547,11 @@ public: /// \brief Retrieves the default calling convention to use for /// C++ instance methods. - CallingConv getDefaultMethodCallConv(); + CallingConv getDefaultCXXMethodCallConv(bool isVariadic); /// \brief Retrieves the canonical representation of the given /// calling convention. - CallingConv getCanonicalCallConv(CallingConv CC) const { - if (!LangOpts.MRTD && CC == CC_C) - return CC_Default; - return CC; - } + CallingConv getCanonicalCallConv(CallingConv CC) const; /// \brief Determines whether two calling conventions name the same /// calling convention. @@ -1463,7 +1566,7 @@ public: /// be used to refer to a given template. For most templates, this /// expression is just the template declaration itself. For example, /// the template std::vector can be referred to via a variety of - /// names---std::vector, ::std::vector, vector (if vector is in + /// names---std::vector, \::std::vector, vector (if vector is in /// scope), etc.---but all of these names map down to the same /// TemplateDecl, which is used to form the canonical template name. /// @@ -1523,12 +1626,12 @@ public: /// This routine adjusts the given parameter type @p T to the actual /// parameter type used by semantic analysis (C99 6.7.5.3p[7,8], /// C++ [dcl.fct]p3). The adjusted parameter type is returned. - QualType getAdjustedParameterType(QualType T); + QualType getAdjustedParameterType(QualType T) const; /// \brief Retrieve the parameter type as adjusted for use in the signature /// of a function, decaying array and function types and removing top-level /// cv-qualifiers. - QualType getSignatureParameterType(QualType T); + QualType getSignatureParameterType(QualType T) const; /// getArrayDecayedType - Return the properly qualified result of decaying the /// specified array type to a pointer. This operation is non-trivial when @@ -1700,7 +1803,7 @@ public: /// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists. ObjCCategoryImplDecl *getObjCImplementation(ObjCCategoryDecl *D); - /// \brief returns true if there is at lease one @implementation in TU. + /// \brief returns true if there is at least one \@implementation in TU. bool AnyObjCImplementation() { return !ObjCImpls.empty(); } @@ -1716,15 +1819,12 @@ public: /// interface, or null if non exists. const ObjCMethodDecl *getObjCMethodRedeclaration( const ObjCMethodDecl *MD) const { - llvm::DenseMap<const ObjCMethodDecl*, const ObjCMethodDecl*>::const_iterator - I = ObjCMethodRedecls.find(MD); - if (I == ObjCMethodRedecls.end()) - return 0; - return I->second; + return ObjCMethodRedecls.lookup(MD); } void setObjCMethodRedeclaration(const ObjCMethodDecl *MD, const ObjCMethodDecl *Redecl) { + assert(!getObjCMethodRedeclaration(MD) && "MD already has a redeclaration"); ObjCMethodRedecls[MD] = Redecl; } diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index 7157efe..46a9881 100644 --- a/include/clang/AST/ASTImporter.h +++ b/include/clang/AST/ASTImporter.h @@ -271,7 +271,8 @@ namespace clang { /// \brief Determine whether the given types are structurally /// equivalent. - bool IsStructurallyEquivalent(QualType From, QualType To); + bool IsStructurallyEquivalent(QualType From, QualType To, + bool Complain = true); }; } diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h index 217dfad..4ff5ea3 100644 --- a/include/clang/AST/ASTVector.h +++ b/include/clang/AST/ASTVector.h @@ -374,7 +374,7 @@ void ASTVector<T>::grow(ASTContext &C, size_t MinSize) { NewCapacity = MinSize; // Allocate the memory from the ASTContext. - T *NewElts = new (C) T[NewCapacity]; + T *NewElts = new (C, llvm::alignOf<T>()) T[NewCapacity]; // Copy the elements over. if (llvm::is_class<T>::value) { @@ -387,7 +387,7 @@ void ASTVector<T>::grow(ASTContext &C, size_t MinSize) { memcpy(NewElts, Begin, CurSize * sizeof(T)); } - C.Deallocate(Begin); + // ASTContext never frees any memory. Begin = NewElts; End = NewElts+CurSize; Capacity = Begin+NewCapacity; diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index ef1aa25..27b44d4 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -1,4 +1,4 @@ -//===--- Attr.h - Classes for representing expressions ----------*- C++ -*-===// +//===--- Attr.h - Classes for representing attributes ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -147,14 +147,12 @@ public: typedef SmallVector<Attr*, 2> AttrVec; typedef SmallVector<const Attr*, 2> ConstAttrVec; -/// DestroyAttrs - Destroy the contents of an AttrVec. -inline void DestroyAttrs (AttrVec& V, ASTContext &C) { -} - /// specific_attr_iterator - Iterates over a subrange of an AttrVec, only /// providing attributes that are of a specifc type. -template <typename SpecificAttr> +template <typename SpecificAttr, typename Container = AttrVec> class specific_attr_iterator { + typedef typename Container::const_iterator Iterator; + /// Current - The current, underlying iterator. /// In order to ensure we don't dereference an invalid iterator unless /// specifically requested, we don't necessarily advance this all the @@ -162,14 +160,14 @@ class specific_attr_iterator { /// operation is acting on what should be a past-the-end iterator, /// then we offer no guarantees, but this way we do not dererence a /// past-the-end iterator when we move to a past-the-end position. - mutable AttrVec::const_iterator Current; + mutable Iterator Current; void AdvanceToNext() const { while (!isa<SpecificAttr>(*Current)) ++Current; } - void AdvanceToNext(AttrVec::const_iterator I) const { + void AdvanceToNext(Iterator I) const { while (Current != I && !isa<SpecificAttr>(*Current)) ++Current; } @@ -182,7 +180,7 @@ public: typedef std::ptrdiff_t difference_type; specific_attr_iterator() : Current() { } - explicit specific_attr_iterator(AttrVec::const_iterator i) : Current(i) { } + explicit specific_attr_iterator(Iterator i) : Current(i) { } reference operator*() const { AdvanceToNext(); @@ -217,23 +215,27 @@ public: } }; -template <typename T> -inline specific_attr_iterator<T> specific_attr_begin(const AttrVec& vec) { - return specific_attr_iterator<T>(vec.begin()); +template <typename SpecificAttr, typename Container> +inline specific_attr_iterator<SpecificAttr, Container> + specific_attr_begin(const Container& container) { + return specific_attr_iterator<SpecificAttr, Container>(container.begin()); } -template <typename T> -inline specific_attr_iterator<T> specific_attr_end(const AttrVec& vec) { - return specific_attr_iterator<T>(vec.end()); +template <typename SpecificAttr, typename Container> +inline specific_attr_iterator<SpecificAttr, Container> + specific_attr_end(const Container& container) { + return specific_attr_iterator<SpecificAttr, Container>(container.end()); } -template <typename T> -inline bool hasSpecificAttr(const AttrVec& vec) { - return specific_attr_begin<T>(vec) != specific_attr_end<T>(vec); +template <typename SpecificAttr, typename Container> +inline bool hasSpecificAttr(const Container& container) { + return specific_attr_begin<SpecificAttr>(container) != + specific_attr_end<SpecificAttr>(container); } -template <typename T> -inline T *getSpecificAttr(const AttrVec& vec) { - specific_attr_iterator<T> i = specific_attr_begin<T>(vec); - if (i != specific_attr_end<T>(vec)) +template <typename SpecificAttr, typename Container> +inline SpecificAttr *getSpecificAttr(const Container& container) { + specific_attr_iterator<SpecificAttr, Container> i = + specific_attr_begin<SpecificAttr>(container); + if (i != specific_attr_end<SpecificAttr>(container)) return *i; else return 0; diff --git a/include/clang/AST/BaseSubobject.h b/include/clang/AST/BaseSubobject.h index 6a036bb..da538e3 100644 --- a/include/clang/AST/BaseSubobject.h +++ b/include/clang/AST/BaseSubobject.h @@ -66,9 +66,9 @@ template<> struct DenseMapInfo<clang::BaseSubobject> { } static unsigned getHashValue(const clang::BaseSubobject &Base) { - return - DenseMapInfo<const clang::CXXRecordDecl *>::getHashValue(Base.getBase()) ^ - DenseMapInfo<int64_t>::getHashValue(Base.getBaseOffset().getQuantity()); + typedef std::pair<const clang::CXXRecordDecl *, clang::CharUnits> PairTy; + return DenseMapInfo<PairTy>::getHashValue(PairTy(Base.getBase(), + Base.getBaseOffset())); } static bool isEqual(const clang::BaseSubobject &LHS, diff --git a/include/clang/AST/CMakeLists.txt b/include/clang/AST/CMakeLists.txt index c10cda8..d7458aa 100644 --- a/include/clang/AST/CMakeLists.txt +++ b/include/clang/AST/CMakeLists.txt @@ -15,3 +15,8 @@ clang_tablegen(StmtNodes.inc -gen-clang-stmt-nodes clang_tablegen(DeclNodes.inc -gen-clang-decl-nodes SOURCE ../Basic/DeclNodes.td TARGET ClangDeclNodes) + +clang_tablegen(CommentNodes.inc -gen-clang-comment-nodes + SOURCE ../Basic/CommentNodes.td + TARGET ClangCommentNodes) + diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index 44c554b..ee6eba7 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -128,8 +128,7 @@ class CXXBasePaths { /// while the element contains the number of non-virtual base /// class subobjects for that class type. The key of the map is /// the cv-unqualified canonical type of the base class subobject. - std::map<QualType, std::pair<bool, unsigned>, QualTypeOrdering> - ClassSubobjects; + llvm::SmallDenseMap<QualType, std::pair<bool, unsigned>, 8> ClassSubobjects; /// FindAmbiguities - Whether Sema::IsDerivedFrom should try find /// ambiguous paths while it is looking for a path from a derived diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h new file mode 100644 index 0000000..01aaac3 --- /dev/null +++ b/include/clang/AST/Comment.h @@ -0,0 +1,1059 @@ +//===--- Comment.h - Comment AST nodes --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines comment AST nodes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_COMMENT_H +#define LLVM_CLANG_AST_COMMENT_H + +#include "clang/Basic/SourceLocation.h" +#include "clang/AST/Type.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" + +namespace clang { +class Decl; +class ParmVarDecl; +class TemplateParameterList; + +namespace comments { + +/// Any part of the comment. +/// Abstract class. +class Comment { +protected: + /// Preferred location to show caret. + SourceLocation Loc; + + /// Source range of this AST node. + SourceRange Range; + + class CommentBitfields { + friend class Comment; + + /// Type of this AST node. + unsigned Kind : 8; + }; + enum { NumCommentBits = 8 }; + + class InlineContentCommentBitfields { + friend class InlineContentComment; + + unsigned : NumCommentBits; + + /// True if there is a newline after this inline content node. + /// (There is no separate AST node for a newline.) + unsigned HasTrailingNewline : 1; + }; + enum { NumInlineContentCommentBits = NumCommentBits + 1 }; + + class TextCommentBitfields { + friend class TextComment; + + unsigned : NumInlineContentCommentBits; + + /// True if \c IsWhitespace field contains a valid value. + mutable unsigned IsWhitespaceValid : 1; + + /// True if this comment AST node contains only whitespace. + mutable unsigned IsWhitespace : 1; + }; + enum { NumTextCommentBits = NumInlineContentCommentBits + 2 }; + + class InlineCommandCommentBitfields { + friend class InlineCommandComment; + + unsigned : NumInlineContentCommentBits; + + unsigned RenderKind : 2; + }; + enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 1 }; + + class HTMLStartTagCommentBitfields { + friend class HTMLStartTagComment; + + unsigned : NumInlineContentCommentBits; + + /// True if this tag is self-closing (e. g., <br />). This is based on tag + /// spelling in comment (plain <br> would not set this flag). + unsigned IsSelfClosing : 1; + }; + enum { NumHTMLStartTagCommentBits = NumInlineContentCommentBits + 1 }; + + class ParagraphCommentBitfields { + friend class ParagraphComment; + + unsigned : NumCommentBits; + + /// True if \c IsWhitespace field contains a valid value. + mutable unsigned IsWhitespaceValid : 1; + + /// True if this comment AST node contains only whitespace. + mutable unsigned IsWhitespace : 1; + }; + enum { NumParagraphCommentBits = NumCommentBits + 2 }; + + class ParamCommandCommentBitfields { + friend class ParamCommandComment; + + unsigned : NumCommentBits; + + /// Parameter passing direction, see ParamCommandComment::PassDirection. + unsigned Direction : 2; + + /// True if direction was specified explicitly in the comment. + unsigned IsDirectionExplicit : 1; + }; + enum { NumParamCommandCommentBits = 11 }; + + union { + CommentBitfields CommentBits; + InlineContentCommentBitfields InlineContentCommentBits; + TextCommentBitfields TextCommentBits; + InlineCommandCommentBitfields InlineCommandCommentBits; + HTMLStartTagCommentBitfields HTMLStartTagCommentBits; + ParagraphCommentBitfields ParagraphCommentBits; + ParamCommandCommentBitfields ParamCommandCommentBits; + }; + + void setSourceRange(SourceRange SR) { + Range = SR; + } + + void setLocation(SourceLocation L) { + Loc = L; + } + +public: + enum CommentKind { + NoCommentKind = 0, +#define COMMENT(CLASS, PARENT) CLASS##Kind, +#define COMMENT_RANGE(BASE, FIRST, LAST) \ + First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind, +#define LAST_COMMENT_RANGE(BASE, FIRST, LAST) \ + First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind +#define ABSTRACT_COMMENT(COMMENT) +#include "clang/AST/CommentNodes.inc" + }; + + Comment(CommentKind K, + SourceLocation LocBegin, + SourceLocation LocEnd) : + Loc(LocBegin), Range(SourceRange(LocBegin, LocEnd)) { + CommentBits.Kind = K; + } + + CommentKind getCommentKind() const { + return static_cast<CommentKind>(CommentBits.Kind); + } + + const char *getCommentKindName() const; + + LLVM_ATTRIBUTE_USED void dump() const; + LLVM_ATTRIBUTE_USED void dump(SourceManager &SM) const; + void dump(llvm::raw_ostream &OS, SourceManager *SM) const; + + static bool classof(const Comment *) { return true; } + + SourceRange getSourceRange() const LLVM_READONLY { return Range; } + + SourceLocation getLocStart() const LLVM_READONLY { + return Range.getBegin(); + } + + SourceLocation getLocEnd() const LLVM_READONLY { + return Range.getEnd(); + } + + SourceLocation getLocation() const LLVM_READONLY { return Loc; } + + typedef Comment * const *child_iterator; + + child_iterator child_begin() const; + child_iterator child_end() const; + + // TODO: const child iterator + + unsigned child_count() const { + return child_end() - child_begin(); + } +}; + +/// Inline content (contained within a block). +/// Abstract class. +class InlineContentComment : public Comment { +protected: + InlineContentComment(CommentKind K, + SourceLocation LocBegin, + SourceLocation LocEnd) : + Comment(K, LocBegin, LocEnd) { + InlineContentCommentBits.HasTrailingNewline = 0; + } + +public: + static bool classof(const Comment *C) { + return C->getCommentKind() >= FirstInlineContentCommentConstant && + C->getCommentKind() <= LastInlineContentCommentConstant; + } + + static bool classof(const InlineContentComment *) { return true; } + + void addTrailingNewline() { + InlineContentCommentBits.HasTrailingNewline = 1; + } + + bool hasTrailingNewline() const { + return InlineContentCommentBits.HasTrailingNewline; + } +}; + +/// Plain text. +class TextComment : public InlineContentComment { + StringRef Text; + +public: + TextComment(SourceLocation LocBegin, + SourceLocation LocEnd, + StringRef Text) : + InlineContentComment(TextCommentKind, LocBegin, LocEnd), + Text(Text) { + TextCommentBits.IsWhitespaceValid = false; + } + + static bool classof(const Comment *C) { + return C->getCommentKind() == TextCommentKind; + } + + static bool classof(const TextComment *) { return true; } + + child_iterator child_begin() const { return NULL; } + + child_iterator child_end() const { return NULL; } + + StringRef getText() const LLVM_READONLY { return Text; } + + bool isWhitespace() const { + if (TextCommentBits.IsWhitespaceValid) + return TextCommentBits.IsWhitespace; + + TextCommentBits.IsWhitespace = isWhitespaceNoCache(); + TextCommentBits.IsWhitespaceValid = true; + return TextCommentBits.IsWhitespace; + } + +private: + bool isWhitespaceNoCache() const; +}; + +/// A command with word-like arguments that is considered inline content. +class InlineCommandComment : public InlineContentComment { +public: + struct Argument { + SourceRange Range; + StringRef Text; + + Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { } + }; + + /// The most appropriate rendering mode for this command, chosen on command + /// semantics in Doxygen. + enum RenderKind { + RenderNormal, + RenderBold, + RenderMonospaced, + RenderEmphasized + }; + +protected: + /// Command name. + StringRef Name; + + /// Command arguments. + llvm::ArrayRef<Argument> Args; + +public: + InlineCommandComment(SourceLocation LocBegin, + SourceLocation LocEnd, + StringRef Name, + RenderKind RK, + llvm::ArrayRef<Argument> Args) : + InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd), + Name(Name), Args(Args) { + InlineCommandCommentBits.RenderKind = RK; + } + + static bool classof(const Comment *C) { + return C->getCommentKind() == InlineCommandCommentKind; + } + + static bool classof(const InlineCommandComment *) { return true; } + + child_iterator child_begin() const { return NULL; } + + child_iterator child_end() const { return NULL; } + + StringRef getCommandName() const { + return Name; + } + + SourceRange getCommandNameRange() const { + return SourceRange(getLocStart().getLocWithOffset(-1), + getLocEnd()); + } + + RenderKind getRenderKind() const { + return static_cast<RenderKind>(InlineCommandCommentBits.RenderKind); + } + + unsigned getNumArgs() const { + return Args.size(); + } + + StringRef getArgText(unsigned Idx) const { + return Args[Idx].Text; + } + + SourceRange getArgRange(unsigned Idx) const { + return Args[Idx].Range; + } +}; + +/// Abstract class for opening and closing HTML tags. HTML tags are always +/// treated as inline content (regardless HTML semantics); opening and closing +/// tags are not matched. +class HTMLTagComment : public InlineContentComment { +protected: + StringRef TagName; + SourceRange TagNameRange; + + HTMLTagComment(CommentKind K, + SourceLocation LocBegin, + SourceLocation LocEnd, + StringRef TagName, + SourceLocation TagNameBegin, + SourceLocation TagNameEnd) : + InlineContentComment(K, LocBegin, LocEnd), + TagName(TagName), + TagNameRange(TagNameBegin, TagNameEnd) { + setLocation(TagNameBegin); + } + +public: + static bool classof(const Comment *C) { + return C->getCommentKind() >= FirstHTMLTagCommentConstant && + C->getCommentKind() <= LastHTMLTagCommentConstant; + } + + static bool classof(const HTMLTagComment *) { return true; } + + StringRef getTagName() const LLVM_READONLY { return TagName; } + + SourceRange getTagNameSourceRange() const LLVM_READONLY { + SourceLocation L = getLocation(); + return SourceRange(L.getLocWithOffset(1), + L.getLocWithOffset(1 + TagName.size())); + } +}; + +/// An opening HTML tag with attributes. +class HTMLStartTagComment : public HTMLTagComment { +public: + class Attribute { + public: + SourceLocation NameLocBegin; + StringRef Name; + + SourceLocation EqualsLoc; + + SourceRange ValueRange; + StringRef Value; + + Attribute() { } + + Attribute(SourceLocation NameLocBegin, StringRef Name) : + NameLocBegin(NameLocBegin), Name(Name), + EqualsLoc(SourceLocation()), + ValueRange(SourceRange()), Value(StringRef()) + { } + + Attribute(SourceLocation NameLocBegin, StringRef Name, + SourceLocation EqualsLoc, + SourceRange ValueRange, StringRef Value) : + NameLocBegin(NameLocBegin), Name(Name), + EqualsLoc(EqualsLoc), + ValueRange(ValueRange), Value(Value) + { } + + SourceLocation getNameLocEnd() const { + return NameLocBegin.getLocWithOffset(Name.size()); + } + + SourceRange getNameRange() const { + return SourceRange(NameLocBegin, getNameLocEnd()); + } + }; + +private: + ArrayRef<Attribute> Attributes; + +public: + HTMLStartTagComment(SourceLocation LocBegin, + StringRef TagName) : + HTMLTagComment(HTMLStartTagCommentKind, + LocBegin, LocBegin.getLocWithOffset(1 + TagName.size()), + TagName, + LocBegin.getLocWithOffset(1), + LocBegin.getLocWithOffset(1 + TagName.size())) { + HTMLStartTagCommentBits.IsSelfClosing = false; + } + + static bool classof(const Comment *C) { + return C->getCommentKind() == HTMLStartTagCommentKind; + } + + static bool classof(const HTMLStartTagComment *) { return true; } + + child_iterator child_begin() const { return NULL; } + + child_iterator child_end() const { return NULL; } + + unsigned getNumAttrs() const { + return Attributes.size(); + } + + const Attribute &getAttr(unsigned Idx) const { + return Attributes[Idx]; + } + + void setAttrs(ArrayRef<Attribute> Attrs) { + Attributes = Attrs; + if (!Attrs.empty()) { + const Attribute &Attr = Attrs.back(); + SourceLocation L = Attr.ValueRange.getEnd(); + if (L.isValid()) + Range.setEnd(L); + else { + Range.setEnd(Attr.getNameLocEnd()); + } + } + } + + void setGreaterLoc(SourceLocation GreaterLoc) { + Range.setEnd(GreaterLoc); + } + + bool isSelfClosing() const { + return HTMLStartTagCommentBits.IsSelfClosing; + } + + void setSelfClosing() { + HTMLStartTagCommentBits.IsSelfClosing = true; + } +}; + +/// A closing HTML tag. +class HTMLEndTagComment : public HTMLTagComment { +public: + HTMLEndTagComment(SourceLocation LocBegin, + SourceLocation LocEnd, + StringRef TagName) : + HTMLTagComment(HTMLEndTagCommentKind, + LocBegin, LocEnd, + TagName, + LocBegin.getLocWithOffset(2), + LocBegin.getLocWithOffset(2 + TagName.size())) + { } + + static bool classof(const Comment *C) { + return C->getCommentKind() == HTMLEndTagCommentKind; + } + + static bool classof(const HTMLEndTagComment *) { return true; } + + child_iterator child_begin() const { return NULL; } + + child_iterator child_end() const { return NULL; } +}; + +/// Block content (contains inline content). +/// Abstract class. +class BlockContentComment : public Comment { +protected: + BlockContentComment(CommentKind K, + SourceLocation LocBegin, + SourceLocation LocEnd) : + Comment(K, LocBegin, LocEnd) + { } + +public: + static bool classof(const Comment *C) { + return C->getCommentKind() >= FirstBlockContentCommentConstant && + C->getCommentKind() <= LastBlockContentCommentConstant; + } + + static bool classof(const BlockContentComment *) { return true; } +}; + +/// A single paragraph that contains inline content. +class ParagraphComment : public BlockContentComment { + llvm::ArrayRef<InlineContentComment *> Content; + +public: + ParagraphComment(llvm::ArrayRef<InlineContentComment *> Content) : + BlockContentComment(ParagraphCommentKind, + SourceLocation(), + SourceLocation()), + Content(Content) { + if (Content.empty()) { + ParagraphCommentBits.IsWhitespace = true; + ParagraphCommentBits.IsWhitespaceValid = true; + return; + } + + ParagraphCommentBits.IsWhitespaceValid = false; + + setSourceRange(SourceRange(Content.front()->getLocStart(), + Content.back()->getLocEnd())); + setLocation(Content.front()->getLocStart()); + } + + static bool classof(const Comment *C) { + return C->getCommentKind() == ParagraphCommentKind; + } + + static bool classof(const ParagraphComment *) { return true; } + + child_iterator child_begin() const { + return reinterpret_cast<child_iterator>(Content.begin()); + } + + child_iterator child_end() const { + return reinterpret_cast<child_iterator>(Content.end()); + } + + bool isWhitespace() const { + if (ParagraphCommentBits.IsWhitespaceValid) + return ParagraphCommentBits.IsWhitespace; + + ParagraphCommentBits.IsWhitespace = isWhitespaceNoCache(); + ParagraphCommentBits.IsWhitespaceValid = true; + return ParagraphCommentBits.IsWhitespace; + } + +private: + bool isWhitespaceNoCache() const; +}; + +/// A command that has zero or more word-like arguments (number of word-like +/// arguments depends on command name) and a paragraph as an argument +/// (e. g., \\brief). +class BlockCommandComment : public BlockContentComment { +public: + struct Argument { + SourceRange Range; + StringRef Text; + + Argument() { } + Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { } + }; + +protected: + /// Command name. + StringRef Name; + + /// Word-like arguments. + llvm::ArrayRef<Argument> Args; + + /// Paragraph argument. + ParagraphComment *Paragraph; + + BlockCommandComment(CommentKind K, + SourceLocation LocBegin, + SourceLocation LocEnd, + StringRef Name) : + BlockContentComment(K, LocBegin, LocEnd), + Name(Name), + Paragraph(NULL) { + setLocation(getCommandNameRange().getBegin()); + } + +public: + BlockCommandComment(SourceLocation LocBegin, + SourceLocation LocEnd, + StringRef Name) : + BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd), + Name(Name), + Paragraph(NULL) { + setLocation(getCommandNameRange().getBegin()); + } + + static bool classof(const Comment *C) { + return C->getCommentKind() >= FirstBlockCommandCommentConstant && + C->getCommentKind() <= LastBlockCommandCommentConstant; + } + + static bool classof(const BlockCommandComment *) { return true; } + + child_iterator child_begin() const { + return reinterpret_cast<child_iterator>(&Paragraph); + } + + child_iterator child_end() const { + return reinterpret_cast<child_iterator>(&Paragraph + 1); + } + + StringRef getCommandName() const { + return Name; + } + + SourceRange getCommandNameRange() const { + return SourceRange(getLocStart().getLocWithOffset(1), + getLocStart().getLocWithOffset(1 + Name.size())); + } + + unsigned getNumArgs() const { + return Args.size(); + } + + StringRef getArgText(unsigned Idx) const { + return Args[Idx].Text; + } + + SourceRange getArgRange(unsigned Idx) const { + return Args[Idx].Range; + } + + void setArgs(llvm::ArrayRef<Argument> A) { + Args = A; + if (Args.size() > 0) { + SourceLocation NewLocEnd = Args.back().Range.getEnd(); + if (NewLocEnd.isValid()) + setSourceRange(SourceRange(getLocStart(), NewLocEnd)); + } + } + + ParagraphComment *getParagraph() const LLVM_READONLY { + return Paragraph; + } + + bool hasNonWhitespaceParagraph() const { + return Paragraph && !Paragraph->isWhitespace(); + } + + void setParagraph(ParagraphComment *PC) { + Paragraph = PC; + SourceLocation NewLocEnd = PC->getLocEnd(); + if (NewLocEnd.isValid()) + setSourceRange(SourceRange(getLocStart(), NewLocEnd)); + } +}; + +/// Doxygen \\param command. +class ParamCommandComment : public BlockCommandComment { +private: + /// Parameter index in the function declaration. + unsigned ParamIndex; + +public: + enum { InvalidParamIndex = ~0U }; + + ParamCommandComment(SourceLocation LocBegin, + SourceLocation LocEnd, + StringRef Name) : + BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd, Name), + ParamIndex(InvalidParamIndex) { + ParamCommandCommentBits.Direction = In; + ParamCommandCommentBits.IsDirectionExplicit = false; + } + + static bool classof(const Comment *C) { + return C->getCommentKind() == ParamCommandCommentKind; + } + + static bool classof(const ParamCommandComment *) { return true; } + + enum PassDirection { + In, + Out, + InOut + }; + + static const char *getDirectionAsString(PassDirection D); + + PassDirection getDirection() const LLVM_READONLY { + return static_cast<PassDirection>(ParamCommandCommentBits.Direction); + } + + bool isDirectionExplicit() const LLVM_READONLY { + return ParamCommandCommentBits.IsDirectionExplicit; + } + + void setDirection(PassDirection Direction, bool Explicit) { + ParamCommandCommentBits.Direction = Direction; + ParamCommandCommentBits.IsDirectionExplicit = Explicit; + } + + bool hasParamName() const { + return getNumArgs() > 0; + } + + StringRef getParamName() const { + return Args[0].Text; + } + + SourceRange getParamNameRange() const { + return Args[0].Range; + } + + bool isParamIndexValid() const LLVM_READONLY { + return ParamIndex != InvalidParamIndex; + } + + unsigned getParamIndex() const LLVM_READONLY { + assert(isParamIndexValid()); + return ParamIndex; + } + + void setParamIndex(unsigned Index) { + ParamIndex = Index; + assert(isParamIndexValid()); + } +}; + +/// Doxygen \\tparam command, describes a template parameter. +class TParamCommandComment : public BlockCommandComment { +private: + /// If this template parameter name was resolved (found in template parameter + /// list), then this stores a list of position indexes in all template + /// parameter lists. + /// + /// For example: + /// \verbatim + /// template<typename C, template<typename T> class TT> + /// void test(TT<int> aaa); + /// \endverbatim + /// For C: Position = { 0 } + /// For TT: Position = { 1 } + /// For T: Position = { 1, 0 } + llvm::ArrayRef<unsigned> Position; + +public: + TParamCommandComment(SourceLocation LocBegin, + SourceLocation LocEnd, + StringRef Name) : + BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, Name) + { } + + static bool classof(const Comment *C) { + return C->getCommentKind() == TParamCommandCommentKind; + } + + static bool classof(const TParamCommandComment *) { return true; } + + bool hasParamName() const { + return getNumArgs() > 0; + } + + StringRef getParamName() const { + return Args[0].Text; + } + + SourceRange getParamNameRange() const { + return Args[0].Range; + } + + bool isPositionValid() const LLVM_READONLY { + return !Position.empty(); + } + + unsigned getDepth() const { + assert(isPositionValid()); + return Position.size(); + } + + unsigned getIndex(unsigned Depth) const { + assert(isPositionValid()); + return Position[Depth]; + } + + void setPosition(ArrayRef<unsigned> NewPosition) { + Position = NewPosition; + assert(isPositionValid()); + } +}; + +/// A line of text contained in a verbatim block. +class VerbatimBlockLineComment : public Comment { + StringRef Text; + +public: + VerbatimBlockLineComment(SourceLocation LocBegin, + StringRef Text) : + Comment(VerbatimBlockLineCommentKind, + LocBegin, + LocBegin.getLocWithOffset(Text.size())), + Text(Text) + { } + + static bool classof(const Comment *C) { + return C->getCommentKind() == VerbatimBlockLineCommentKind; + } + + static bool classof(const VerbatimBlockLineComment *) { return true; } + + child_iterator child_begin() const { return NULL; } + + child_iterator child_end() const { return NULL; } + + StringRef getText() const LLVM_READONLY { + return Text; + } +}; + +/// A verbatim block command (e. g., preformatted code). Verbatim block has an +/// opening and a closing command and contains multiple lines of text +/// (VerbatimBlockLineComment nodes). +class VerbatimBlockComment : public BlockCommandComment { +protected: + StringRef CloseName; + SourceLocation CloseNameLocBegin; + llvm::ArrayRef<VerbatimBlockLineComment *> Lines; + +public: + VerbatimBlockComment(SourceLocation LocBegin, + SourceLocation LocEnd, + StringRef Name) : + BlockCommandComment(VerbatimBlockCommentKind, + LocBegin, LocEnd, Name) + { } + + static bool classof(const Comment *C) { + return C->getCommentKind() == VerbatimBlockCommentKind; + } + + static bool classof(const VerbatimBlockComment *) { return true; } + + child_iterator child_begin() const { + return reinterpret_cast<child_iterator>(Lines.begin()); + } + + child_iterator child_end() const { + return reinterpret_cast<child_iterator>(Lines.end()); + } + + void setCloseName(StringRef Name, SourceLocation LocBegin) { + CloseName = Name; + CloseNameLocBegin = LocBegin; + } + + void setLines(llvm::ArrayRef<VerbatimBlockLineComment *> L) { + Lines = L; + } + + StringRef getCloseName() const { + return CloseName; + } + + unsigned getNumLines() const { + return Lines.size(); + } + + StringRef getText(unsigned LineIdx) const { + return Lines[LineIdx]->getText(); + } +}; + +/// A verbatim line command. Verbatim line has an opening command, a single +/// line of text (up to the newline after the opening command) and has no +/// closing command. +class VerbatimLineComment : public BlockCommandComment { +protected: + StringRef Text; + SourceLocation TextBegin; + +public: + VerbatimLineComment(SourceLocation LocBegin, + SourceLocation LocEnd, + StringRef Name, + SourceLocation TextBegin, + StringRef Text) : + BlockCommandComment(VerbatimLineCommentKind, + LocBegin, LocEnd, + Name), + Text(Text), + TextBegin(TextBegin) + { } + + static bool classof(const Comment *C) { + return C->getCommentKind() == VerbatimLineCommentKind; + } + + static bool classof(const VerbatimLineComment *) { return true; } + + child_iterator child_begin() const { return NULL; } + + child_iterator child_end() const { return NULL; } + + StringRef getText() const { + return Text; + } + + SourceRange getTextRange() const { + return SourceRange(TextBegin, getLocEnd()); + } +}; + +/// Information about the declaration, useful to clients of FullComment. +struct DeclInfo { + /// Declaration the comment is attached to. Should not be NULL. + const Decl *ThisDecl; + + /// Parameters that can be referenced by \\param if \c ThisDecl is something + /// that we consider a "function". + ArrayRef<const ParmVarDecl *> ParamVars; + + /// Function result type if \c ThisDecl is something that we consider + /// a "function". + QualType ResultType; + + /// Template parameters that can be referenced by \\tparam if \c ThisDecl is + /// a template (\c IsTemplateDecl or \c IsTemplatePartialSpecialization is + /// true). + const TemplateParameterList *TemplateParameters; + + /// A simplified description of \c ThisDecl kind that should be good enough + /// for documentation rendering purposes. + enum DeclKind { + /// Everything else not explicitly mentioned below. + OtherKind, + + /// Something that we consider a "function": + /// \li function, + /// \li function template, + /// \li function template specialization, + /// \li member function, + /// \li member function template, + /// \li member function template specialization, + /// \li ObjC method. + FunctionKind, + + /// Something that we consider a "class": + /// \li class/struct, + /// \li class template, + /// \li class template (partial) specialization. + ClassKind, + + /// Something that we consider a "variable": + /// \li namespace scope variables; + /// \li static and non-static class data members; + /// \li enumerators. + VariableKind, + + /// A C++ namespace. + NamespaceKind, + + /// A C++ typedef-name (a 'typedef' decl specifier or alias-declaration), + /// see \c TypedefNameDecl. + TypedefKind, + + /// An enumeration or scoped enumeration. + EnumKind + }; + + /// What kind of template specialization \c ThisDecl is. + enum TemplateDeclKind { + NotTemplate, + Template, + TemplateSpecialization, + TemplatePartialSpecialization + }; + + /// If false, only \c ThisDecl is valid. + unsigned IsFilled : 1; + + /// Simplified kind of \c ThisDecl, see\c DeclKind enum. + unsigned Kind : 3; + + /// Is \c ThisDecl a template declaration. + unsigned TemplateKind : 2; + + /// Is \c ThisDecl an ObjCMethodDecl. + unsigned IsObjCMethod : 1; + + /// Is \c ThisDecl a non-static member function of C++ class or + /// instance method of ObjC class. + /// Can be true only if \c IsFunctionDecl is true. + unsigned IsInstanceMethod : 1; + + /// Is \c ThisDecl a static member function of C++ class or + /// class method of ObjC class. + /// Can be true only if \c IsFunctionDecl is true. + unsigned IsClassMethod : 1; + + void fill(); + + DeclKind getKind() const LLVM_READONLY { + return static_cast<DeclKind>(Kind); + } + + TemplateDeclKind getTemplateKind() const LLVM_READONLY { + return static_cast<TemplateDeclKind>(TemplateKind); + } +}; + +/// A full comment attached to a declaration, contains block content. +class FullComment : public Comment { + llvm::ArrayRef<BlockContentComment *> Blocks; + + DeclInfo *ThisDeclInfo; + +public: + FullComment(llvm::ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) : + Comment(FullCommentKind, SourceLocation(), SourceLocation()), + Blocks(Blocks), ThisDeclInfo(D) { + if (Blocks.empty()) + return; + + setSourceRange(SourceRange(Blocks.front()->getLocStart(), + Blocks.back()->getLocEnd())); + setLocation(Blocks.front()->getLocStart()); + } + + static bool classof(const Comment *C) { + return C->getCommentKind() == FullCommentKind; + } + + static bool classof(const FullComment *) { return true; } + + child_iterator child_begin() const { + return reinterpret_cast<child_iterator>(Blocks.begin()); + } + + child_iterator child_end() const { + return reinterpret_cast<child_iterator>(Blocks.end()); + } + + const Decl *getDecl() const LLVM_READONLY { + return ThisDeclInfo->ThisDecl; + } + + const DeclInfo *getDeclInfo() const LLVM_READONLY { + if (!ThisDeclInfo->IsFilled) + ThisDeclInfo->fill(); + return ThisDeclInfo; + } +}; + +} // end namespace comments +} // end namespace clang + +#endif + diff --git a/include/clang/AST/CommentBriefParser.h b/include/clang/AST/CommentBriefParser.h new file mode 100644 index 0000000..003c337 --- /dev/null +++ b/include/clang/AST/CommentBriefParser.h @@ -0,0 +1,56 @@ +//===--- CommentBriefParser.h - Dumb comment parser -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a very simple Doxygen comment parser. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CLANG_AST_BRIEF_COMMENT_PARSER_H +#define LLVM_CLANG_AST_BRIEF_COMMENT_PARSER_H + +#include "clang/AST/CommentLexer.h" + +namespace clang { +namespace comments { + +/// A very simple comment parser that extracts "a brief description". +/// +/// Due to a variety of comment styles, it considers the following as "a brief +/// description", in order of priority: +/// \li a \\brief or \\short command, +/// \li the first paragraph, +/// \li a \\result or \\return or \\returns paragraph. +class BriefParser { + Lexer &L; + + const CommandTraits &Traits; + + /// Current lookahead token. + Token Tok; + + SourceLocation ConsumeToken() { + SourceLocation Loc = Tok.getLocation(); + L.lex(Tok); + return Loc; + } + +public: + BriefParser(Lexer &L, const CommandTraits &Traits); + + /// Return \\brief paragraph, if it exists; otherwise return the first + /// paragraph. + std::string Parse(); +}; + +} // end namespace comments +} // end namespace clang + +#endif + diff --git a/include/clang/AST/CommentCommandTraits.h b/include/clang/AST/CommentCommandTraits.h new file mode 100644 index 0000000..f188375 --- /dev/null +++ b/include/clang/AST/CommentCommandTraits.h @@ -0,0 +1,156 @@ +//===--- CommentCommandTraits.h - Comment command properties ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the class that provides information about comment +// commands. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CLANG_AST_COMMENT_COMMAND_TRAITS_H +#define LLVM_CLANG_AST_COMMENT_COMMAND_TRAITS_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSwitch.h" + +namespace clang { +namespace comments { + +/// This class provides informaiton about commands that can be used +/// in comments. +class CommandTraits { +public: + CommandTraits() { } + + /// \brief Check if a given command is a verbatim-like block command. + /// + /// A verbatim-like block command eats every character (except line starting + /// decorations) until matching end command is seen or comment end is hit. + /// + /// \param BeginName name of the command that starts the verbatim block. + /// \param [out] EndName name of the command that ends the verbatim block. + /// + /// \returns true if a given command is a verbatim block command. + bool isVerbatimBlockCommand(StringRef StartName, StringRef &EndName) const; + + /// \brief Register a new verbatim block command. + void addVerbatimBlockCommand(StringRef BeginName, StringRef EndName); + + /// \brief Check if a given command is a verbatim line command. + /// + /// A verbatim-like line command eats everything until a newline is seen or + /// comment end is hit. + bool isVerbatimLineCommand(StringRef Name) const; + + /// \brief Check if a given command is a command that contains a declaration + /// for the entity being documented. + /// + /// For example: + /// \code + /// \fn void f(int a); + /// \endcode + bool isDeclarationCommand(StringRef Name) const; + + /// \brief Register a new verbatim line command. + void addVerbatimLineCommand(StringRef Name); + + /// \brief Check if a given command is a block command (of any kind). + bool isBlockCommand(StringRef Name) const; + + /// \brief Check if a given command is introducing documentation for + /// a function parameter (\\param or an alias). + bool isParamCommand(StringRef Name) const; + + /// \brief Check if a given command is introducing documentation for + /// a template parameter (\\tparam or an alias). + bool isTParamCommand(StringRef Name) const; + + /// \brief Check if a given command is introducing a brief documentation + /// paragraph (\\brief or an alias). + bool isBriefCommand(StringRef Name) const; + + /// \brief Check if a given command is \\brief or an alias. + bool isReturnsCommand(StringRef Name) const; + + /// \returns the number of word-like arguments for a given block command, + /// except for \\param and \\tparam commands -- these have special argument + /// parsers. + unsigned getBlockCommandNumArgs(StringRef Name) const; + + /// \brief Check if a given command is a inline command (of any kind). + bool isInlineCommand(StringRef Name) const; + +private: + struct VerbatimBlockCommand { + StringRef BeginName; + StringRef EndName; + }; + + typedef SmallVector<VerbatimBlockCommand, 4> VerbatimBlockCommandVector; + + /// Registered additional verbatim-like block commands. + VerbatimBlockCommandVector VerbatimBlockCommands; + + struct VerbatimLineCommand { + StringRef Name; + }; + + typedef SmallVector<VerbatimLineCommand, 4> VerbatimLineCommandVector; + + /// Registered verbatim-like line commands. + VerbatimLineCommandVector VerbatimLineCommands; +}; + +inline bool CommandTraits::isBlockCommand(StringRef Name) const { + return isBriefCommand(Name) || isReturnsCommand(Name) || + isParamCommand(Name) || isTParamCommand(Name) || + llvm::StringSwitch<bool>(Name) + .Case("author", true) + .Case("authors", true) + .Case("pre", true) + .Case("post", true) + .Default(false); +} + +inline bool CommandTraits::isParamCommand(StringRef Name) const { + return Name == "param"; +} + +inline bool CommandTraits::isTParamCommand(StringRef Name) const { + return Name == "tparam" || // Doxygen + Name == "templatefield"; // HeaderDoc +} + +inline bool CommandTraits::isBriefCommand(StringRef Name) const { + return Name == "brief" || Name == "short"; +} + +inline bool CommandTraits::isReturnsCommand(StringRef Name) const { + return Name == "returns" || Name == "return" || Name == "result"; +} + +inline unsigned CommandTraits::getBlockCommandNumArgs(StringRef Name) const { + return 0; +} + +inline bool CommandTraits::isInlineCommand(StringRef Name) const { + return llvm::StringSwitch<bool>(Name) + .Case("b", true) + .Cases("c", "p", true) + .Cases("a", "e", "em", true) + .Default(false); +} + +} // end namespace comments +} // end namespace clang + +#endif + diff --git a/include/clang/AST/CommentDiagnostic.h b/include/clang/AST/CommentDiagnostic.h new file mode 100644 index 0000000..6e89410 --- /dev/null +++ b/include/clang/AST/CommentDiagnostic.h @@ -0,0 +1,29 @@ +//===--- CommentDiagnostic.h - Diagnostics for the AST library --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_COMMENTDIAGNOSTIC_H +#define LLVM_CLANG_COMMENTDIAGNOSTIC_H + +#include "clang/Basic/Diagnostic.h" + +namespace clang { + namespace diag { + enum { +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM, +#define COMMENTSTART +#include "clang/Basic/DiagnosticCommentKinds.inc" +#undef DIAG + NUM_BUILTIN_COMMENT_DIAGNOSTICS + }; + } // end namespace diag +} // end namespace clang + +#endif + diff --git a/include/clang/AST/CommentLexer.h b/include/clang/AST/CommentLexer.h new file mode 100644 index 0000000..7a24b11 --- /dev/null +++ b/include/clang/AST/CommentLexer.h @@ -0,0 +1,353 @@ +//===--- CommentLexer.h - Lexer for structured comments ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines lexer for structured comments and supporting token class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_COMMENT_LEXER_H +#define LLVM_CLANG_AST_COMMENT_LEXER_H + +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/raw_ostream.h" + +namespace clang { +namespace comments { + +class Lexer; +class TextTokenRetokenizer; +class CommandTraits; + +namespace tok { +enum TokenKind { + eof, + newline, + text, + command, + verbatim_block_begin, + verbatim_block_line, + verbatim_block_end, + verbatim_line_name, + verbatim_line_text, + html_start_tag, // <tag + html_ident, // attr + html_equals, // = + html_quoted_string, // "blah\"blah" or 'blah\'blah' + html_greater, // > + html_slash_greater, // /> + html_end_tag // </tag +}; +} // end namespace tok + +class CommentOptions { +public: + bool Markdown; +}; + +/// \brief Comment token. +class Token { + friend class Lexer; + friend class TextTokenRetokenizer; + + /// The location of the token. + SourceLocation Loc; + + /// The actual kind of the token. + tok::TokenKind Kind; + + /// Length of the token spelling in comment. Can be 0 for synthenized + /// tokens. + unsigned Length; + + /// Contains text value associated with a token. + const char *TextPtr1; + unsigned TextLen1; + +public: + SourceLocation getLocation() const LLVM_READONLY { return Loc; } + void setLocation(SourceLocation SL) { Loc = SL; } + + SourceLocation getEndLocation() const LLVM_READONLY { + if (Length == 0 || Length == 1) + return Loc; + return Loc.getLocWithOffset(Length - 1); + } + + tok::TokenKind getKind() const LLVM_READONLY { return Kind; } + void setKind(tok::TokenKind K) { Kind = K; } + + bool is(tok::TokenKind K) const LLVM_READONLY { return Kind == K; } + bool isNot(tok::TokenKind K) const LLVM_READONLY { return Kind != K; } + + unsigned getLength() const LLVM_READONLY { return Length; } + void setLength(unsigned L) { Length = L; } + + StringRef getText() const LLVM_READONLY { + assert(is(tok::text)); + return StringRef(TextPtr1, TextLen1); + } + + void setText(StringRef Text) { + assert(is(tok::text)); + TextPtr1 = Text.data(); + TextLen1 = Text.size(); + } + + StringRef getCommandName() const LLVM_READONLY { + assert(is(tok::command)); + return StringRef(TextPtr1, TextLen1); + } + + void setCommandName(StringRef Name) { + assert(is(tok::command)); + TextPtr1 = Name.data(); + TextLen1 = Name.size(); + } + + StringRef getVerbatimBlockName() const LLVM_READONLY { + assert(is(tok::verbatim_block_begin) || is(tok::verbatim_block_end)); + return StringRef(TextPtr1, TextLen1); + } + + void setVerbatimBlockName(StringRef Name) { + assert(is(tok::verbatim_block_begin) || is(tok::verbatim_block_end)); + TextPtr1 = Name.data(); + TextLen1 = Name.size(); + } + + StringRef getVerbatimBlockText() const LLVM_READONLY { + assert(is(tok::verbatim_block_line)); + return StringRef(TextPtr1, TextLen1); + } + + void setVerbatimBlockText(StringRef Text) { + assert(is(tok::verbatim_block_line)); + TextPtr1 = Text.data(); + TextLen1 = Text.size(); + } + + /// Returns the name of verbatim line command. + StringRef getVerbatimLineName() const LLVM_READONLY { + assert(is(tok::verbatim_line_name)); + return StringRef(TextPtr1, TextLen1); + } + + void setVerbatimLineName(StringRef Name) { + assert(is(tok::verbatim_line_name)); + TextPtr1 = Name.data(); + TextLen1 = Name.size(); + } + + StringRef getVerbatimLineText() const LLVM_READONLY { + assert(is(tok::verbatim_line_text)); + return StringRef(TextPtr1, TextLen1); + } + + void setVerbatimLineText(StringRef Text) { + assert(is(tok::verbatim_line_text)); + TextPtr1 = Text.data(); + TextLen1 = Text.size(); + } + + StringRef getHTMLTagStartName() const LLVM_READONLY { + assert(is(tok::html_start_tag)); + return StringRef(TextPtr1, TextLen1); + } + + void setHTMLTagStartName(StringRef Name) { + assert(is(tok::html_start_tag)); + TextPtr1 = Name.data(); + TextLen1 = Name.size(); + } + + StringRef getHTMLIdent() const LLVM_READONLY { + assert(is(tok::html_ident)); + return StringRef(TextPtr1, TextLen1); + } + + void setHTMLIdent(StringRef Name) { + assert(is(tok::html_ident)); + TextPtr1 = Name.data(); + TextLen1 = Name.size(); + } + + StringRef getHTMLQuotedString() const LLVM_READONLY { + assert(is(tok::html_quoted_string)); + return StringRef(TextPtr1, TextLen1); + } + + void setHTMLQuotedString(StringRef Str) { + assert(is(tok::html_quoted_string)); + TextPtr1 = Str.data(); + TextLen1 = Str.size(); + } + + StringRef getHTMLTagEndName() const LLVM_READONLY { + assert(is(tok::html_end_tag)); + return StringRef(TextPtr1, TextLen1); + } + + void setHTMLTagEndName(StringRef Name) { + assert(is(tok::html_end_tag)); + TextPtr1 = Name.data(); + TextLen1 = Name.size(); + } + + void dump(const Lexer &L, const SourceManager &SM) const; +}; + +/// \brief Comment lexer. +class Lexer { +private: + Lexer(const Lexer&); // DO NOT IMPLEMENT + void operator=(const Lexer&); // DO NOT IMPLEMENT + + /// Allocator for strings that are semantic values of tokens and have to be + /// computed (for example, resolved decimal character references). + llvm::BumpPtrAllocator &Allocator; + + const CommandTraits &Traits; + + const char *const BufferStart; + const char *const BufferEnd; + SourceLocation FileLoc; + CommentOptions CommOpts; + + const char *BufferPtr; + + /// One past end pointer for the current comment. For BCPL comments points + /// to newline or BufferEnd, for C comments points to star in '*/'. + const char *CommentEnd; + + enum LexerCommentState { + LCS_BeforeComment, + LCS_InsideBCPLComment, + LCS_InsideCComment, + LCS_BetweenComments + }; + + /// Low-level lexer state, track if we are inside or outside of comment. + LexerCommentState CommentState; + + enum LexerState { + /// Lexing normal comment text + LS_Normal, + + /// Finished lexing verbatim block beginning command, will lex first body + /// line. + LS_VerbatimBlockFirstLine, + + /// Lexing verbatim block body line-by-line, skipping line-starting + /// decorations. + LS_VerbatimBlockBody, + + /// Finished lexing verbatim line beginning command, will lex text (one + /// line). + LS_VerbatimLineText, + + /// Finished lexing \verbatim <TAG \endverbatim part, lexing tag attributes. + LS_HTMLStartTag, + + /// Finished lexing \verbatim </TAG \endverbatim part, lexing '>'. + LS_HTMLEndTag + }; + + /// Current lexing mode. + LexerState State; + + /// If State is LS_VerbatimBlock, contains the name of verbatim end + /// command, including command marker. + SmallString<16> VerbatimBlockEndCommandName; + + /// Given a character reference name (e.g., "lt"), return the character that + /// it stands for (e.g., "<"). + StringRef resolveHTMLNamedCharacterReference(StringRef Name) const; + + /// Given a Unicode codepoint as base-10 integer, return the character. + StringRef resolveHTMLDecimalCharacterReference(StringRef Name) const; + + /// Given a Unicode codepoint as base-16 integer, return the character. + StringRef resolveHTMLHexCharacterReference(StringRef Name) const; + + void formTokenWithChars(Token &Result, const char *TokEnd, + tok::TokenKind Kind) { + const unsigned TokLen = TokEnd - BufferPtr; + Result.setLocation(getSourceLocation(BufferPtr)); + Result.setKind(Kind); + Result.setLength(TokLen); +#ifndef NDEBUG + Result.TextPtr1 = "<UNSET>"; + Result.TextLen1 = 7; +#endif + BufferPtr = TokEnd; + } + + void formTextToken(Token &Result, const char *TokEnd) { + StringRef Text(BufferPtr, TokEnd - BufferPtr); + formTokenWithChars(Result, TokEnd, tok::text); + Result.setText(Text); + } + + SourceLocation getSourceLocation(const char *Loc) const { + assert(Loc >= BufferStart && Loc <= BufferEnd && + "Location out of range for this buffer!"); + + const unsigned CharNo = Loc - BufferStart; + return FileLoc.getLocWithOffset(CharNo); + } + + /// Eat string matching regexp \code \s*\* \endcode. + void skipLineStartingDecorations(); + + /// Lex stuff inside comments. CommentEnd should be set correctly. + void lexCommentText(Token &T); + + void setupAndLexVerbatimBlock(Token &T, + const char *TextBegin, + char Marker, StringRef EndName); + + void lexVerbatimBlockFirstLine(Token &T); + + void lexVerbatimBlockBody(Token &T); + + void setupAndLexVerbatimLine(Token &T, const char *TextBegin); + + void lexVerbatimLineText(Token &T); + + void lexHTMLCharacterReference(Token &T); + + void setupAndLexHTMLStartTag(Token &T); + + void lexHTMLStartTag(Token &T); + + void setupAndLexHTMLEndTag(Token &T); + + void lexHTMLEndTag(Token &T); + +public: + Lexer(llvm::BumpPtrAllocator &Allocator, const CommandTraits &Traits, + SourceLocation FileLoc, const CommentOptions &CommOpts, + const char *BufferStart, const char *BufferEnd); + + void lex(Token &T); + + StringRef getSpelling(const Token &Tok, + const SourceManager &SourceMgr, + bool *Invalid = NULL) const; +}; + +} // end namespace comments +} // end namespace clang + +#endif + diff --git a/include/clang/AST/CommentParser.h b/include/clang/AST/CommentParser.h new file mode 100644 index 0000000..0390799 --- /dev/null +++ b/include/clang/AST/CommentParser.h @@ -0,0 +1,124 @@ +//===--- CommentParser.h - Doxygen comment parser ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the Doxygen comment parser. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_COMMENT_PARSER_H +#define LLVM_CLANG_AST_COMMENT_PARSER_H + +#include "clang/Basic/Diagnostic.h" +#include "clang/AST/CommentLexer.h" +#include "clang/AST/Comment.h" +#include "clang/AST/CommentSema.h" +#include "llvm/Support/Allocator.h" + +namespace clang { +class SourceManager; + +namespace comments { +class CommandTraits; + +/// Doxygen comment parser. +class Parser { + Parser(const Parser&); // DO NOT IMPLEMENT + void operator=(const Parser&); // DO NOT IMPLEMENT + + friend class TextTokenRetokenizer; + + Lexer &L; + + Sema &S; + + /// Allocator for anything that goes into AST nodes. + llvm::BumpPtrAllocator &Allocator; + + /// Source manager for the comment being parsed. + const SourceManager &SourceMgr; + + DiagnosticsEngine &Diags; + + DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) { + return Diags.Report(Loc, DiagID); + } + + const CommandTraits &Traits; + + /// Current lookahead token. We can safely assume that all tokens are from + /// a single source file. + Token Tok; + + /// A stack of additional lookahead tokens. + SmallVector<Token, 8> MoreLATokens; + + void consumeToken() { + if (MoreLATokens.empty()) + L.lex(Tok); + else { + Tok = MoreLATokens.back(); + MoreLATokens.pop_back(); + } + } + + void putBack(const Token &OldTok) { + MoreLATokens.push_back(Tok); + Tok = OldTok; + } + + void putBack(ArrayRef<Token> Toks) { + if (Toks.empty()) + return; + + MoreLATokens.push_back(Tok); + for (const Token *I = &Toks.back(), + *B = &Toks.front(); + I != B; --I) { + MoreLATokens.push_back(*I); + } + + Tok = Toks[0]; + } + +public: + Parser(Lexer &L, Sema &S, llvm::BumpPtrAllocator &Allocator, + const SourceManager &SourceMgr, DiagnosticsEngine &Diags, + const CommandTraits &Traits); + + /// Parse arguments for \\param command. + void parseParamCommandArgs(ParamCommandComment *PC, + TextTokenRetokenizer &Retokenizer); + + /// Parse arguments for \\tparam command. + void parseTParamCommandArgs(TParamCommandComment *TPC, + TextTokenRetokenizer &Retokenizer); + + void parseBlockCommandArgs(BlockCommandComment *BC, + TextTokenRetokenizer &Retokenizer, + unsigned NumArgs); + + BlockCommandComment *parseBlockCommand(); + InlineCommandComment *parseInlineCommand(); + + HTMLStartTagComment *parseHTMLStartTag(); + HTMLEndTagComment *parseHTMLEndTag(); + + BlockContentComment *parseParagraphOrBlockCommand(); + + VerbatimBlockComment *parseVerbatimBlock(); + VerbatimLineComment *parseVerbatimLine(); + BlockContentComment *parseBlockContent(); + FullComment *parseFullComment(); +}; + +} // end namespace comments +} // end namespace clang + +#endif + diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h new file mode 100644 index 0000000..e1756ca --- /dev/null +++ b/include/clang/AST/CommentSema.h @@ -0,0 +1,230 @@ +//===--- CommentSema.h - Doxygen comment semantic analysis ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the semantic analysis class for Doxygen comments. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_COMMENT_SEMA_H +#define LLVM_CLANG_AST_COMMENT_SEMA_H + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/AST/Comment.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/Allocator.h" + +namespace clang { +class Decl; +class SourceMgr; + +namespace comments { +class CommandTraits; + +class Sema { + Sema(const Sema&); // DO NOT IMPLEMENT + void operator=(const Sema&); // DO NOT IMPLEMENT + + /// Allocator for AST nodes. + llvm::BumpPtrAllocator &Allocator; + + /// Source manager for the comment being parsed. + const SourceManager &SourceMgr; + + DiagnosticsEngine &Diags; + + const CommandTraits &Traits; + + /// Information about the declaration this comment is attached to. + DeclInfo *ThisDeclInfo; + + /// Comment AST nodes that correspond to \c ParamVars for which we have + /// found a \\param command or NULL if no documentation was found so far. + /// + /// Has correct size and contains valid values if \c DeclInfo->IsFilled is + /// true. + llvm::SmallVector<ParamCommandComment *, 8> ParamVarDocs; + + /// Comment AST nodes that correspond to parameter names in + /// \c TemplateParameters. + /// + /// Contains a valid value if \c DeclInfo->IsFilled is true. + llvm::StringMap<TParamCommandComment *> TemplateParameterDocs; + + /// AST node for the \\brief command and its aliases. + const BlockCommandComment *BriefCommand; + + /// AST node for the \\returns command and its aliases. + const BlockCommandComment *ReturnsCommand; + + DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) { + return Diags.Report(Loc, DiagID); + } + + /// A stack of HTML tags that are currently open (not matched with closing + /// tags). + SmallVector<HTMLStartTagComment *, 8> HTMLOpenTags; + +public: + Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr, + DiagnosticsEngine &Diags, const CommandTraits &Traits); + + void setDecl(const Decl *D); + + /// Returns a copy of array, owned by Sema's allocator. + template<typename T> + ArrayRef<T> copyArray(ArrayRef<T> Source) { + size_t Size = Source.size(); + if (Size != 0) { + T *Mem = Allocator.Allocate<T>(Size); + std::uninitialized_copy(Source.begin(), Source.end(), Mem); + return llvm::makeArrayRef(Mem, Size); + } else + return llvm::makeArrayRef(static_cast<T *>(NULL), 0); + } + + ParagraphComment *actOnParagraphComment( + ArrayRef<InlineContentComment *> Content); + + BlockCommandComment *actOnBlockCommandStart(SourceLocation LocBegin, + SourceLocation LocEnd, + StringRef Name); + + void actOnBlockCommandArgs(BlockCommandComment *Command, + ArrayRef<BlockCommandComment::Argument> Args); + + void actOnBlockCommandFinish(BlockCommandComment *Command, + ParagraphComment *Paragraph); + + ParamCommandComment *actOnParamCommandStart(SourceLocation LocBegin, + SourceLocation LocEnd, + StringRef Name); + + void actOnParamCommandDirectionArg(ParamCommandComment *Command, + SourceLocation ArgLocBegin, + SourceLocation ArgLocEnd, + StringRef Arg); + + void actOnParamCommandParamNameArg(ParamCommandComment *Command, + SourceLocation ArgLocBegin, + SourceLocation ArgLocEnd, + StringRef Arg); + + void actOnParamCommandFinish(ParamCommandComment *Command, + ParagraphComment *Paragraph); + + TParamCommandComment *actOnTParamCommandStart(SourceLocation LocBegin, + SourceLocation LocEnd, + StringRef Name); + + void actOnTParamCommandParamNameArg(TParamCommandComment *Command, + SourceLocation ArgLocBegin, + SourceLocation ArgLocEnd, + StringRef Arg); + + void actOnTParamCommandFinish(TParamCommandComment *Command, + ParagraphComment *Paragraph); + + InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin, + SourceLocation CommandLocEnd, + StringRef CommandName); + + InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin, + SourceLocation CommandLocEnd, + StringRef CommandName, + SourceLocation ArgLocBegin, + SourceLocation ArgLocEnd, + StringRef Arg); + + InlineContentComment *actOnUnknownCommand(SourceLocation LocBegin, + SourceLocation LocEnd, + StringRef Name); + + TextComment *actOnText(SourceLocation LocBegin, + SourceLocation LocEnd, + StringRef Text); + + VerbatimBlockComment *actOnVerbatimBlockStart(SourceLocation Loc, + StringRef Name); + + VerbatimBlockLineComment *actOnVerbatimBlockLine(SourceLocation Loc, + StringRef Text); + + void actOnVerbatimBlockFinish(VerbatimBlockComment *Block, + SourceLocation CloseNameLocBegin, + StringRef CloseName, + ArrayRef<VerbatimBlockLineComment *> Lines); + + VerbatimLineComment *actOnVerbatimLine(SourceLocation LocBegin, + StringRef Name, + SourceLocation TextBegin, + StringRef Text); + + HTMLStartTagComment *actOnHTMLStartTagStart(SourceLocation LocBegin, + StringRef TagName); + + void actOnHTMLStartTagFinish(HTMLStartTagComment *Tag, + ArrayRef<HTMLStartTagComment::Attribute> Attrs, + SourceLocation GreaterLoc, + bool IsSelfClosing); + + HTMLEndTagComment *actOnHTMLEndTag(SourceLocation LocBegin, + SourceLocation LocEnd, + StringRef TagName); + + FullComment *actOnFullComment(ArrayRef<BlockContentComment *> Blocks); + + void checkBlockCommandEmptyParagraph(BlockCommandComment *Command); + + void checkReturnsCommand(const BlockCommandComment *Command); + + /// Emit diagnostics about duplicate block commands that should be + /// used only once per comment, e.g., \\brief and \\returns. + void checkBlockCommandDuplicate(const BlockCommandComment *Command); + + bool isFunctionDecl(); + bool isTemplateOrSpecialization(); + + ArrayRef<const ParmVarDecl *> getParamVars(); + + /// Extract all important semantic information from + /// \c ThisDeclInfo->ThisDecl into \c ThisDeclInfo members. + void inspectThisDecl(); + + /// Returns index of a function parameter with a given name. + unsigned resolveParmVarReference(StringRef Name, + ArrayRef<const ParmVarDecl *> ParamVars); + + /// Returns index of a function parameter with the name closest to a given + /// typo. + unsigned correctTypoInParmVarReference(StringRef Typo, + ArrayRef<const ParmVarDecl *> ParamVars); + + bool resolveTParamReference(StringRef Name, + const TemplateParameterList *TemplateParameters, + SmallVectorImpl<unsigned> *Position); + + StringRef correctTypoInTParamReference( + StringRef Typo, + const TemplateParameterList *TemplateParameters); + + InlineCommandComment::RenderKind + getInlineCommandRenderKind(StringRef Name) const; + + bool isHTMLEndTagOptional(StringRef Name); + bool isHTMLEndTagForbidden(StringRef Name); +}; + +} // end namespace comments +} // end namespace clang + +#endif + diff --git a/include/clang/AST/CommentVisitor.h b/include/clang/AST/CommentVisitor.h new file mode 100644 index 0000000..47867a6 --- /dev/null +++ b/include/clang/AST/CommentVisitor.h @@ -0,0 +1,66 @@ +//===--- CommentVisitor.h - Visitor for Comment subclasses ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/Comment.h" +#include "llvm/Support/ErrorHandling.h" + +namespace clang { +namespace comments { + +template <typename T> struct make_ptr { typedef T *type; }; +template <typename T> struct make_const_ptr { typedef const T *type; }; + +template<template <typename> class Ptr, typename ImplClass, typename RetTy=void> +class CommentVisitorBase { +public: +#define PTR(CLASS) typename Ptr<CLASS>::type +#define DISPATCH(NAME, CLASS) \ + return static_cast<ImplClass*>(this)->visit ## NAME(static_cast<PTR(CLASS)>(C)) + + RetTy visit(PTR(Comment) C) { + if (!C) + return RetTy(); + + switch (C->getCommentKind()) { + default: llvm_unreachable("Unknown comment kind!"); +#define ABSTRACT_COMMENT(COMMENT) +#define COMMENT(CLASS, PARENT) \ + case Comment::CLASS##Kind: DISPATCH(CLASS, CLASS); +#include "clang/AST/CommentNodes.inc" +#undef ABSTRACT_COMMENT +#undef COMMENT + } + } + + // If the derived class does not implement a certain Visit* method, fall back + // on Visit* method for the superclass. +#define ABSTRACT_COMMENT(COMMENT) COMMENT +#define COMMENT(CLASS, PARENT) \ + RetTy visit ## CLASS(PTR(CLASS) C) { DISPATCH(PARENT, PARENT); } +#include "clang/AST/CommentNodes.inc" +#undef ABSTRACT_COMMENT +#undef COMMENT + + RetTy visitComment(PTR(Comment) C) { return RetTy(); } + +#undef PTR +#undef DISPATCH +}; + +template<typename ImplClass, typename RetTy=void> +class CommentVisitor : + public CommentVisitorBase<make_ptr, ImplClass, RetTy> {}; + +template<typename ImplClass, typename RetTy=void> +class ConstCommentVisitor : + public CommentVisitorBase<make_const_ptr, ImplClass, RetTy> {}; + +} // end namespace comments +} // end namespace clang + diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 0c47f2e..e9f25b3 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -99,7 +99,7 @@ public: }; /// NamedDecl - This represents a decl with a name. Many decls have names such -/// as ObjCMethodDecl, but not @class, etc. +/// as ObjCMethodDecl, but not \@class, etc. class NamedDecl : public Decl { virtual void anchor(); /// Name - The name of this declaration, which is typically a normal @@ -218,6 +218,7 @@ public: Visibility visibility_; bool explicit_; + void setVisibility(Visibility V, bool E) { visibility_ = V; explicit_ = E; } public: LinkageInfo() : linkage_(ExternalLinkage), visibility_(DefaultVisibility), explicit_(false) {} @@ -242,8 +243,6 @@ public: bool visibilityExplicit() const { return explicit_; } void setLinkage(Linkage L) { linkage_ = L; } - void setVisibility(Visibility V, bool E) { visibility_ = V; explicit_ = E; } - void mergeLinkage(Linkage L) { setLinkage(minLinkage(linkage(), L)); } @@ -256,15 +255,15 @@ public: // down to one of its members. If the member has no explicit visibility, // the class visibility wins. void mergeVisibility(Visibility V, bool E = false) { - // If one has explicit visibility and the other doesn't, keep the - // explicit one. - if (visibilityExplicit() && !E) + // Never increase the visibility + if (visibility() < V) return; - if (!visibilityExplicit() && E) - setVisibility(V, E); - // If both are explicit or both are implicit, keep the minimum. - setVisibility(minVisibility(visibility(), V), visibilityExplicit() || E); + // If we have an explicit visibility, keep it + if (visibilityExplicit()) + return; + + setVisibility(V, E); } // Merge the visibility V, keeping the most restrictive one. // This is used for cases like merging the visibility of a template @@ -275,9 +274,16 @@ public: if (visibility() < V) return; + // FIXME: this // If this visibility is explicit, keep it. if (visibilityExplicit() && !E) return; + + // should be replaced with this + // Don't lose the explicit bit for nothing + // if (visibility() == V && visibilityExplicit()) + // return; + setVisibility(V, E); } void mergeVisibility(LinkageInfo Other) { @@ -295,11 +301,6 @@ public: mergeLinkage(Other); mergeVisibilityWithMin(Other); } - - friend LinkageInfo merge(LinkageInfo L, LinkageInfo R) { - L.merge(R); - return L; - } }; /// \brief Determine what kind of linkage this entity has. @@ -1151,7 +1152,7 @@ public: } /// \brief Determine whether this variable is the exception variable in a - /// C++ catch statememt or an Objective-C @catch statement. + /// C++ catch statememt or an Objective-C \@catch statement. bool isExceptionVariable() const { return VarDeclBits.ExceptionVar; } @@ -1182,7 +1183,7 @@ public: bool isARCPseudoStrong() const { return VarDeclBits.ARCPseudoStrong; } void setARCPseudoStrong(bool ps) { VarDeclBits.ARCPseudoStrong = ps; } - /// Whether this variable is (C++0x) constexpr. + /// Whether this variable is (C++11) constexpr. bool isConstexpr() const { return VarDeclBits.IsConstexpr; } void setConstexpr(bool IC) { VarDeclBits.IsConstexpr = IC; } @@ -1735,9 +1736,9 @@ public: bool hasInheritedPrototype() const { return HasInheritedPrototype; } void setHasInheritedPrototype(bool P = true) { HasInheritedPrototype = P; } - /// Whether this is a (C++0x) constexpr function or constexpr constructor. + /// Whether this is a (C++11) constexpr function or constexpr constructor. bool isConstexpr() const { return IsConstexpr; } - void setConstexpr(bool IC) { IsConstexpr = IC; } + void setConstexpr(bool IC); /// \brief Whether this function has been deleted. /// @@ -2092,25 +2093,26 @@ class FieldDecl : public DeclaratorDecl { bool Mutable : 1; mutable unsigned CachedFieldIndex : 31; - /// \brief A pointer to either the in-class initializer for this field (if - /// the boolean value is false), or the bit width expression for this bit - /// field (if the boolean value is true). + /// \brief An InClassInitStyle value, and either a bit width expression (if + /// the InClassInitStyle value is ICIS_NoInit), or a pointer to the in-class + /// initializer for this field (otherwise). /// /// We can safely combine these two because in-class initializers are not /// permitted for bit-fields. /// - /// If the boolean is false and the initializer is null, then this field has - /// an in-class initializer which has not yet been parsed and attached. - llvm::PointerIntPair<Expr *, 1, bool> InitializerOrBitWidth; + /// If the InClassInitStyle is not ICIS_NoInit and the initializer is null, + /// then this field has an in-class initializer which has not yet been parsed + /// and attached. + llvm::PointerIntPair<Expr *, 2, unsigned> InitializerOrBitWidth; protected: FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, - bool HasInit) + InClassInitStyle InitStyle) : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), Mutable(Mutable), CachedFieldIndex(0), - InitializerOrBitWidth(BW, !HasInit) { - assert(!(BW && HasInit) && "got initializer for bitfield"); + InitializerOrBitWidth(BW, InitStyle) { + assert((!BW || InitStyle == ICIS_NoInit) && "got initializer for bitfield"); } public: @@ -2118,7 +2120,7 @@ public: SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, - bool HasInit); + InClassInitStyle InitStyle); static FieldDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -2129,12 +2131,10 @@ public: /// isMutable - Determines whether this field is mutable (C++ only). bool isMutable() const { return Mutable; } - /// \brief Set whether this field is mutable (C++ only). - void setMutable(bool M) { Mutable = M; } - /// isBitfield - Determines whether this field is a bitfield. bool isBitField() const { - return InitializerOrBitWidth.getInt() && InitializerOrBitWidth.getPointer(); + return getInClassInitStyle() == ICIS_NoInit && + InitializerOrBitWidth.getPointer(); } /// @brief Determines whether this is an unnamed bitfield. @@ -2150,39 +2150,44 @@ public: return isBitField() ? InitializerOrBitWidth.getPointer() : 0; } unsigned getBitWidthValue(const ASTContext &Ctx) const; - void setBitWidth(Expr *BW) { - assert(!InitializerOrBitWidth.getPointer() && - "bit width or initializer already set"); - InitializerOrBitWidth.setPointer(BW); - InitializerOrBitWidth.setInt(1); - } - /// removeBitWidth - Remove the bitfield width from this member. + + /// setBitWidth - Set the bit-field width for this member. + // Note: used by some clients (i.e., do not remove it). + void setBitWidth(Expr *Width); + /// removeBitWidth - Remove the bit-field width from this member. + // Note: used by some clients (i.e., do not remove it). void removeBitWidth() { - assert(isBitField() && "no bit width to remove"); + assert(isBitField() && "no bitfield width to remove"); InitializerOrBitWidth.setPointer(0); } - /// hasInClassInitializer - Determine whether this member has a C++0x in-class + /// getInClassInitStyle - Get the kind of (C++11) in-class initializer which + /// this field has. + InClassInitStyle getInClassInitStyle() const { + return static_cast<InClassInitStyle>(InitializerOrBitWidth.getInt()); + } + + /// hasInClassInitializer - Determine whether this member has a C++11 in-class /// initializer. bool hasInClassInitializer() const { - return !InitializerOrBitWidth.getInt(); + return getInClassInitStyle() != ICIS_NoInit; } - /// getInClassInitializer - Get the C++0x in-class initializer for this + /// getInClassInitializer - Get the C++11 in-class initializer for this /// member, or null if one has not been set. If a valid declaration has an /// in-class initializer, but this returns null, then we have not parsed and /// attached it yet. Expr *getInClassInitializer() const { return hasInClassInitializer() ? InitializerOrBitWidth.getPointer() : 0; } - /// setInClassInitializer - Set the C++0x in-class initializer for this + /// setInClassInitializer - Set the C++11 in-class initializer for this /// member. void setInClassInitializer(Expr *Init); - /// removeInClassInitializer - Remove the C++0x in-class initializer from this + /// removeInClassInitializer - Remove the C++11 in-class initializer from this /// member. void removeInClassInitializer() { - assert(!InitializerOrBitWidth.getInt() && "no initializer to remove"); + assert(hasInClassInitializer() && "no initializer to remove"); InitializerOrBitWidth.setPointer(0); - InitializerOrBitWidth.setInt(1); + InitializerOrBitWidth.setInt(ICIS_NoInit); } /// getParent - Returns the parent of this field declaration, which @@ -2201,6 +2206,9 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const FieldDecl *D) { return true; } static bool classofKind(Kind K) { return K >= firstField && K <= lastField; } + + friend class ASTDeclReader; + friend class ASTDeclWriter; }; /// EnumConstantDecl - An instance of this object exists for each enum constant @@ -2308,7 +2316,10 @@ protected: : NamedDecl(DK, DC, L, Id), TypeForDecl(0), LocStart(StartL) {} public: - // Low-level accessor + // Low-level accessor. If you just want the type defined by this node, + // check out ASTContext::getTypeDeclType or one of + // ASTContext::getTypedefType, ASTContext::getRecordType, etc. if you + // already know the specific kind of node this is. const Type *getTypeForDecl() const { return TypeForDecl; } void setTypeForDecl(const Type *TD) { TypeForDecl = TD; } @@ -2602,6 +2613,7 @@ public: void setCompleteDefinition(bool V) { IsCompleteDefinition = V; } + // FIXME: Return StringRef; const char *getKindName() const { return TypeWithKeyword::getTagTypeKindName(getTagKind()); } @@ -3214,8 +3226,8 @@ public: /// @__experimental_modules_import std.vector; /// \endcode /// -/// Import declarations can also be implicitly generated from #include/#import -/// directives. +/// Import declarations can also be implicitly generated from +/// \#include/\#import directives. class ImportDecl : public Decl { /// \brief The imported module, along with a bit that indicates whether /// we have source-location information for each identifier in the module diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 22328912..ac2cc9e 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_DECLBASE_H #include "clang/AST/Attr.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/Type.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/PointerUnion.h" @@ -692,17 +693,17 @@ public: Decl *Starter; public: - typedef Decl* value_type; - typedef Decl* reference; - typedef Decl* pointer; + typedef Decl *value_type; + typedef const value_type &reference; + typedef const value_type *pointer; typedef std::forward_iterator_tag iterator_category; - typedef std::ptrdiff_t difference_type; + typedef std::ptrdiff_t difference_type; redecl_iterator() : Current(0) { } explicit redecl_iterator(Decl *C) : Current(C), Starter(C) { } reference operator*() const { return Current; } - pointer operator->() const { return Current; } + value_type operator->() const { return Current; } redecl_iterator& operator++() { assert(Current && "Advancing while iterator has reached end"); @@ -856,8 +857,11 @@ public: static void printGroup(Decl** Begin, unsigned NumDecls, raw_ostream &Out, const PrintingPolicy &Policy, unsigned Indentation = 0); - LLVM_ATTRIBUTE_USED void dump() const; - LLVM_ATTRIBUTE_USED void dumpXML() const; + // Debuggers don't usually respect default arguments. + LLVM_ATTRIBUTE_USED void dump() const { dump(llvm::errs()); } + void dump(raw_ostream &Out) const; + // Debuggers don't usually respect default arguments. + LLVM_ATTRIBUTE_USED void dumpXML() const { dumpXML(llvm::errs()); } void dumpXML(raw_ostream &OS) const; private: @@ -1141,7 +1145,7 @@ public: /// inline, its enclosing namespace, recursively. bool InEnclosingNamespaceSetOf(const DeclContext *NS) const; - /// \\brief Collects all of the declaration contexts that are semantically + /// \brief Collects all of the declaration contexts that are semantically /// connected to this declaration context. /// /// For declaration contexts that have multiple semantically connected but @@ -1173,9 +1177,9 @@ public: Decl *Current; public: - typedef Decl* value_type; - typedef Decl* reference; - typedef Decl* pointer; + typedef Decl *value_type; + typedef const value_type &reference; + typedef const value_type *pointer; typedef std::forward_iterator_tag iterator_category; typedef std::ptrdiff_t difference_type; @@ -1183,7 +1187,8 @@ public: explicit decl_iterator(Decl *C) : Current(C) { } reference operator*() const { return Current; } - pointer operator->() const { return Current; } + // This doesn't meet the iterator requirements, but it's convenient + value_type operator->() const { return Current; } decl_iterator& operator++() { Current = Current->getNextDeclInContext(); @@ -1207,14 +1212,14 @@ public: /// decls_begin/decls_end - Iterate over the declarations stored in /// this context. decl_iterator decls_begin() const; - decl_iterator decls_end() const; + decl_iterator decls_end() const { return decl_iterator(); } bool decls_empty() const; /// noload_decls_begin/end - Iterate over the declarations stored in this /// context that are currently loaded; don't attempt to retrieve anything /// from an external source. decl_iterator noload_decls_begin() const; - decl_iterator noload_decls_end() const; + decl_iterator noload_decls_end() const { return decl_iterator(); } /// specific_decl_iterator - Iterates over a subrange of /// declarations stored in a DeclContext, providing only those that @@ -1237,9 +1242,11 @@ public: } public: - typedef SpecificDecl* value_type; - typedef SpecificDecl* reference; - typedef SpecificDecl* pointer; + typedef SpecificDecl *value_type; + // TODO: Add reference and pointer typedefs (with some appropriate proxy + // type) if we ever have a need for them. + typedef void reference; + typedef void pointer; typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type difference_type; typedef std::forward_iterator_tag iterator_category; @@ -1258,8 +1265,9 @@ public: SkipToNextDecl(); } - reference operator*() const { return cast<SpecificDecl>(*Current); } - pointer operator->() const { return cast<SpecificDecl>(*Current); } + value_type operator*() const { return cast<SpecificDecl>(*Current); } + // This doesn't meet the iterator requirements, but it's convenient + value_type operator->() const { return **this; } specific_decl_iterator& operator++() { ++Current; @@ -1311,16 +1319,18 @@ public: } public: - typedef SpecificDecl* value_type; - typedef SpecificDecl* reference; - typedef SpecificDecl* pointer; + typedef SpecificDecl *value_type; + // TODO: Add reference and pointer typedefs (with some appropriate proxy + // type) if we ever have a need for them. + typedef void reference; + typedef void pointer; typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type difference_type; typedef std::forward_iterator_tag iterator_category; filtered_decl_iterator() : Current() { } - /// specific_decl_iterator - Construct a new iterator over a + /// filtered_decl_iterator - Construct a new iterator over a /// subset of the declarations the range [C, /// end-of-declarations). If A is non-NULL, it is a pointer to a /// member function of SpecificDecl that should return true for @@ -1332,8 +1342,8 @@ public: SkipToNextDecl(); } - reference operator*() const { return cast<SpecificDecl>(*Current); } - pointer operator->() const { return cast<SpecificDecl>(*Current); } + value_type operator*() const { return cast<SpecificDecl>(*Current); } + value_type operator->() const { return cast<SpecificDecl>(*Current); } filtered_decl_iterator& operator++() { ++Current; @@ -1410,7 +1420,9 @@ public: /// and enumerator names preceding any tag name. Note that this /// routine will not look into parent contexts. lookup_result lookup(DeclarationName Name); - lookup_const_result lookup(DeclarationName Name) const; + lookup_const_result lookup(DeclarationName Name) const { + return const_cast<DeclContext*>(this)->lookup(Name); + } /// \brief A simplistic name lookup mechanism that performs name lookup /// into this declaration context without consulting the external source. diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 7f3ec4c..851e310 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -41,6 +41,7 @@ class CXXFinalOverriderMap; class CXXIndirectPrimaryBaseSet; class FriendDecl; class LambdaExpr; +class UsingDecl; /// \brief Represents any kind of function declaration, whether it is a /// concrete function or a function template. @@ -98,7 +99,7 @@ namespace llvm { namespace clang { -/// AccessSpecDecl - An access specifier followed by colon ':'. +/// @brief Represents an access specifier followed by colon ':'. /// /// An objects of this class represents sugar for the syntactic occurrence /// of an access specifier followed by a colon in the list of member @@ -110,7 +111,7 @@ namespace clang { /// "access declarations" (C++98 11.3 [class.access.dcl]). class AccessSpecDecl : public Decl { virtual void anchor(); - /// ColonLoc - The location of the ':'. + /// \brief The location of the ':'. SourceLocation ColonLoc; AccessSpecDecl(AccessSpecifier AS, DeclContext *DC, @@ -121,14 +122,14 @@ class AccessSpecDecl : public Decl { AccessSpecDecl(EmptyShell Empty) : Decl(AccessSpec, Empty) { } public: - /// getAccessSpecifierLoc - The location of the access specifier. + /// \brief The location of the access specifier. SourceLocation getAccessSpecifierLoc() const { return getLocation(); } - /// setAccessSpecifierLoc - Sets the location of the access specifier. + /// \brief Sets the location of the access specifier. void setAccessSpecifierLoc(SourceLocation ASLoc) { setLocation(ASLoc); } - /// getColonLoc - The location of the colon following the access specifier. + /// \brief The location of the colon following the access specifier. SourceLocation getColonLoc() const { return ColonLoc; } - /// setColonLoc - Sets the location of the colon. + /// \brief Sets the location of the colon. void setColonLoc(SourceLocation CLoc) { ColonLoc = CLoc; } SourceRange getSourceRange() const LLVM_READONLY { @@ -149,7 +150,7 @@ public: }; -/// CXXBaseSpecifier - A base class of a C++ class. +/// \brief Represents a base class of a C++ class. /// /// Each CXXBaseSpecifier represents a single, direct base class (or /// struct) of a C++ class (or struct). It specifies the type of that @@ -175,7 +176,7 @@ class CXXBaseSpecifier { /// expansion. SourceLocation EllipsisLoc; - /// Virtual - Whether this is a virtual base class or not. + /// \brief Whether this is a virtual base class or not. bool Virtual : 1; /// BaseOfClass - Whether this is the base of a class (true) or of a @@ -357,6 +358,9 @@ class CXXRecordDecl : public RecordDecl { /// \brief True if there no non-field members declared by the user. bool HasOnlyCMembers : 1; + /// \brief True if any field has an in-class initializer. + bool HasInClassInitializer : 1; + /// HasTrivialDefaultConstructor - True when, if this class has a default /// constructor, this default constructor is trivial. /// @@ -382,26 +386,10 @@ class CXXRecordDecl : public RecordDecl { /// constructor for this class would be constexpr. bool DefaultedDefaultConstructorIsConstexpr : 1; - /// DefaultedCopyConstructorIsConstexpr - True if a defaulted copy - /// constructor for this class would be constexpr. - bool DefaultedCopyConstructorIsConstexpr : 1; - - /// DefaultedMoveConstructorIsConstexpr - True if a defaulted move - /// constructor for this class would be constexpr. - bool DefaultedMoveConstructorIsConstexpr : 1; - /// HasConstexprDefaultConstructor - True if this class has a constexpr /// default constructor (either user-declared or implicitly declared). bool HasConstexprDefaultConstructor : 1; - /// HasConstexprCopyConstructor - True if this class has a constexpr copy - /// constructor (either user-declared or implicitly declared). - bool HasConstexprCopyConstructor : 1; - - /// HasConstexprMoveConstructor - True if this class has a constexpr move - /// constructor (either user-declared or implicitly declared). - bool HasConstexprMoveConstructor : 1; - /// HasTrivialCopyConstructor - True when this class has a trivial copy /// constructor. /// @@ -554,13 +542,21 @@ class CXXRecordDecl : public RecordDecl { /// \brief Retrieve the set of direct base classes. CXXBaseSpecifier *getBases() const { - return Bases.get(Definition->getASTContext().getExternalSource()); + if (!Bases.isOffset()) + return Bases.get(0); + return getBasesSlowCase(); } /// \brief Retrieve the set of virtual base classes. CXXBaseSpecifier *getVBases() const { - return VBases.get(Definition->getASTContext().getExternalSource()); + if (!VBases.isOffset()) + return VBases.get(0); + return getVBasesSlowCase(); } + + private: + CXXBaseSpecifier *getBasesSlowCase() const; + CXXBaseSpecifier *getVBasesSlowCase() const; } *DefinitionData; /// \brief Describes a C++ closure type (generated by a lambda expression). @@ -647,6 +643,9 @@ class CXXRecordDecl : public RecordDecl { void markedVirtualFunctionPure(); friend void FunctionDecl::setPure(bool); + void markedConstructorConstexpr(CXXConstructorDecl *CD); + friend void FunctionDecl::setConstexpr(bool); + friend class ASTNodeImporter; protected: @@ -1040,6 +1039,10 @@ public: /// no base classes, and no virtual functions (C++ [dcl.init.aggr]p1). bool isAggregate() const { return data().Aggregate; } + /// hasInClassInitializer - Whether this class has any in-class initializers + /// for non-static data members. + bool hasInClassInitializer() const { return data().HasInClassInitializer; } + /// isPOD - Whether this class is a POD-type (C++ [class]p4), which is a class /// that is an aggregate that has no non-static non-POD data members, no /// reference data members, no user-defined copy assignment operator and no @@ -1091,19 +1094,8 @@ public: /// defaultedDefaultConstructorIsConstexpr - Whether a defaulted default /// constructor for this class would be constexpr. bool defaultedDefaultConstructorIsConstexpr() const { - return data().DefaultedDefaultConstructorIsConstexpr; - } - - /// defaultedCopyConstructorIsConstexpr - Whether a defaulted copy - /// constructor for this class would be constexpr. - bool defaultedCopyConstructorIsConstexpr() const { - return data().DefaultedCopyConstructorIsConstexpr; - } - - /// defaultedMoveConstructorIsConstexpr - Whether a defaulted move - /// constructor for this class would be constexpr. - bool defaultedMoveConstructorIsConstexpr() const { - return data().DefaultedMoveConstructorIsConstexpr; + return data().DefaultedDefaultConstructorIsConstexpr && + (!isUnion() || hasInClassInitializer()); } /// hasConstexprDefaultConstructor - Whether this class has a constexpr @@ -1111,23 +1103,7 @@ public: bool hasConstexprDefaultConstructor() const { return data().HasConstexprDefaultConstructor || (!data().UserDeclaredConstructor && - data().DefaultedDefaultConstructorIsConstexpr && isLiteral()); - } - - /// hasConstexprCopyConstructor - Whether this class has a constexpr copy - /// constructor. - bool hasConstexprCopyConstructor() const { - return data().HasConstexprCopyConstructor || - (!data().DeclaredCopyConstructor && - data().DefaultedCopyConstructorIsConstexpr && isLiteral()); - } - - /// hasConstexprMoveConstructor - Whether this class has a constexpr move - /// constructor. - bool hasConstexprMoveConstructor() const { - return data().HasConstexprMoveConstructor || - (needsImplicitMoveConstructor() && - data().DefaultedMoveConstructorIsConstexpr && isLiteral()); + defaultedDefaultConstructorIsConstexpr()); } // hasTrivialCopyConstructor - Whether this class has a trivial copy @@ -1212,12 +1188,12 @@ public: /// This routine will return non-NULL for (non-templated) member /// classes of class templates. For example, given: /// - /// \code + /// @code /// template<typename T> /// struct X { /// struct A { }; /// }; - /// \endcode + /// @endcode /// /// The declaration for X<int>::A is a (non-templated) CXXRecordDecl /// whose parent is the class template specialization X<int>. For @@ -1319,7 +1295,7 @@ public: /// /// \returns true if this class is virtually derived from Base, /// false otherwise. - bool isVirtuallyDerivedFrom(CXXRecordDecl *Base) const; + bool isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const; /// \brief Determine whether this class is provably not derived from /// the type \p Base. @@ -1573,6 +1549,9 @@ public: bool isStatic() const { return getStorageClass() == SC_Static; } bool isInstance() const { return !isStatic(); } + bool isConst() { return getType()->castAs<FunctionType>()->isConst(); } + bool isVolatile() { return getType()->castAs<FunctionType>()->isVolatile(); } + bool isVirtual() const { CXXMethodDecl *CD = cast<CXXMethodDecl>(const_cast<CXXMethodDecl*>(this)->getCanonicalDecl()); @@ -1602,8 +1581,8 @@ public: return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl()); } - /// isUserProvided - True if it is either an implicit constructor or - /// if it was defaulted or deleted on first declaration. + /// isUserProvided - True if this method is user-declared and was not + /// deleted or defaulted on its first declaration. bool isUserProvided() const { return !(isDeleted() || getCanonicalDecl()->isDefaulted()); } @@ -1642,13 +1621,13 @@ public: /// /// In the following example, \c f() has an lvalue ref-qualifier, \c g() /// has an rvalue ref-qualifier, and \c h() has no ref-qualifier. - /// \code + /// @code /// struct X { /// void f() &; /// void g() &&; /// void h(); /// }; - /// \endcode + /// @endcode RefQualifierKind getRefQualifier() const { return getType()->getAs<FunctionProtoType>()->getRefQualifier(); } @@ -1663,7 +1642,20 @@ public: /// supplied by IR generation to either forward to the function call operator /// or clone the function call operator. bool isLambdaStaticInvoker() const; - + + /// \brief Find the method in RD that corresponds to this one. + /// + /// Find if RD or one of the classes it inherits from override this method. + /// If so, return it. RD is assumed to be a base class of the class defining + /// this method (or be the class itself). + CXXMethodDecl * + getCorrespondingMethodInClass(const CXXRecordDecl *RD); + + const CXXMethodDecl * + getCorrespondingMethodInClass(const CXXRecordDecl *RD) const { + return const_cast<CXXMethodDecl*>(this)->getCorrespondingMethodInClass(RD); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const CXXMethodDecl *D) { return true; } @@ -2468,7 +2460,9 @@ public: friend class ASTDeclReader; }; -/// NamespaceAliasDecl - Represents a C++ namespace alias. For example: +/// \brief Represents a C++ namespace alias. +/// +/// For example: /// /// @code /// namespace Foo = Bar; @@ -2555,17 +2549,19 @@ public: static bool classofKind(Kind K) { return K == NamespaceAlias; } }; -/// UsingShadowDecl - Represents a shadow declaration introduced into -/// a scope by a (resolved) using declaration. For example, +/// \brief Represents a shadow declaration introduced into a scope by a +/// (resolved) using declaration. /// +/// For example, +/// @code /// namespace A { /// void foo(); /// } /// namespace B { -/// using A::foo(); // <- a UsingDecl -/// // Also creates a UsingShadowDecl for A::foo in B +/// using A::foo; // <- a UsingDecl +/// // Also creates a UsingShadowDecl for A::foo() in B /// } -/// +/// @endcode class UsingShadowDecl : public NamedDecl { virtual void anchor(); @@ -2627,8 +2623,12 @@ public: friend class ASTDeclWriter; }; -/// UsingDecl - Represents a C++ using-declaration. For example: +/// \brief Represents a C++ using-declaration. +/// +/// For example: +/// @code /// using someNameSpace::someIdentifier; +/// @endcode class UsingDecl : public NamedDecl { virtual void anchor(); @@ -2643,8 +2643,10 @@ class UsingDecl : public NamedDecl { DeclarationNameLoc DNLoc; /// \brief The first shadow declaration of the shadow decl chain associated - /// with this using declaration. The bool member of the pair store whether - /// this decl has the 'typename' keyword. + /// with this using declaration. + /// + /// The bool member of the pair store whether this decl has the \c typename + /// keyword. llvm::PointerIntPair<UsingShadowDecl *, 1, bool> FirstUsingShadow; UsingDecl(DeclContext *DC, SourceLocation UL, @@ -2753,14 +2755,17 @@ public: friend class ASTDeclWriter; }; -/// UnresolvedUsingValueDecl - Represents a dependent using -/// declaration which was not marked with 'typename'. Unlike -/// non-dependent using declarations, these *only* bring through +/// \brief Represents a dependent using declaration which was not marked with +/// \c typename. +/// +/// Unlike non-dependent using declarations, these *only* bring through /// non-types; otherwise they would break two-phase lookup. /// -/// template <class T> class A : public Base<T> { +/// @code +/// template \<class T> class A : public Base<T> { /// using Base<T>::foo; /// }; +/// @endcode class UnresolvedUsingValueDecl : public ValueDecl { virtual void anchor(); @@ -2824,14 +2829,16 @@ public: friend class ASTDeclWriter; }; -/// UnresolvedUsingTypenameDecl - Represents a dependent using -/// declaration which was marked with 'typename'. +/// @brief Represents a dependent using declaration which was marked with +/// \c typename. /// -/// template <class T> class A : public Base<T> { +/// @code +/// template \<class T> class A : public Base<T> { /// using typename Base<T>::foo; /// }; +/// @endcode /// -/// The type associated with a unresolved using typename decl is +/// The type associated with an unresolved using typename decl is /// currently always a typename type. class UnresolvedUsingTypenameDecl : public TypeDecl { virtual void anchor(); @@ -2885,34 +2892,36 @@ public: static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; } }; -/// StaticAssertDecl - Represents a C++0x static_assert declaration. +/// \brief Represents a C++11 static_assert declaration. class StaticAssertDecl : public Decl { virtual void anchor(); - Expr *AssertExpr; + llvm::PointerIntPair<Expr *, 1, bool> AssertExprAndFailed; StringLiteral *Message; SourceLocation RParenLoc; StaticAssertDecl(DeclContext *DC, SourceLocation StaticAssertLoc, - Expr *assertexpr, StringLiteral *message, - SourceLocation RParenLoc) - : Decl(StaticAssert, DC, StaticAssertLoc), AssertExpr(assertexpr), - Message(message), RParenLoc(RParenLoc) { } + Expr *AssertExpr, StringLiteral *Message, + SourceLocation RParenLoc, bool Failed) + : Decl(StaticAssert, DC, StaticAssertLoc), + AssertExprAndFailed(AssertExpr, Failed), Message(Message), + RParenLoc(RParenLoc) { } public: static StaticAssertDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StaticAssertLoc, Expr *AssertExpr, StringLiteral *Message, - SourceLocation RParenLoc); + SourceLocation RParenLoc, bool Failed); static StaticAssertDecl *CreateDeserialized(ASTContext &C, unsigned ID); - Expr *getAssertExpr() { return AssertExpr; } - const Expr *getAssertExpr() const { return AssertExpr; } + Expr *getAssertExpr() { return AssertExprAndFailed.getPointer(); } + const Expr *getAssertExpr() const { return AssertExprAndFailed.getPointer(); } StringLiteral *getMessage() { return Message; } const StringLiteral *getMessage() const { return Message; } + bool isFailed() const { return AssertExprAndFailed.getInt(); } + SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getLocation(), getRParenLoc()); @@ -2925,7 +2934,7 @@ public: friend class ASTDeclReader; }; -/// Insertion operator for diagnostics. This allows sending AccessSpecifier's +/// Insertion operator for diagnostics. This allows sending an AccessSpecifier /// into a diagnostic with <<. const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, AccessSpecifier AS); diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h index c5f2aa0..39f04c6 100644 --- a/include/clang/AST/DeclContextInternals.h +++ b/include/clang/AST/DeclContextInternals.h @@ -17,8 +17,8 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/DeclCXX.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include <algorithm> @@ -196,7 +196,7 @@ public: }; class StoredDeclsMap - : public llvm::DenseMap<DeclarationName, StoredDeclsList> { + : public llvm::SmallDenseMap<DeclarationName, StoredDeclsList, 4> { public: static void DestroyAll(StoredDeclsMap *Map, bool Dependent); diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index ba1eb8d..9a64f08 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -71,10 +71,12 @@ private: : Decl(Decl::Friend, Empty), NextFriend() { } FriendDecl *getNextFriend() { - return cast_or_null<FriendDecl>( - NextFriend.get(getASTContext().getExternalSource())); + if (!NextFriend.isOffset()) + return cast_or_null<FriendDecl>(NextFriend.get(0)); + return getNextFriendSlowCase(); } - + FriendDecl *getNextFriendSlowCase(); + public: static FriendDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_, diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 4ae073e..6c39f2c 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -136,7 +136,7 @@ private: mutable unsigned HasRedeclaration : 1; // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum - /// @required/@optional + /// \@required/\@optional unsigned DeclImplementation : 2; // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum @@ -150,6 +150,15 @@ private: /// "standard" position, a enum SelectorLocationsKind. unsigned SelLocsKind : 2; + /// \brief Whether this method overrides any other in the class hierarchy. + /// + /// A method is said to override any method in the class's + /// base classes, its protocols, or its categories' protocols, that has + /// the same selector and is of the same kind (class or instance). + /// A method in an implementation is not considered as overriding the same + /// method in the interface or its categories. + unsigned IsOverriding : 1; + // Result type of this method. QualType MethodDeclType; @@ -162,7 +171,7 @@ private: unsigned NumParams; /// List of attributes for this method declaration. - SourceLocation EndLoc; // the location of the ';' or '}'. + SourceLocation DeclEndLoc; // the location of the ';' or '{'. // The following are only used for method definitions, null otherwise. // FIXME: space savings opportunity, consider a sub-class. @@ -230,10 +239,10 @@ private: IsDefined(isDefined), IsRedeclaration(0), HasRedeclaration(0), DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None), RelatedResultType(HasRelatedResultType), - SelLocsKind(SelLoc_StandardNoSpace), + SelLocsKind(SelLoc_StandardNoSpace), IsOverriding(0), MethodDeclType(T), ResultTInfo(ResultTInfo), ParamsAndSelLocs(0), NumParams(0), - EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) { + DeclEndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) { setImplicit(isImplicitlyDeclared); } @@ -281,12 +290,16 @@ public: bool isRedeclaration() const { return IsRedeclaration; } void setAsRedeclaration(const ObjCMethodDecl *PrevMethod); + /// \brief Returns the location where the declarator ends. It will be + /// the location of ';' for a method declaration and the location of '{' + /// for a method definition. + SourceLocation getDeclaratorEndLoc() const { return DeclEndLoc; } + // Location information, modeled after the Stmt API. SourceLocation getLocStart() const LLVM_READONLY { return getLocation(); } - SourceLocation getLocEnd() const LLVM_READONLY { return EndLoc; } - void setEndLoc(SourceLocation Loc) { EndLoc = Loc; } + SourceLocation getLocEnd() const LLVM_READONLY; virtual SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getLocation(), EndLoc); + return SourceRange(getLocation(), getLocEnd()); } SourceLocation getSelectorStartLoc() const { @@ -301,7 +314,7 @@ public: getSelLocsKind() == SelLoc_StandardWithSpace, llvm::makeArrayRef(const_cast<ParmVarDecl**>(getParams()), NumParams), - EndLoc); + DeclEndLoc); return getStoredSelLocs()[Index]; } @@ -396,7 +409,17 @@ public: bool isDefined() const { return IsDefined; } void setDefined(bool isDefined) { IsDefined = isDefined; } - // Related to protocols declared in @protocol + /// \brief Whether this method overrides any other in the class hierarchy. + /// + /// A method is said to override any method in the class's + /// base classes, its protocols, or its categories' protocols, that has + /// the same selector and is of the same kind (class or instance). + /// A method in an implementation is not considered as overriding the same + /// method in the interface or its categories. + bool isOverriding() const { return IsOverriding; } + void setOverriding(bool isOverriding) { IsOverriding = isOverriding; } + + // Related to protocols declared in \@protocol void setDeclImplementation(ImplementationControl ic) { DeclImplementation = ic; } @@ -528,24 +551,28 @@ public: } }; -/// ObjCInterfaceDecl - Represents an ObjC class declaration. For example: +/// \brief Represents an ObjC class declaration. +/// +/// For example: /// +/// \code /// // MostPrimitive declares no super class (not particularly useful). -/// @interface MostPrimitive +/// \@interface MostPrimitive /// // no instance variables or methods. -/// @end +/// \@end /// /// // NSResponder inherits from NSObject & implements NSCoding (a protocol). -/// @interface NSResponder : NSObject <NSCoding> +/// \@interface NSResponder : NSObject \<NSCoding> /// { // instance variables are represented by ObjCIvarDecl. /// id nextResponder; // nextResponder instance variable. /// } /// - (NSResponder *)nextResponder; // return a pointer to NSResponder. /// - (void)mouseMoved:(NSEvent *)theEvent; // return void, takes a pointer -/// @end // to an NSEvent. +/// \@end // to an NSEvent. +/// \endcode /// -/// Unlike C/C++, forward class declarations are accomplished with @class. -/// Unlike C/C++, @class allows for a list of classes to be forward declared. +/// Unlike C/C++, forward class declarations are accomplished with \@class. +/// Unlike C/C++, \@class allows for a list of classes to be forward declared. /// Unlike C++, ObjC is a single-rooted class model. In Cocoa, classes /// typically inherit from NSObject (an exception is NSProxy). /// @@ -566,10 +593,10 @@ class ObjCInterfaceDecl : public ObjCContainerDecl /// Class's super class. ObjCInterfaceDecl *SuperClass; - /// Protocols referenced in the @interface declaration + /// Protocols referenced in the \@interface declaration ObjCProtocolList ReferencedProtocols; - /// Protocols reference in both the @interface and class extensions. + /// Protocols reference in both the \@interface and class extensions. ObjCList<ObjCProtocolDecl> AllReferencedProtocols; /// \brief List of categories and class extensions defined for this class. @@ -799,21 +826,21 @@ public: bool hasDefinition() const { return Data; } /// \brief Retrieve the definition of this class, or NULL if this class - /// has been forward-declared (with @class) but not yet defined (with - /// @interface). + /// has been forward-declared (with \@class) but not yet defined (with + /// \@interface). ObjCInterfaceDecl *getDefinition() { return hasDefinition()? Data->Definition : 0; } /// \brief Retrieve the definition of this class, or NULL if this class - /// has been forward-declared (with @class) but not yet defined (with - /// @interface). + /// has been forward-declared (with \@class) but not yet defined (with + /// \@interface). const ObjCInterfaceDecl *getDefinition() const { return hasDefinition()? Data->Definition : 0; } /// \brief Starts the definition of this Objective-C class, taking it from - /// a forward declaration (@class) to a definition (@interface). + /// a forward declaration (\@class) to a definition (\@interface). void startDefinition(); ObjCInterfaceDecl *getSuperClass() const { @@ -879,8 +906,8 @@ public: } /// isObjCRequiresPropertyDefs - Checks that a class or one of its super - /// classes must not be auto-synthesized. Returns class decl. if it must not be; - /// 0, otherwise. + /// classes must not be auto-synthesized. Returns class decl. if it must not + /// be; 0, otherwise. const ObjCInterfaceDecl *isObjCRequiresPropertyDefs() const { const ObjCInterfaceDecl *Class = this; while (Class) { @@ -912,8 +939,13 @@ public: } ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName); - // Lookup a method in the classes implementation hierarchy. - ObjCMethodDecl *lookupPrivateMethod(const Selector &Sel, bool Instance=true); + /// \brief Lookup a method in the classes implementation hierarchy. + ObjCMethodDecl *lookupPrivateMethod(const Selector &Sel, + bool Instance=true) const; + + ObjCMethodDecl *lookupPrivateClassMethod(const Selector &Sel) { + return lookupPrivateMethod(Sel, false); + } SourceLocation getEndOfDefinitionLoc() const { if (!hasDefinition()) @@ -928,8 +960,8 @@ public: SourceLocation getSuperClassLoc() const { return data().SuperClassLoc; } /// isImplicitInterfaceDecl - check that this is an implicitly declared - /// ObjCInterfaceDecl node. This is for legacy objective-c @implementation - /// declaration without an @interface declaration. + /// ObjCInterfaceDecl node. This is for legacy objective-c \@implementation + /// declaration without an \@interface declaration. bool isImplicitInterfaceDecl() const { return hasDefinition() ? Data->Definition->isImplicit() : isImplicit(); } @@ -972,14 +1004,14 @@ public: /// instance variables are identical to C. The only exception is Objective-C /// supports C++ style access control. For example: /// -/// @interface IvarExample : NSObject +/// \@interface IvarExample : NSObject /// { /// id defaultToProtected; -/// @public: +/// \@public: /// id canBePublic; // same as C++. -/// @protected: +/// \@protected: /// id canBeProtected; // same as C++. -/// @package: +/// \@package: /// id canBePackage; // framework visibility (not available in C++). /// } /// @@ -997,7 +1029,7 @@ private: QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW, bool synthesized) : FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW, - /*Mutable=*/false, /*HasInit=*/false), + /*Mutable=*/false, /*HasInit=*/ICIS_NoInit), NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {} public: @@ -1046,8 +1078,7 @@ private: }; -/// ObjCAtDefsFieldDecl - Represents a field declaration created by an -/// @defs(...). +/// \brief Represents a field declaration created by an \@defs(...). class ObjCAtDefsFieldDecl : public FieldDecl { virtual void anchor(); ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation StartLoc, @@ -1055,7 +1086,7 @@ class ObjCAtDefsFieldDecl : public FieldDecl { QualType T, Expr *BW) : FieldDecl(ObjCAtDefsField, DC, StartLoc, IdLoc, Id, T, /*TInfo=*/0, // FIXME: Do ObjCAtDefs have declarators ? - BW, /*Mutable=*/false, /*HasInit=*/false) {} + BW, /*Mutable=*/false, /*HasInit=*/ICIS_NoInit) {} public: static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC, @@ -1071,29 +1102,35 @@ public: static bool classofKind(Kind K) { return K == ObjCAtDefsField; } }; -/// ObjCProtocolDecl - Represents a protocol declaration. ObjC protocols -/// declare a pure abstract type (i.e no instance variables are permitted). -/// Protocols originally drew inspiration from C++ pure virtual functions (a C++ -/// feature with nice semantics and lousy syntax:-). Here is an example: +/// \brief Represents an Objective-C protocol declaration. +/// +/// Objective-C protocols declare a pure abstract type (i.e., no instance +/// variables are permitted). Protocols originally drew inspiration from +/// C++ pure virtual functions (a C++ feature with nice semantics and lousy +/// syntax:-). Here is an example: /// -/// @protocol NSDraggingInfo <refproto1, refproto2> +/// \code +/// \@protocol NSDraggingInfo <refproto1, refproto2> /// - (NSWindow *)draggingDestinationWindow; /// - (NSImage *)draggedImage; -/// @end +/// \@end +/// \endcode /// /// This says that NSDraggingInfo requires two methods and requires everything /// that the two "referenced protocols" 'refproto1' and 'refproto2' require as /// well. /// -/// @interface ImplementsNSDraggingInfo : NSObject <NSDraggingInfo> -/// @end +/// \code +/// \@interface ImplementsNSDraggingInfo : NSObject \<NSDraggingInfo> +/// \@end +/// \endcode /// /// ObjC protocols inspired Java interfaces. Unlike Java, ObjC classes and /// protocols are in distinct namespaces. For example, Cocoa defines both /// an NSObject protocol and class (which isn't allowed in Java). As a result, /// protocols are referenced using angle brackets as follows: /// -/// id <NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo; +/// id \<NSDraggingInfo> anyObjectThatImplementsNSDraggingInfo; /// class ObjCProtocolDecl : public ObjCContainerDecl, public Redeclarable<ObjCProtocolDecl> { @@ -1255,9 +1292,9 @@ public: /// you to add instance data. The following example adds "myMethod" to all /// NSView's within a process: /// -/// @interface NSView (MyViewMethods) +/// \@interface NSView (MyViewMethods) /// - myMethod; -/// @end +/// \@end /// /// Categories also allow you to split the implementation of a class across /// several files (a feature more naturally supported in C++). @@ -1279,9 +1316,6 @@ class ObjCCategoryDecl : public ObjCContainerDecl { /// FIXME: this should not be a singly-linked list. Move storage elsewhere. ObjCCategoryDecl *NextClassCategory; - /// true of class extension has at least one bitfield ivar. - bool HasSynthBitfield : 1; - /// \brief The location of the category name in this declaration. SourceLocation CategoryNameLoc; @@ -1295,7 +1329,7 @@ class ObjCCategoryDecl : public ObjCContainerDecl { SourceLocation IvarLBraceLoc=SourceLocation(), SourceLocation IvarRBraceLoc=SourceLocation()) : ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc), - ClassInterface(IDecl), NextClassCategory(0), HasSynthBitfield(false), + ClassInterface(IDecl), NextClassCategory(0), CategoryNameLoc(CategoryNameLoc), IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) { } @@ -1345,9 +1379,6 @@ public: bool IsClassExtension() const { return getIdentifier() == 0; } const ObjCCategoryDecl *getNextClassExtension() const; - bool hasSynthBitfield() const { return HasSynthBitfield; } - void setHasSynthBitfield (bool val) { HasSynthBitfield = val; } - typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); @@ -1431,16 +1462,16 @@ public: }; /// ObjCCategoryImplDecl - An object of this class encapsulates a category -/// @implementation declaration. If a category class has declaration of a +/// \@implementation declaration. If a category class has declaration of a /// property, its implementation must be specified in the category's -/// @implementation declaration. Example: -/// @interface I @end -/// @interface I(CATEGORY) -/// @property int p1, d1; -/// @end -/// @implementation I(CATEGORY) -/// @dynamic p1,d1; -/// @end +/// \@implementation declaration. Example: +/// \@interface I \@end +/// \@interface I(CATEGORY) +/// \@property int p1, d1; +/// \@end +/// \@implementation I(CATEGORY) +/// \@dynamic p1,d1; +/// \@end /// /// ObjCCategoryImplDecl class ObjCCategoryImplDecl : public ObjCImplDecl { @@ -1493,15 +1524,6 @@ public: return Id ? Id->getNameStart() : ""; } - /// getNameAsCString - Get the name of identifier for the class - /// interface associated with this implementation as a C string - /// (const char*). - // - // FIXME: Deprecated, move clients to getName(). - const char *getNameAsCString() const { - return Id ? Id->getNameStart() : ""; - } - /// @brief Get the name of the class associated with this interface. // // FIXME: Deprecated, move clients to getName(). @@ -1523,9 +1545,9 @@ raw_ostream &operator<<(raw_ostream &OS, const ObjCCategoryImplDecl &CID); /// method definitions are specified. For example: /// /// @code -/// @implementation MyClass +/// \@implementation MyClass /// - (void)myMethod { /* do something */ } -/// @end +/// \@end /// @endcode /// /// Typically, instance variables are specified in the class interface, @@ -1537,7 +1559,7 @@ class ObjCImplementationDecl : public ObjCImplDecl { virtual void anchor(); /// Implementation Class's super class. ObjCInterfaceDecl *SuperClass; - /// @implementation may have private ivars. + /// \@implementation may have private ivars. SourceLocation IvarLBraceLoc; SourceLocation IvarRBraceLoc; @@ -1549,9 +1571,6 @@ class ObjCImplementationDecl : public ObjCImplDecl { /// true if class has a .cxx_[construct,destruct] method. bool HasCXXStructors : 1; - /// true of class extension has at least one bitfield ivar. - bool HasSynthBitfield : 1; - ObjCImplementationDecl(DeclContext *DC, ObjCInterfaceDecl *classInterface, ObjCInterfaceDecl *superDecl, @@ -1562,7 +1581,7 @@ class ObjCImplementationDecl : public ObjCImplDecl { SuperClass(superDecl), IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc), IvarInitializers(0), NumIvarInitializers(0), - HasCXXStructors(false), HasSynthBitfield(false){} + HasCXXStructors(false) {} public: static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC, ObjCInterfaceDecl *classInterface, @@ -1609,9 +1628,6 @@ public: bool hasCXXStructors() const { return HasCXXStructors; } void setHasCXXStructors(bool val) { HasCXXStructors = val; } - bool hasSynthBitfield() const { return HasSynthBitfield; } - void setHasSynthBitfield (bool val) { HasSynthBitfield = val; } - /// getIdentifier - Get the identifier that names the class /// interface associated with this implementation. IdentifierInfo *getIdentifier() const { @@ -1628,15 +1644,6 @@ public: return getIdentifier()->getName(); } - /// getNameAsCString - Get the name of identifier for the class - /// interface associated with this implementation as a C string - /// (const char*). - // - // FIXME: Move to StringRef API. - const char *getNameAsCString() const { - return getName().data(); - } - /// @brief Get the name of the class associated with this interface. // // FIXME: Move to StringRef API. @@ -1679,7 +1686,7 @@ public: raw_ostream &operator<<(raw_ostream &OS, const ObjCImplementationDecl &ID); /// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is -/// declared as @compatibility_alias alias class. +/// declared as \@compatibility_alias alias class. class ObjCCompatibleAliasDecl : public NamedDecl { virtual void anchor(); /// Class that this is an alias of. @@ -1706,10 +1713,12 @@ public: }; -/// ObjCPropertyDecl - Represents one property declaration in an interface. -/// For example: -/// @property (assign, readwrite) int MyProperty; +/// \brief Represents one property declaration in an Objective-C interface. /// +/// For example: +/// \code{.mm} +/// \@property (assign, readwrite) int MyProperty; +/// \endcode class ObjCPropertyDecl : public NamedDecl { virtual void anchor(); public: @@ -1738,12 +1747,12 @@ public: enum SetterKind { Assign, Retain, Copy, Weak }; enum PropertyControl { None, Required, Optional }; private: - SourceLocation AtLoc; // location of @property + SourceLocation AtLoc; // location of \@property SourceLocation LParenLoc; // location of '(' starting attribute list or null. TypeSourceInfo *DeclType; unsigned PropertyAttributes : NumPropertyAttrsBits; unsigned PropertyAttributesAsWritten : NumPropertyAttrsBits; - // @required/@optional + // \@required/\@optional unsigned PropertyImplementation : 2; Selector GetterName; // getter name of NULL if no getter @@ -1855,7 +1864,7 @@ public: ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; } void setSetterMethodDecl(ObjCMethodDecl *gDecl) { SetterMethodDecl = gDecl; } - // Related to @optional/@required declared in @protocol + // Related to \@optional/\@required declared in \@protocol void setPropertyImplementation(PropertyControl pc) { PropertyImplementation = pc; } @@ -1885,7 +1894,7 @@ public: /// ObjCPropertyImplDecl - Represents implementation declaration of a property /// in a class or category implementation block. For example: -/// @synthesize prop1 = ivar1; +/// \@synthesize prop1 = ivar1; /// class ObjCPropertyImplDecl : public Decl { public: @@ -1894,26 +1903,27 @@ public: Dynamic }; private: - SourceLocation AtLoc; // location of @synthesize or @dynamic + SourceLocation AtLoc; // location of \@synthesize or \@dynamic - /// \brief For @synthesize, the location of the ivar, if it was written in + /// \brief For \@synthesize, the location of the ivar, if it was written in /// the source code. /// /// \code - /// @synthesize int a = b + /// \@synthesize int a = b /// \endcode SourceLocation IvarLoc; /// Property declaration being implemented ObjCPropertyDecl *PropertyDecl; - /// Null for @dynamic. Required for @synthesize. + /// Null for \@dynamic. Required for \@synthesize. ObjCIvarDecl *PropertyIvarDecl; - /// Null for @dynamic. Non-null if property must be copy-constructed in getter + /// Null for \@dynamic. Non-null if property must be copy-constructed in + /// getter. Expr *GetterCXXConstructor; - /// Null for @dynamic. Non-null if property has assignment operator to call + /// Null for \@dynamic. Non-null if property has assignment operator to call /// in Setter synthesis. Expr *SetterCXXAssignment; @@ -1963,6 +1973,17 @@ public: this->IvarLoc = IvarLoc; } + /// \brief For \@synthesize, returns true if an ivar name was explicitly + /// specified. + /// + /// \code + /// \@synthesize int a = b; // true + /// \@synthesize int a; // false + /// \endcode + bool isIvarNameSpecified() const { + return IvarLoc.isValid() && IvarLoc != getLocation(); + } + Expr *getGetterCXXConstructor() const { return GetterCXXConstructor; } diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 36549ea..7affc7e 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the C++ template declaration subclasses. -// +/// +/// \file +/// \brief Defines the C++ template declaration subclasses. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_DECLTEMPLATE_H @@ -38,8 +39,8 @@ class TypeAliasTemplateDecl; typedef llvm::PointerUnion3<TemplateTypeParmDecl*, NonTypeTemplateParmDecl*, TemplateTemplateParmDecl*> TemplateParameter; -/// TemplateParameterList - Stores a list of template parameters for a -/// TemplateDecl and its derived classes. +/// \brief Stores a list of template parameters for a TemplateDecl and its +/// derived classes. class TemplateParameterList { /// The location of the 'template' keyword. SourceLocation TemplateLoc; @@ -64,10 +65,10 @@ public: unsigned NumParams, SourceLocation RAngleLoc); - /// iterator - Iterates through the template parameters in this list. + /// \brief Iterates through the template parameters in this list. typedef NamedDecl** iterator; - /// const_iterator - Iterates through the template parameters in this list. + /// \brief Iterates through the template parameters in this list. typedef NamedDecl* const* const_iterator; iterator begin() { return reinterpret_cast<NamedDecl **>(this + 1); } @@ -90,9 +91,10 @@ public: } /// \brief Returns the minimum number of arguments needed to form a - /// template specialization. This may be fewer than the number of - /// template parameters, if some of the parameters have default - /// arguments or if there is a parameter pack. + /// template specialization. + /// + /// This may be fewer than the number of template parameters, if some of + /// the parameters have default arguments or if there is a parameter pack. unsigned getMinRequiredArguments() const; /// \brief Get the depth of this template parameter list in the set of @@ -111,8 +113,8 @@ public: } }; -/// FixedSizeTemplateParameterList - Stores a list of template parameters for a -/// TemplateDecl and its derived classes. Suitable for creating on the stack. +/// \brief Stores a list of template parameters for a TemplateDecl and its +/// derived classes. Suitable for creating on the stack. template<size_t N> class FixedSizeTemplateParameterList : public TemplateParameterList { NamedDecl *Params[N]; @@ -195,10 +197,11 @@ public: // Kinds of Templates //===----------------------------------------------------------------------===// -/// TemplateDecl - The base class of all kinds of template declarations (e.g., -/// class, function, etc.). The TemplateDecl class stores the list of template -/// parameters and a reference to the templated scoped declaration: the -/// underlying AST node. +/// \brief The base class of all kinds of template declarations (e.g., +/// class, function, etc.). +/// +/// The TemplateDecl class stores the list of template parameters and a +/// reference to the templated scoped declaration: the underlying AST node. class TemplateDecl : public NamedDecl { virtual void anchor(); protected: @@ -404,16 +407,19 @@ public: }; /// \brief Provides information about a dependent function-template -/// specialization declaration. Since explicit function template -/// specialization and instantiation declarations can only appear in -/// namespace scope, and you can only specialize a member of a -/// fully-specialized class, the only way to get one of these is in -/// a friend declaration like the following: +/// specialization declaration. +/// +/// Since explicit function template specialization and instantiation +/// declarations can only appear in namespace scope, and you can only +/// specialize a member of a fully-specialized class, the only way to +/// get one of these is in a friend declaration like the following: /// -/// template <class T> void foo(T); -/// template <class T> class A { +/// \code +/// template \<class T> void foo(T); +/// template \<class T> class A { /// friend void foo<>(T); /// }; +/// \endcode class DependentFunctionTemplateSpecializationInfo { union { // Force sizeof to be a multiple of sizeof(void*) so that the @@ -512,7 +518,8 @@ protected: typedef _SETraits SETraits; typedef _DeclType DeclType; - typedef typename llvm::FoldingSet<EntryType>::iterator SetIteratorType; + typedef typename llvm::FoldingSetVector<EntryType>::iterator + SetIteratorType; SetIteratorType SetIter; @@ -541,13 +548,13 @@ protected: }; template <typename EntryType> - SpecIterator<EntryType> makeSpecIterator(llvm::FoldingSet<EntryType> &Specs, - bool isEnd) { + SpecIterator<EntryType> + makeSpecIterator(llvm::FoldingSetVector<EntryType> &Specs, bool isEnd) { return SpecIterator<EntryType>(isEnd ? Specs.end() : Specs.begin()); } template <class EntryType> typename SpecEntryTraits<EntryType>::DeclType* - findSpecializationImpl(llvm::FoldingSet<EntryType> &Specs, + findSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs, const TemplateArgument *Args, unsigned NumArgs, void *&InsertPos); @@ -583,7 +590,7 @@ protected: public: template <class decl_type> friend class RedeclarableTemplate; - /// Retrieves the canonical declaration of this template. + /// \brief Retrieves the canonical declaration of this template. RedeclarableTemplateDecl *getCanonicalDecl() { return getFirstDeclaration(); } const RedeclarableTemplateDecl *getCanonicalDecl() const { return getFirstDeclaration(); @@ -646,7 +653,7 @@ public: /// /// which was itself created during the instantiation of \c X<int>. Calling /// getInstantiatedFromMemberTemplate() on this FunctionTemplateDecl will - /// retrieve the FunctionTemplateDecl for the original template "f" within + /// retrieve the FunctionTemplateDecl for the original template \c f within /// the class template \c X<T>, i.e., /// /// \code @@ -706,7 +713,7 @@ protected: /// \brief The function template specializations for this function /// template, including explicit specializations and instantiations. - llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations; + llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> Specializations; /// \brief The set of "injected" template arguments used within this /// function template. @@ -732,13 +739,14 @@ protected: /// \brief Retrieve the set of function template specializations of this /// function template. - llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() { + llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> & + getSpecializations() { return getCommonPtr()->Specializations; } /// \brief Add a specialization of this function template. /// - /// \param InsertPos Insert position in the FoldingSet, must have been + /// \param InsertPos Insert position in the FoldingSetVector, must have been /// retrieved by an earlier call to findSpecialization(). void addSpecialization(FunctionTemplateSpecializationInfo* Info, void *InsertPos); @@ -830,8 +838,10 @@ public: // Kinds of Template Parameters //===----------------------------------------------------------------------===// -/// The TemplateParmPosition class defines the position of a template parameter -/// within a template parameter list. Because template parameter can be listed +/// \brief Defines the position of a template parameter within a template +/// parameter list. +/// +/// Because template parameter can be listed /// sequentially for out-of-line template members, each template parameter is /// given a Depth - the nesting of template parameter scopes - and a Position - /// the occurrence within the parameter list. @@ -866,15 +876,17 @@ public: unsigned getIndex() const { return Position; } }; -/// TemplateTypeParmDecl - Declaration of a template type parameter, -/// e.g., "T" in -/// @code +/// \brief Declaration of a template type parameter. +/// +/// For example, "T" in +/// \code /// template<typename T> class vector; -/// @endcode +/// \endcode class TemplateTypeParmDecl : public TypeDecl { /// \brief Whether this template type parameter was declaration with - /// the 'typename' keyword. If false, it was declared with the - /// 'class' keyword. + /// the 'typename' keyword. + /// + /// If false, it was declared with the 'class' keyword. bool Typename : 1; /// \brief Whether this template type parameter inherited its @@ -904,8 +916,9 @@ public: unsigned ID); /// \brief Whether this template type parameter was declared with - /// the 'typename' keyword. If not, it was declared with the 'class' - /// keyword. + /// the 'typename' keyword. + /// + /// If not, it was declared with the 'class' keyword. bool wasDeclaredWithTypename() const { return Typename; } /// \brief Determine whether this template parameter has a default @@ -1688,11 +1701,11 @@ protected: /// \brief The class template specializations for this class /// template, including explicit specializations and instantiations. - llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations; + llvm::FoldingSetVector<ClassTemplateSpecializationDecl> Specializations; /// \brief The class template partial specializations for this class /// template. - llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> + llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> PartialSpecializations; /// \brief The injected-class-name type for this class template. @@ -1710,11 +1723,11 @@ protected: void LoadLazySpecializations(); /// \brief Retrieve the set of specializations of this class template. - llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations(); + llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &getSpecializations(); /// \brief Retrieve the set of partial specializations of this class /// template. - llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> & + llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> & getPartialSpecializations(); ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, @@ -1732,18 +1745,18 @@ protected: } public: - /// Get the underlying class declarations of the template. + /// \brief Get the underlying class declarations of the template. CXXRecordDecl *getTemplatedDecl() const { return static_cast<CXXRecordDecl *>(TemplatedDecl); } - /// Returns whether this template declaration defines the primary + /// \brief Returns whether this template declaration defines the primary /// class pattern. bool isThisDeclarationADefinition() const { return getTemplatedDecl()->isThisDeclarationADefinition(); } - /// Create a class template node. + /// \brief Create a class template node. static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, @@ -1751,7 +1764,7 @@ public: NamedDecl *Decl, ClassTemplateDecl *PrevDecl); - /// Create an empty class template node. + /// \brief Create an empty class template node. static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); /// \brief Return the specialization with the provided arguments if it exists, @@ -1880,14 +1893,18 @@ public: friend class ASTDeclWriter; }; -/// Declaration of a friend template. For example: +/// \brief Declaration of a friend template. /// -/// template <typename T> class A { +/// For example: +/// \code +/// template \<typename T> class A { /// friend class MyVector<T>; // not a friend template -/// template <typename U> friend class B; // not a friend template -/// template <typename U> friend class Foo<T>::Nested; // friend template +/// template \<typename U> friend class B; // not a friend template +/// template \<typename U> friend class Foo<T>::Nested; // friend template /// }; -/// NOTE: This class is not currently in use. All of the above +/// \endcode +/// +/// \note This class is not currently in use. All of the above /// will yield a FriendDecl, not a FriendTemplateDecl. class FriendTemplateDecl : public Decl { virtual void anchor(); @@ -1950,7 +1967,7 @@ public: return Friend.dyn_cast<NamedDecl*>(); } - /// Retrieves the location of the 'friend' keyword. + /// \brief Retrieves the location of the 'friend' keyword. SourceLocation getFriendLoc() const { return FriendLoc; } @@ -1972,9 +1989,12 @@ public: friend class ASTDeclReader; }; -/// Declaration of an alias template. For example: +/// \brief Declaration of an alias template. /// -/// template <typename T> using V = std::map<T*, int, MyCompare<T>>; +/// For example: +/// \code +/// template \<typename T> using V = std::map<T*, int, MyCompare<T>>; +/// \endcode class TypeAliasTemplateDecl : public RedeclarableTemplateDecl { static void DeallocateCommon(void *Ptr); @@ -2046,14 +2066,18 @@ public: friend class ASTDeclWriter; }; -/// Declaration of a function specialization at template class scope. +/// \brief Declaration of a function specialization at template class scope. +/// /// This is a non standard extension needed to support MSVC. +/// /// For example: +/// \code /// template <class T> /// class A { /// template <class U> void foo(U a) { } /// template<> void foo(int a) { } /// } +/// \endcode /// /// "template<> foo(int a)" will be saved in Specialization as a normal /// CXXMethodDecl. Then during an instantiation of class A, it will be @@ -2062,23 +2086,33 @@ class ClassScopeFunctionSpecializationDecl : public Decl { virtual void anchor(); ClassScopeFunctionSpecializationDecl(DeclContext *DC, SourceLocation Loc, - CXXMethodDecl *FD) + CXXMethodDecl *FD, bool Args, + TemplateArgumentListInfo TemplArgs) : Decl(Decl::ClassScopeFunctionSpecialization, DC, Loc), - Specialization(FD) {} + Specialization(FD), HasExplicitTemplateArgs(Args), + TemplateArgs(TemplArgs) {} ClassScopeFunctionSpecializationDecl(EmptyShell Empty) : Decl(Decl::ClassScopeFunctionSpecialization, Empty) {} CXXMethodDecl *Specialization; + bool HasExplicitTemplateArgs; + TemplateArgumentListInfo TemplateArgs; public: CXXMethodDecl *getSpecialization() const { return Specialization; } + bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; } + const TemplateArgumentListInfo& templateArgs() const { return TemplateArgs; } static ClassScopeFunctionSpecializationDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, - CXXMethodDecl *FD) { - return new (C) ClassScopeFunctionSpecializationDecl(DC , Loc, FD); + CXXMethodDecl *FD, + bool HasExplicitTemplateArgs, + TemplateArgumentListInfo TemplateArgs) { + return new (C) ClassScopeFunctionSpecializationDecl(DC , Loc, FD, + HasExplicitTemplateArgs, + TemplateArgs); } static ClassScopeFunctionSpecializationDecl * diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index 6349d9c..6146525 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -58,11 +58,14 @@ public: private: /// StoredNameKind - The kind of name that is actually stored in the /// upper bits of the Ptr field. This is only used internally. + /// + /// Note: The entries here are synchronized with the entries in Selector, + /// for efficient translation between the two. enum StoredNameKind { StoredIdentifier = 0, - StoredObjCZeroArgSelector, - StoredObjCOneArgSelector, - StoredDeclarationNameExtra, + StoredObjCZeroArgSelector = 0x01, + StoredObjCOneArgSelector = 0x02, + StoredDeclarationNameExtra = 0x03, PtrMask = 0x03 }; @@ -106,8 +109,8 @@ private: /// CXXSpecialName, returns a pointer to it. Otherwise, returns /// a NULL pointer. CXXSpecialName *getAsCXXSpecialName() const { - if (getNameKind() >= CXXConstructorName && - getNameKind() <= CXXConversionFunctionName) + NameKind Kind = getNameKind(); + if (Kind >= CXXConstructorName && Kind <= CXXConversionFunctionName) return reinterpret_cast<CXXSpecialName *>(Ptr & ~PtrMask); return 0; } @@ -153,9 +156,9 @@ private: friend class DeclarationNameTable; friend class NamedDecl; - /// getFETokenInfoAsVoid - Retrieves the front end-specified pointer - /// for this name as a void pointer. - void *getFETokenInfoAsVoid() const; + /// getFETokenInfoAsVoidSlow - Retrieves the front end-specified pointer + /// for this name as a void pointer if it's not an identifier. + void *getFETokenInfoAsVoidSlow() const; public: /// DeclarationName - Used to create an empty selector. @@ -168,7 +171,7 @@ public: } // Construct a declaration name from an Objective-C selector. - DeclarationName(Selector Sel); + DeclarationName(Selector Sel) : Ptr(Sel.InfoPtr) { } /// getUsingDirectiveName - Return name for all using-directives. static DeclarationName getUsingDirectiveName(); @@ -251,14 +254,24 @@ public: /// getObjCSelector - Get the Objective-C selector stored in this /// declaration name. - Selector getObjCSelector() const; + Selector getObjCSelector() const { + assert((getNameKind() == ObjCZeroArgSelector || + getNameKind() == ObjCOneArgSelector || + getNameKind() == ObjCMultiArgSelector || + Ptr == 0) && "Not a selector!"); + return Selector(Ptr); + } /// getFETokenInfo/setFETokenInfo - The language front-end is /// allowed to associate arbitrary metadata with some kinds of /// declaration names, including normal identifiers and C++ /// constructors, destructors, and conversion functions. template<typename T> - T *getFETokenInfo() const { return static_cast<T*>(getFETokenInfoAsVoid()); } + T *getFETokenInfo() const { + if (const IdentifierInfo *Info = getAsIdentifierInfo()) + return Info->getFETokenInfo<T>(); + return static_cast<T*>(getFETokenInfoAsVoidSlow()); + } void setFETokenInfo(void *T); @@ -564,7 +577,9 @@ struct DenseMapInfo<clang::DeclarationName> { return clang::DeclarationName::getTombstoneMarker(); } - static unsigned getHashValue(clang::DeclarationName); + static unsigned getHashValue(clang::DeclarationName Name) { + return DenseMapInfo<void*>::getHashValue(Name.getAsOpaquePtr()); + } static inline bool isEqual(clang::DeclarationName LHS, clang::DeclarationName RHS) { diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h index bab1606..d5e9c8c 100644 --- a/include/clang/AST/EvaluatedExprVisitor.h +++ b/include/clang/AST/EvaluatedExprVisitor.h @@ -24,7 +24,7 @@ namespace clang { class ASTContext; -/// \begin Given a potentially-evaluated expression, this visitor visits all +/// \brief Given a potentially-evaluated expression, this visitor visits all /// of its potentially-evaluated subexpressions, recursively. template<typename ImplClass> class EvaluatedExprVisitor : public StmtVisitor<ImplClass> { diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index b0b9b0f..89c003c 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_EXPR_H #include "clang/AST/APValue.h" +#include "clang/AST/Decl.h" #include "clang/AST/Stmt.h" #include "clang/AST/Type.h" #include "clang/AST/DeclAccessPair.h" @@ -179,11 +180,12 @@ public: SourceLocation getExprLoc() const LLVM_READONLY; /// isUnusedResultAWarning - Return true if this immediate expression should - /// be warned about if the result is unused. If so, fill in Loc and Ranges - /// with location to warn on and the source range[s] to report with the - /// warning. - bool isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, - SourceRange &R2, ASTContext &Ctx) const; + /// be warned about if the result is unused. If so, fill in expr, location, + /// and ranges with expr to warn on and source locations/ranges appropriate + /// for a warning. + bool isUnusedResultAWarning(const Expr *&WarnExpr, SourceLocation &Loc, + SourceRange &R1, SourceRange &R2, + ASTContext &Ctx) const; /// isLValue - True if this expression is an "l-value" according to /// the rules of the current language. C and C++ give somewhat @@ -212,7 +214,8 @@ public: LV_InvalidMessageExpression, LV_MemberFunction, LV_SubObjCPropertySetting, - LV_ClassTemporary + LV_ClassTemporary, + LV_ArrayTemporary }; /// Reasons why an expression might not be an l-value. LValueClassification ClassifyLValue(ASTContext &Ctx) const; @@ -223,7 +226,7 @@ public: /// recursively, any member or element of all contained aggregates or unions) /// with a const-qualified type. /// - /// \param Loc [in] [out] - A source location which *may* be filled + /// \param Loc [in,out] - A source location which *may* be filled /// in with the location of the expression making this a /// non-modifiable lvalue, if specified. enum isModifiableLvalueResult { @@ -241,7 +244,8 @@ public: MLV_MemberFunction, MLV_SubObjCPropertySetting, MLV_InvalidMessageExpression, - MLV_ClassTemporary + MLV_ClassTemporary, + MLV_ArrayTemporary }; isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc = 0) const; @@ -260,7 +264,8 @@ public: CL_DuplicateVectorComponents, // A vector shuffle with dupes. CL_MemberFunction, // An expression referring to a member function CL_SubObjCPropertySetting, - CL_ClassTemporary, // A prvalue of class type + CL_ClassTemporary, // A temporary of class type, or subobject thereof. + CL_ArrayTemporary, // A temporary of array type. CL_ObjCMessageRValue, // ObjC message is an rvalue CL_PRValue // A prvalue for any other reason, of any other type }; @@ -505,9 +510,8 @@ public: bool isEvaluatable(const ASTContext &Ctx) const; /// HasSideEffects - This routine returns true for all those expressions - /// which must be evaluated each time and must not be optimized away - /// or evaluated at compile time. Example is a function call, volatile - /// variable read. + /// which have any effect other than producing a value. Example is a function + /// call, volatile variable read, or throwing an exception. bool HasSideEffects(const ASTContext &Ctx) const; /// \brief Determine whether this expression involves a call to any function @@ -537,8 +541,15 @@ public: /// \brief Expression is not a Null pointer constant. NPCK_NotNull = 0, - /// \brief Expression is a Null pointer constant built from a zero integer. - NPCK_ZeroInteger, + /// \brief Expression is a Null pointer constant built from a zero integer + /// expression that is not a simple, possibly parenthesized, zero literal. + /// C++ Core Issue 903 will classify these expressions as "not pointers" + /// once it is adopted. + /// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#903 + NPCK_ZeroExpression, + + /// \brief Expression is a Null pointer constant built from a literal zero. + NPCK_ZeroLiteral, /// \brief Expression is a C++0X nullptr. NPCK_CXX0X_nullptr, @@ -591,6 +602,10 @@ public: return cast<Expr>(Stmt::IgnoreImplicit()); } + const Expr *IgnoreImplicit() const LLVM_READONLY { + return const_cast<Expr*>(this)->IgnoreImplicit(); + } + /// IgnoreParens - Ignore parentheses. If this Expr is a ParenExpr, return /// its subexpression. If that subexpression is also a ParenExpr, /// then this method recursively returns its subexpression, and so forth. @@ -630,6 +645,13 @@ public: /// ParenExpr or CastExprs, returning their operand. Expr *IgnoreParenNoopCasts(ASTContext &Ctx) LLVM_READONLY; + /// Ignore parentheses and derived-to-base casts. + Expr *ignoreParenBaseCasts() LLVM_READONLY; + + const Expr *ignoreParenBaseCasts() const LLVM_READONLY { + return const_cast<Expr*>(this)->ignoreParenBaseCasts(); + } + /// \brief Determine whether this expression is a default function argument. /// /// Default arguments are implicitly generated in the abstract syntax tree @@ -661,6 +683,15 @@ public: static bool hasAnyTypeDependentArguments(llvm::ArrayRef<Expr *> Exprs); + /// \brief For an expression of class type or pointer to class type, + /// return the most derived class decl the expression is known to refer to. + /// + /// If this expression is a cast, this method looks through it to find the + /// most derived decl that can be inferred from the expression. + /// This is valid because derived-to-base conversions have undefined + /// behavior if the object isn't dynamically of the derived type. + const CXXRecordDecl *getBestDynamicClassType() const; + static bool classof(const Stmt *T) { return T->getStmtClass() >= firstExprConstant && T->getStmtClass() <= lastExprConstant; @@ -1043,6 +1074,7 @@ public: enum IdentType { Func, Function, + LFunction, // Same as Function, but as wide string. PrettyFunction, /// PrettyFunctionNoVirtual - The same as PrettyFunction, except that the /// 'virtual' keyword is omitted for virtual member functions. @@ -1142,16 +1174,8 @@ class IntegerLiteral : public Expr, public APIntStorage { public: // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy, // or UnsignedLongLongTy - IntegerLiteral(ASTContext &C, const llvm::APInt &V, - QualType type, SourceLocation l) - : Expr(IntegerLiteralClass, type, VK_RValue, OK_Ordinary, false, false, - false, false), - Loc(l) { - assert(type->isIntegerType() && "Illegal type in IntegerLiteral"); - assert(V.getBitWidth() == C.getIntWidth(type) && - "Integer type is not the correct size for constant."); - setValue(C, V); - } + IntegerLiteral(ASTContext &C, const llvm::APInt &V, QualType type, + SourceLocation l); /// \brief Returns a new integer literal with value 'V' and type 'type'. /// \param type - either IntTy, LongTy, LongLongTy, UnsignedIntTy, @@ -1229,22 +1253,10 @@ class FloatingLiteral : public Expr, private APFloatStorage { SourceLocation Loc; FloatingLiteral(ASTContext &C, const llvm::APFloat &V, bool isexact, - QualType Type, SourceLocation L) - : Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary, false, false, - false, false), Loc(L) { - FloatingLiteralBits.IsIEEE = - &C.getTargetInfo().getLongDoubleFormat() == &llvm::APFloat::IEEEquad; - FloatingLiteralBits.IsExact = isexact; - setValue(C, V); - } + QualType Type, SourceLocation L); /// \brief Construct an empty floating-point literal. - explicit FloatingLiteral(ASTContext &C, EmptyShell Empty) - : Expr(FloatingLiteralClass, Empty) { - FloatingLiteralBits.IsIEEE = - &C.getTargetInfo().getLongDoubleFormat() == &llvm::APFloat::IEEEquad; - FloatingLiteralBits.IsExact = false; - } + explicit FloatingLiteral(ASTContext &C, EmptyShell Empty); public: static FloatingLiteral *Create(ASTContext &C, const llvm::APFloat &V, @@ -1381,8 +1393,8 @@ public: return StringRef(StrData.asChar, getByteLength()); } - /// Allow clients that need the byte representation, such as ASTWriterStmt - /// ::VisitStringLiteral(), access. + /// Allow access to clients that need the byte representation, such as + /// ASTWriterStmt::VisitStringLiteral(). StringRef getBytes() const { // FIXME: StringRef may not be the right type to use as a result for this. if (CharByteWidth == 1) @@ -1395,6 +1407,8 @@ public: getByteLength()); } + void outputString(raw_ostream &OS); + uint32_t getCodeUnit(size_t i) const { assert(i < Length && "out of bounds access"); if (CharByteWidth == 1) diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index b69693d..ecfa9e2 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_EXPRCXX_H #define LLVM_CLANG_AST_EXPRCXX_H +#include "clang/AST/Decl.h" #include "clang/AST/Expr.h" #include "clang/AST/UnresolvedSet.h" #include "clang/AST/TemplateBase.h" @@ -50,14 +51,18 @@ class TemplateArgumentListInfo; class CXXOperatorCallExpr : public CallExpr { /// \brief The overloaded operator. OverloadedOperatorKind Operator; + SourceRange Range; + SourceRange getSourceRangeImpl() const LLVM_READONLY; public: CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn, Expr **args, unsigned numargs, QualType t, ExprValueKind VK, SourceLocation operatorloc) : CallExpr(C, CXXOperatorCallExprClass, fn, 0, args, numargs, t, VK, operatorloc), - Operator(Op) {} + Operator(Op) { + Range = getSourceRangeImpl(); + } explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) : CallExpr(C, CXXOperatorCallExprClass, Empty) { } @@ -65,7 +70,6 @@ public: /// getOperator - Returns the kind of overloaded operator that this /// expression refers to. OverloadedOperatorKind getOperator() const { return Operator; } - void setOperator(OverloadedOperatorKind Kind) { Operator = Kind; } /// getOperatorLoc - Returns the location of the operator symbol in /// the expression. When @c getOperator()==OO_Call, this is the @@ -74,12 +78,15 @@ public: /// bracket. SourceLocation getOperatorLoc() const { return getRParenLoc(); } - SourceRange getSourceRange() const LLVM_READONLY; + SourceRange getSourceRange() const { return Range; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXOperatorCallExprClass; } static bool classof(const CXXOperatorCallExpr *) { return true; } + + friend class ASTStmtReader; + friend class ASTStmtWriter; }; /// CXXMemberCallExpr - Represents a call to a member function that @@ -112,7 +119,7 @@ public: /// declaration as that of the class context of the CXXMethodDecl which this /// function is calling. /// FIXME: Returns 0 for member pointer call exprs. - CXXRecordDecl *getRecordDecl(); + CXXRecordDecl *getRecordDecl() const; static bool classof(const Stmt *T) { return T->getStmtClass() == CXXMemberCallExprClass; @@ -369,10 +376,21 @@ public: return const_cast<UserDefinedLiteral*>(this)->getCookedLiteral(); } + SourceLocation getLocStart() const { + if (getLiteralOperatorKind() == LOK_Template) + return getRParenLoc(); + return getArg(0)->getLocStart(); + } + SourceLocation getLocEnd() const { return getRParenLoc(); } + SourceRange getSourceRange() const { + return SourceRange(getLocStart(), getLocEnd()); + } + + /// getUDSuffixLoc - Returns the location of a ud-suffix in the expression. /// For a string literal, there may be multiple identical suffixes. This /// returns the first. - SourceLocation getUDSuffixLoc() const { return getRParenLoc(); } + SourceLocation getUDSuffixLoc() const { return UDSuffixLoc; } /// getUDSuffix - Returns the ud-suffix specified for this literal. const IdentifierInfo *getUDSuffix() const; @@ -481,6 +499,10 @@ public: Operand = (TypeSourceInfo*)0; } + /// Determine whether this typeid has a type operand which is potentially + /// evaluated, per C++11 [expr.typeid]p3. + bool isPotentiallyEvaluated() const; + bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } /// \brief Retrieves the type operand of this typeid() expression after @@ -859,7 +881,7 @@ public: child_range children() { return child_range(&SubExpr, &SubExpr + 1); } }; -/// CXXConstructExpr - Represents a call to a C++ constructor. +/// \brief Represents a call to a C++ constructor. class CXXConstructExpr : public Expr { public: enum ConstructionKind { @@ -983,6 +1005,7 @@ public: SourceRange getSourceRange() const LLVM_READONLY; SourceRange getParenRange() const { return ParenRange; } + void setParenRange(SourceRange Range) { ParenRange = Range; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXConstructExprClass || @@ -998,9 +1021,13 @@ public: friend class ASTStmtReader; }; -/// CXXFunctionalCastExpr - Represents an explicit C++ type conversion -/// that uses "functional" notion (C++ [expr.type.conv]). Example: @c -/// x = int(0.5); +/// \brief Represents an explicit C++ type conversion that uses "functional" +/// notation (C++ [expr.type.conv]). +/// +/// Example: +/// @code +/// x = int(0.5); +/// @endcode class CXXFunctionalCastExpr : public ExplicitCastExpr { SourceLocation TyBeginLoc; SourceLocation RParenLoc; @@ -1231,7 +1258,8 @@ private: ArrayRef<Expr *> CaptureInits, ArrayRef<VarDecl *> ArrayIndexVars, ArrayRef<unsigned> ArrayIndexStarts, - SourceLocation ClosingBrace); + SourceLocation ClosingBrace, + bool ContainsUnexpandedParameterPack); /// \brief Construct an empty lambda expression. LambdaExpr(EmptyShell Empty, unsigned NumCaptures, bool HasArrayIndexVars) @@ -1269,7 +1297,8 @@ public: ArrayRef<Expr *> CaptureInits, ArrayRef<VarDecl *> ArrayIndexVars, ArrayRef<unsigned> ArrayIndexStarts, - SourceLocation ClosingBrace); + SourceLocation ClosingBrace, + bool ContainsUnexpandedParameterPack); /// \brief Construct a new lambda expression that will be deserialized from /// an external source. @@ -1419,15 +1448,16 @@ public: child_range children() { return child_range(); } }; -/// CXXNewExpr - A new expression for memory allocation and constructor calls, -/// e.g: "new CXXNewExpr(foo)". +/// @brief Represents a new-expression for memory allocation and constructor +// calls, e.g: "new CXXNewExpr(foo)". class CXXNewExpr : public Expr { // Contains an optional array size expression, an optional initialization // expression, and any number of optional placement arguments, in that order. Stmt **SubExprs; - // Points to the allocation function used. + /// \brief Points to the allocation function used. FunctionDecl *OperatorNew; - // Points to the deallocation function used in case of error. May be null. + /// \brief Points to the deallocation function used in case of error. May be + /// null. FunctionDecl *OperatorDelete; /// \brief The allocated type-source information, as written in the source. @@ -1607,8 +1637,8 @@ public: } }; -/// CXXDeleteExpr - A delete expression for memory deallocation and destructor -/// calls, e.g. "delete[] pArray". +/// \brief Represents a \c delete expression for memory deallocation and +/// destructor calls, e.g. "delete[] pArray". class CXXDeleteExpr : public Expr { // Points to the operator delete overload that is used. Could be a member. FunctionDecl *OperatorDelete; @@ -1678,8 +1708,7 @@ public: friend class ASTStmtReader; }; -/// \brief Structure used to store the type being destroyed by a -/// pseudo-destructor expression. +/// \brief Stores the type being destroyed by a pseudo-destructor expression. class PseudoDestructorTypeStorage { /// \brief Either the type source information or the name of the type, if /// it couldn't be resolved due to type-dependence. @@ -1866,11 +1895,14 @@ public: child_range children() { return child_range(&Base, &Base + 1); } }; -/// UnaryTypeTraitExpr - A GCC or MS unary type trait, as used in the -/// implementation of TR1/C++0x type trait templates. +/// \brief Represents a GCC or MS unary type trait, as used in the +/// implementation of TR1/C++11 type trait templates. +/// /// Example: -/// __is_pod(int) == true -/// __is_enum(std::string) == false +/// @code +/// __is_pod(int) == true +/// __is_enum(std::string) == false +/// @endcode class UnaryTypeTraitExpr : public Expr { /// UTT - The trait. A UnaryTypeTrait enum in MSVC compat unsigned. unsigned UTT : 31; @@ -1921,10 +1953,13 @@ public: friend class ASTStmtReader; }; -/// BinaryTypeTraitExpr - A GCC or MS binary type trait, as used in the -/// implementation of TR1/C++0x type trait templates. +/// \brief Represents a GCC or MS binary type trait, as used in the +/// implementation of TR1/C++11 type trait templates. +/// /// Example: -/// __is_base_of(Base, Derived) == true +/// @code +/// __is_base_of(Base, Derived) == true +/// @endcode class BinaryTypeTraitExpr : public Expr { /// BTT - The trait. A BinaryTypeTrait enum in MSVC compat unsigned. unsigned BTT : 8; @@ -2086,30 +2121,33 @@ public: }; -/// ArrayTypeTraitExpr - An Embarcadero array type trait, as used in the -/// implementation of __array_rank and __array_extent. +/// \brief An Embarcadero array type trait, as used in the implementation of +/// __array_rank and __array_extent. +/// /// Example: -/// __array_rank(int[10][20]) == 2 -/// __array_extent(int, 1) == 20 +/// @code +/// __array_rank(int[10][20]) == 2 +/// __array_extent(int, 1) == 20 +/// @endcode class ArrayTypeTraitExpr : public Expr { virtual void anchor(); - /// ATT - The trait. An ArrayTypeTrait enum in MSVC compat unsigned. + /// \brief The trait. An ArrayTypeTrait enum in MSVC compat unsigned. unsigned ATT : 2; - /// The value of the type trait. Unspecified if dependent. + /// \brief The value of the type trait. Unspecified if dependent. uint64_t Value; - /// The array dimension being queried, or -1 if not used + /// \brief The array dimension being queried, or -1 if not used. Expr *Dimension; - /// Loc - The location of the type trait keyword. + /// \brief The location of the type trait keyword. SourceLocation Loc; - /// RParen - The location of the closing paren. + /// \brief The location of the closing paren. SourceLocation RParen; - /// The type being queried. + /// \brief The type being queried. TypeSourceInfo *QueriedType; public: @@ -2156,22 +2194,26 @@ public: friend class ASTStmtReader; }; -/// ExpressionTraitExpr - An expression trait intrinsic +/// \brief An expression trait intrinsic. +/// /// Example: -/// __is_lvalue_expr(std::cout) == true -/// __is_lvalue_expr(1) == false +/// @code +/// __is_lvalue_expr(std::cout) == true +/// __is_lvalue_expr(1) == false +/// @endcode class ExpressionTraitExpr : public Expr { - /// ET - The trait. A ExpressionTrait enum in MSVC compat unsigned. + /// \brief The trait. A ExpressionTrait enum in MSVC compat unsigned. unsigned ET : 31; - /// The value of the type trait. Unspecified if dependent. + /// \brief The value of the type trait. Unspecified if dependent. bool Value : 1; - /// Loc - The location of the type trait keyword. + /// \brief The location of the type trait keyword. SourceLocation Loc; - /// RParen - The location of the closing paren. + /// \brief The location of the closing paren. SourceLocation RParen; + /// \brief The expression being queried. Expr* QueriedExpression; public: ExpressionTraitExpr(SourceLocation loc, ExpressionTrait et, @@ -2190,7 +2232,9 @@ public: : Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false), QueriedExpression() { } - SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc, RParen);} + SourceRange getSourceRange() const LLVM_READONLY { + return SourceRange(Loc, RParen); + } ExpressionTrait getTrait() const { return static_cast<ExpressionTrait>(ET); } @@ -2211,9 +2255,9 @@ public: /// \brief A reference to an overloaded function set, either an -/// \t UnresolvedLookupExpr or an \t UnresolvedMemberExpr. +/// \c UnresolvedLookupExpr or an \c UnresolvedMemberExpr. class OverloadExpr : public Expr { - /// The common name of these declarations. + /// \brief The common name of these declarations. DeclarationNameInfo NameInfo; /// \brief The nested-name-specifier that qualifies the name, if any. @@ -2292,7 +2336,7 @@ public: return Result; } - /// Gets the naming class of this lookup, if any. + /// \brief Gets the naming class of this lookup, if any. CXXRecordDecl *getNamingClass() const; typedef UnresolvedSetImpl::iterator decls_iterator; @@ -2301,25 +2345,25 @@ public: return UnresolvedSetIterator(Results + NumResults); } - /// Gets the number of declarations in the unresolved set. + /// \brief Gets the number of declarations in the unresolved set. unsigned getNumDecls() const { return NumResults; } - /// Gets the full name info. + /// \brief Gets the full name info. const DeclarationNameInfo &getNameInfo() const { return NameInfo; } - /// Gets the name looked up. + /// \brief Gets the name looked up. DeclarationName getName() const { return NameInfo.getName(); } - /// Gets the location of the name. + /// \brief Gets the location of the name. SourceLocation getNameLoc() const { return NameInfo.getLoc(); } - /// Fetches the nested-name qualifier, if one was given. + /// \brief Fetches the nested-name qualifier, if one was given. NestedNameSpecifier *getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } - /// Fetches the nested-name qualifier with source-location information, if - /// one was given. + /// \brief Fetches the nested-name qualifier with source-location + /// information, if one was given. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } /// \brief Retrieve the location of the template keyword preceding @@ -2343,10 +2387,10 @@ public: return getTemplateKWAndArgsInfo()->RAngleLoc; } - /// Determines whether the name was preceded by the template keyword. + /// \brief Determines whether the name was preceded by the template keyword. bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } - /// Determines whether this expression had explicit template arguments. + /// \brief Determines whether this expression had explicit template arguments. bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } // Note that, inconsistently with the explicit-template-argument AST @@ -2370,12 +2414,13 @@ public: return getExplicitTemplateArgs().NumTemplateArgs; } - /// Copies the template arguments into the given structure. + /// \brief Copies the template arguments into the given structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { getExplicitTemplateArgs().copyInto(List); } /// \brief Retrieves the optional explicit template arguments. + /// /// This points to the same data as getExplicitTemplateArgs(), but /// returns null if there are no explicit template arguments. const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() { @@ -2394,15 +2439,15 @@ public: }; /// \brief A reference to a name which we were able to look up during -/// parsing but could not resolve to a specific declaration. This -/// arises in several ways: +/// parsing but could not resolve to a specific declaration. +/// +/// This arises in several ways: /// * we might be waiting for argument-dependent lookup /// * the name might resolve to an overloaded function /// and eventually: /// * the lookup might have included a function template -/// These never include UnresolvedUsingValueDecls, which are always -/// class members and therefore appear only in -/// UnresolvedMemberLookupExprs. +/// These never include UnresolvedUsingValueDecls, which are always class +/// members and therefore appear only in UnresolvedMemberLookupExprs. class UnresolvedLookupExpr : public OverloadExpr { /// True if these lookup results should be extended by /// argument-dependent lookup if this is the operand of a function @@ -2483,8 +2528,8 @@ public: /// argument-dependent lookup. bool requiresADL() const { return RequiresADL; } - /// True if namespace ::std should be artificially added to the set of - /// associated namespaecs for argument-dependent lookup purposes. + /// True if namespace \::std should be artificially added to the set of + /// associated namespaces for argument-dependent lookup purposes. bool isStdAssociatedNamespace() const { return StdIsAssociatedNamespace; } /// True if this lookup is overloaded. @@ -2744,9 +2789,9 @@ public: /// type-dependent. /// /// The explicit type conversions expressed by -/// CXXUnresolvedConstructExpr have the form \c T(a1, a2, ..., aN), -/// where \c T is some type and \c a1, a2, ..., aN are values, and -/// either \C T is a dependent type or one or more of the \c a's is +/// CXXUnresolvedConstructExpr have the form <tt>T(a1, a2, ..., aN)</tt>, +/// where \c T is some type and \c a1, \c a2, ..., \c aN are values, and +/// either \c T is a dependent type or one or more of the <tt>a</tt>'s is /// type-dependent. For example, this would occur in a template such /// as: /// diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index 4bfd12c..93a5ada 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -87,43 +87,45 @@ public: child_range children() { return child_range(); } }; -/// ObjCNumericLiteral - used for objective-c numeric literals; -/// as in: @42 or @true (c++/objc++) or @__yes (c/objc) -class ObjCNumericLiteral : public Expr { - /// Number - expression AST node for the numeric literal - Stmt *Number; - ObjCMethodDecl *ObjCNumericLiteralMethod; - SourceLocation AtLoc; +/// ObjCBoxedExpr - used for generalized expression boxing. +/// as in: @(strdup("hello world")) or @(random()) +/// Also used for boxing non-parenthesized numeric literals; +/// as in: @42 or \@true (c++/objc++) or \@__yes (c/objc). +class ObjCBoxedExpr : public Expr { + Stmt *SubExpr; + ObjCMethodDecl *BoxingMethod; + SourceRange Range; public: - ObjCNumericLiteral(Stmt *NL, QualType T, ObjCMethodDecl *method, - SourceLocation L) - : Expr(ObjCNumericLiteralClass, T, VK_RValue, OK_Ordinary, - false, false, false, false), Number(NL), - ObjCNumericLiteralMethod(method), AtLoc(L) {} - explicit ObjCNumericLiteral(EmptyShell Empty) - : Expr(ObjCNumericLiteralClass, Empty) {} + ObjCBoxedExpr(Expr *E, QualType T, ObjCMethodDecl *method, + SourceRange R) + : Expr(ObjCBoxedExprClass, T, VK_RValue, OK_Ordinary, + E->isTypeDependent(), E->isValueDependent(), + E->isInstantiationDependent(), E->containsUnexpandedParameterPack()), + SubExpr(E), BoxingMethod(method), Range(R) {} + explicit ObjCBoxedExpr(EmptyShell Empty) + : Expr(ObjCBoxedExprClass, Empty) {} - Expr *getNumber() { return cast<Expr>(Number); } - const Expr *getNumber() const { return cast<Expr>(Number); } + Expr *getSubExpr() { return cast<Expr>(SubExpr); } + const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } - ObjCMethodDecl *getObjCNumericLiteralMethod() const { - return ObjCNumericLiteralMethod; + ObjCMethodDecl *getBoxingMethod() const { + return BoxingMethod; } - - SourceLocation getAtLoc() const { return AtLoc; } + + SourceLocation getAtLoc() const { return Range.getBegin(); } SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(AtLoc, Number->getSourceRange().getEnd()); + return Range; } - + static bool classof(const Stmt *T) { - return T->getStmtClass() == ObjCNumericLiteralClass; + return T->getStmtClass() == ObjCBoxedExprClass; } - static bool classof(const ObjCNumericLiteral *) { return true; } + static bool classof(const ObjCBoxedExpr *) { return true; } // Iterators - child_range children() { return child_range(&Number, &Number+1); } - + child_range children() { return child_range(&SubExpr, &SubExpr+1); } + friend class ASTStmtReader; }; @@ -332,9 +334,9 @@ public: }; -/// ObjCEncodeExpr, used for @encode in Objective-C. @encode has the same type -/// and behavior as StringLiteral except that the string initializer is obtained -/// from ASTContext with the encoding type as an argument. +/// ObjCEncodeExpr, used for \@encode in Objective-C. \@encode has the same +/// type and behavior as StringLiteral except that the string initializer is +/// obtained from ASTContext with the encoding type as an argument. class ObjCEncodeExpr : public Expr { TypeSourceInfo *EncodedType; SourceLocation AtLoc, RParenLoc; @@ -376,7 +378,7 @@ public: child_range children() { return child_range(); } }; -/// ObjCSelectorExpr used for @selector in Objective-C. +/// ObjCSelectorExpr used for \@selector in Objective-C. class ObjCSelectorExpr : public Expr { Selector SelName; SourceLocation AtLoc, RParenLoc; @@ -419,19 +421,20 @@ public: /// The return type is "Protocol*". class ObjCProtocolExpr : public Expr { ObjCProtocolDecl *TheProtocol; - SourceLocation AtLoc, RParenLoc; + SourceLocation AtLoc, ProtoLoc, RParenLoc; public: ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol, - SourceLocation at, SourceLocation rp) + SourceLocation at, SourceLocation protoLoc, SourceLocation rp) : Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false, false, false), - TheProtocol(protocol), AtLoc(at), RParenLoc(rp) {} + TheProtocol(protocol), AtLoc(at), ProtoLoc(protoLoc), RParenLoc(rp) {} explicit ObjCProtocolExpr(EmptyShell Empty) : Expr(ObjCProtocolExprClass, Empty) {} ObjCProtocolDecl *getProtocol() const { return TheProtocol; } void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; } + SourceLocation getProtocolIdLoc() const { return ProtoLoc; } SourceLocation getAtLoc() const { return AtLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } void setAtLoc(SourceLocation L) { AtLoc = L; } @@ -448,6 +451,9 @@ public: // Iterators child_range children() { return child_range(); } + + friend class ASTStmtReader; + friend class ASTStmtWriter; }; /// ObjCIvarRefExpr - A reference to an ObjC instance variable. @@ -1019,7 +1025,7 @@ public: /// a l-value or r-value reference will be an l-value or x-value, /// respectively. /// - /// \param LBrac The location of the open square bracket '['. + /// \param LBracLoc The location of the open square bracket '['. /// /// \param SuperLoc The location of the "super" keyword. /// @@ -1033,8 +1039,6 @@ public: /// /// \param Args The message send arguments. /// - /// \param NumArgs The number of arguments. - /// /// \param RBracLoc The location of the closing square bracket ']'. static ObjCMessageExpr *Create(ASTContext &Context, QualType T, ExprValueKind VK, @@ -1059,7 +1063,7 @@ public: /// a l-value or r-value reference will be an l-value or x-value, /// respectively. /// - /// \param LBrac The location of the open square bracket '['. + /// \param LBracLoc The location of the open square bracket '['. /// /// \param Receiver The type of the receiver, including /// source-location information. @@ -1071,8 +1075,6 @@ public: /// /// \param Args The message send arguments. /// - /// \param NumArgs The number of arguments. - /// /// \param RBracLoc The location of the closing square bracket ']'. static ObjCMessageExpr *Create(ASTContext &Context, QualType T, ExprValueKind VK, @@ -1095,7 +1097,7 @@ public: /// a l-value or r-value reference will be an l-value or x-value, /// respectively. /// - /// \param LBrac The location of the open square bracket '['. + /// \param LBracLoc The location of the open square bracket '['. /// /// \param Receiver The expression used to produce the object that /// will receive this message. @@ -1107,8 +1109,6 @@ public: /// /// \param Args The message send arguments. /// - /// \param NumArgs The number of arguments. - /// /// \param RBracLoc The location of the closing square bracket ']'. static ObjCMessageExpr *Create(ASTContext &Context, QualType T, ExprValueKind VK, diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index e2a60d5..7aedfe2 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -179,6 +179,9 @@ public: /// \c ObjCInterfaceDecl::setExternallyCompleted(). 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. diff --git a/include/clang/AST/Makefile b/include/clang/AST/Makefile index 2854b7f..f6dd4ce 100644 --- a/include/clang/AST/Makefile +++ b/include/clang/AST/Makefile @@ -1,6 +1,6 @@ CLANG_LEVEL := ../../.. TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic -BUILT_SOURCES = Attrs.inc AttrImpl.inc StmtNodes.inc DeclNodes.inc +BUILT_SOURCES = Attrs.inc AttrImpl.inc StmtNodes.inc DeclNodes.inc CommentNodes.inc TABLEGEN_INC_FILES_COMMON = 1 @@ -27,3 +27,9 @@ $(ObjDir)/DeclNodes.inc.tmp : $(TD_SRC_DIR)/DeclNodes.td $(CLANG_TBLGEN) \ $(ObjDir)/.dir $(Echo) "Building Clang declaration node tables with tblgen" $(Verb) $(ClangTableGen) -gen-clang-decl-nodes -o $(call SYSPATH, $@) $< + +$(ObjDir)/CommentNodes.inc.tmp : $(TD_SRC_DIR)/CommentNodes.td $(CLANG_TBLGEN) \ + $(ObjDir)/.dir + $(Echo) "Building Clang comment node tables with tblgen" + $(Verb) $(ClangTableGen) -gen-clang-comment-nodes -o $(call SYSPATH, $@) $< + diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h index ca22ed6..a0dffb9 100644 --- a/include/clang/AST/Mangle.h +++ b/include/clang/AST/Mangle.h @@ -121,6 +121,7 @@ public: raw_ostream &) = 0; void mangleGlobalBlock(const BlockDecl *BD, + const NamedDecl *ID, raw_ostream &Out); void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT, const BlockDecl *BD, raw_ostream &Out); @@ -129,7 +130,8 @@ public: void mangleBlock(const DeclContext *DC, const BlockDecl *BD, raw_ostream &Out); // Do the right thing. - void mangleBlock(const BlockDecl *BD, raw_ostream &Out); + void mangleBlock(const BlockDecl *BD, raw_ostream &Out, + const NamedDecl *ID=0); void mangleObjCMethodName(const ObjCMethodDecl *MD, raw_ostream &); diff --git a/include/clang/AST/NSAPI.h b/include/clang/AST/NSAPI.h index 40e9759..51ae1da 100644 --- a/include/clang/AST/NSAPI.h +++ b/include/clang/AST/NSAPI.h @@ -11,11 +11,13 @@ #define LLVM_CLANG_AST_NSAPI_H #include "clang/Basic/IdentifierTable.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" namespace clang { class ASTContext; class QualType; + class Expr; // \brief Provides info and caches identifiers/selectors for NSFoundation API. class NSAPI { @@ -37,15 +39,33 @@ public: enum NSStringMethodKind { NSStr_stringWithString, + NSStr_stringWithUTF8String, + NSStr_stringWithCStringEncoding, + NSStr_stringWithCString, NSStr_initWithString }; - static const unsigned NumNSStringMethods = 2; + static const unsigned NumNSStringMethods = 5; IdentifierInfo *getNSClassId(NSClassIdKindKind K) const; /// \brief The Objective-C NSString selectors. Selector getNSStringSelector(NSStringMethodKind MK) const; + /// \brief Return NSStringMethodKind if \param Sel is such a selector. + llvm::Optional<NSStringMethodKind> getNSStringMethodKind(Selector Sel) const; + + /// \brief Returns true if the expression \param E is a reference of + /// "NSUTF8StringEncoding" enum constant. + bool isNSUTF8StringEncodingConstant(const Expr *E) const { + return isObjCEnumerator(E, "NSUTF8StringEncoding", NSUTF8StringEncodingId); + } + + /// \brief Returns true if the expression \param E is a reference of + /// "NSASCIIStringEncoding" enum constant. + bool isNSASCIIStringEncodingConstant(const Expr *E) const { + return isObjCEnumerator(E, "NSASCIIStringEncoding",NSASCIIStringEncodingId); + } + /// \brief Enumerates the NSArray methods used to generate literals. enum NSArrayMethodKind { NSArr_array, @@ -88,6 +108,35 @@ public: llvm::Optional<NSDictionaryMethodKind> getNSDictionaryMethodKind(Selector Sel); + /// \brief Returns selector for "objectForKeyedSubscript:". + Selector getObjectForKeyedSubscriptSelector() const { + return getOrInitSelector(StringRef("objectForKeyedSubscript"), + objectForKeyedSubscriptSel); + } + + /// \brief Returns selector for "objectAtIndexedSubscript:". + Selector getObjectAtIndexedSubscriptSelector() const { + return getOrInitSelector(StringRef("objectAtIndexedSubscript"), + objectAtIndexedSubscriptSel); + } + + /// \brief Returns selector for "setObject:forKeyedSubscript". + Selector getSetObjectForKeyedSubscriptSelector() const { + StringRef Ids[] = { "setObject", "forKeyedSubscript" }; + return getOrInitSelector(Ids, setObjectForKeyedSubscriptSel); + } + + /// \brief Returns selector for "setObject:atIndexedSubscript". + Selector getSetObjectAtIndexedSubscriptSelector() const { + StringRef Ids[] = { "setObject", "atIndexedSubscript" }; + return getOrInitSelector(Ids, setObjectAtIndexedSubscriptSel); + } + + /// \brief Returns selector for "isEqual:". + Selector getIsEqualSelector() const { + return getOrInitSelector(StringRef("isEqual"), isEqualSel); + } + /// \brief Enumerates the NSNumber methods used to generate literals. enum NSNumberLiteralMethodKind { NSNumberWithChar, @@ -126,10 +175,22 @@ public: /// \brief Determine the appropriate NSNumber factory method kind for a /// literal of the given type. - static llvm::Optional<NSNumberLiteralMethodKind> - getNSNumberFactoryMethodKind(QualType T); + llvm::Optional<NSNumberLiteralMethodKind> + getNSNumberFactoryMethodKind(QualType T) const; + + /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c. + bool isObjCBOOLType(QualType T) const; + /// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c. + bool isObjCNSIntegerType(QualType T) const; + /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c. + bool isObjCNSUIntegerType(QualType T) const; private: + bool isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const; + bool isObjCEnumerator(const Expr *E, + StringRef name, IdentifierInfo *&II) const; + Selector getOrInitSelector(ArrayRef<StringRef> Ids, Selector &Sel) const; + ASTContext &Ctx; mutable IdentifierInfo *ClassIds[NumClassIds]; @@ -145,6 +206,13 @@ private: /// \brief The Objective-C NSNumber selectors used to create NSNumber literals. mutable Selector NSNumberClassSelectors[NumNSNumberLiteralMethods]; mutable Selector NSNumberInstanceSelectors[NumNSNumberLiteralMethods]; + + mutable Selector objectForKeyedSubscriptSel, objectAtIndexedSubscriptSel, + setObjectForKeyedSubscriptSel,setObjectAtIndexedSubscriptSel, + isEqualSel; + + mutable IdentifierInfo *BOOLId, *NSIntegerId, *NSUIntegerId; + mutable IdentifierInfo *NSASCIIStringEncodingId, *NSUTF8StringEncodingId; }; } // end namespace clang diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index b5bd824..a5aec1f 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/include/clang/AST/NestedNameSpecifier.h @@ -31,7 +31,7 @@ class TypeLoc; class LangOptions; /// \brief Represents a C++ nested name specifier, such as -/// "::std::vector<int>::". +/// "\::std::vector<int>::". /// /// C++ nested name specifiers are the prefixes to qualified /// namespaces. For example, "foo::" in "foo::x" is a nested name @@ -190,7 +190,7 @@ public: bool isInstantiationDependent() const; /// \brief Whether this nested-name-specifier contains an unexpanded - /// parameter pack (for C++0x variadic templates). + /// parameter pack (for C++11 variadic templates). bool containsUnexpandedParameterPack() const; /// \brief Print this nested name specifier to the given output @@ -247,7 +247,7 @@ public: /// nested-name-specifier. /// /// For example, if this instance refers to a nested-name-specifier - /// \c ::std::vector<int>::, the returned source range would cover + /// \c \::std::vector<int>::, the returned source range would cover /// from the initial '::' to the last '::'. SourceRange getSourceRange() const LLVM_READONLY; @@ -255,7 +255,7 @@ public: /// 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 + /// \c \::std::vector<int>::, the returned source range would cover /// from "vector" to the last '::'. SourceRange getLocalSourceRange() const; @@ -286,7 +286,7 @@ public: /// \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 + /// \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 { @@ -443,8 +443,9 @@ public: NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const; /// \brief Retrieve a nested-name-specifier with location - /// information based on the information in this builder. This loc - /// will contain references to the builder's internal data and may + /// information based on the information in this builder. + /// + /// This loc will contain references to the builder's internal data and may /// be invalidated by any change to the builder. NestedNameSpecifierLoc getTemporary() const { return NestedNameSpecifierLoc(Representation, Buffer); diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h index 258637d..6359414 100644 --- a/include/clang/AST/OperationKinds.h +++ b/include/clang/AST/OperationKinds.h @@ -291,7 +291,7 @@ enum CastKind { CK_CopyAndAutoreleaseBlockObject }; -#define CK_Invalid ((CastKind) -1) +static const CastKind CK_Invalid = static_cast<CastKind>(-1); enum BinaryOperatorKind { // Operators listed in order of precedence. diff --git a/include/clang/AST/RawCommentList.h b/include/clang/AST/RawCommentList.h new file mode 100644 index 0000000..4901d07 --- /dev/null +++ b/include/clang/AST/RawCommentList.h @@ -0,0 +1,220 @@ +//===--- RawCommentList.h - Classes for processing raw comments -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_RAW_COMMENT_LIST_H +#define LLVM_CLANG_AST_RAW_COMMENT_LIST_H + +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/ArrayRef.h" + +namespace clang { + +class ASTContext; +class ASTReader; +class Decl; + +namespace comments { + class FullComment; +} // end namespace comments + +class RawComment { +public: + enum CommentKind { + RCK_Invalid, ///< Invalid comment + RCK_OrdinaryBCPL, ///< Any normal BCPL comments + RCK_OrdinaryC, ///< Any normal C comment + RCK_BCPLSlash, ///< \code /// stuff \endcode + RCK_BCPLExcl, ///< \code //! stuff \endcode + RCK_JavaDoc, ///< \code /** stuff */ \endcode + RCK_Qt, ///< \code /*! stuff */ \endcode, also used by HeaderDoc + RCK_Merged ///< Two or more documentation comments merged together + }; + + RawComment() : Kind(RCK_Invalid), IsAlmostTrailingComment(false) { } + + RawComment(const SourceManager &SourceMgr, SourceRange SR, + bool Merged = false); + + CommentKind getKind() const LLVM_READONLY { + return (CommentKind) Kind; + } + + bool isInvalid() const LLVM_READONLY { + return Kind == RCK_Invalid; + } + + bool isMerged() const LLVM_READONLY { + return Kind == RCK_Merged; + } + + /// Is this comment attached to any declaration? + bool isAttached() const LLVM_READONLY { + return !DeclOrParsedComment.isNull(); + } + + /// Return the declaration that this comment is attached to. + const Decl *getDecl() const; + + /// Set the declaration that this comment is attached to. + void setDecl(const Decl *D) { + assert(DeclOrParsedComment.isNull()); + DeclOrParsedComment = D; + } + + /// Returns true if it is a comment that should be put after a member: + /// \code ///< stuff \endcode + /// \code //!< stuff \endcode + /// \code /**< stuff */ \endcode + /// \code /*!< stuff */ \endcode + bool isTrailingComment() const LLVM_READONLY { + assert(isDocumentation()); + return IsTrailingComment; + } + + /// Returns true if it is a probable typo: + /// \code //< stuff \endcode + /// \code /*< stuff */ \endcode + bool isAlmostTrailingComment() const LLVM_READONLY { + return IsAlmostTrailingComment; + } + + /// Returns true if this comment is not a documentation comment. + bool isOrdinary() const LLVM_READONLY { + return (Kind == RCK_OrdinaryBCPL) || (Kind == RCK_OrdinaryC); + } + + /// Returns true if this comment any kind of a documentation comment. + bool isDocumentation() const LLVM_READONLY { + return !isInvalid() && !isOrdinary(); + } + + /// Returns raw comment text with comment markers. + StringRef getRawText(const SourceManager &SourceMgr) const { + if (RawTextValid) + return RawText; + + RawText = getRawTextSlow(SourceMgr); + RawTextValid = true; + return RawText; + } + + SourceRange getSourceRange() const LLVM_READONLY { + return Range; + } + + unsigned getBeginLine(const SourceManager &SM) const; + unsigned getEndLine(const SourceManager &SM) const; + + const char *getBriefText(const ASTContext &Context) const { + if (BriefTextValid) + return BriefText; + + return extractBriefText(Context); + } + + /// Returns a \c FullComment AST node, parsing the comment if needed. + comments::FullComment *getParsed(const ASTContext &Context) const { + if (comments::FullComment *FC = + DeclOrParsedComment.dyn_cast<comments::FullComment *>()) + return FC; + + return parse(Context); + } + +private: + SourceRange Range; + + mutable StringRef RawText; + mutable const char *BriefText; + mutable llvm::PointerUnion<const Decl *, comments::FullComment *> + DeclOrParsedComment; + + mutable bool RawTextValid : 1; ///< True if RawText is valid + mutable bool BriefTextValid : 1; ///< True if BriefText is valid + + unsigned Kind : 3; + + bool IsTrailingComment : 1; + bool IsAlmostTrailingComment : 1; + + mutable bool BeginLineValid : 1; ///< True if BeginLine is valid + mutable bool EndLineValid : 1; ///< True if EndLine is valid + mutable unsigned BeginLine; ///< Cached line number + mutable unsigned EndLine; ///< Cached line number + + /// \brief Constructor for AST deserialization. + RawComment(SourceRange SR, CommentKind K, bool IsTrailingComment, + bool IsAlmostTrailingComment) : + Range(SR), RawTextValid(false), BriefTextValid(false), Kind(K), + IsTrailingComment(IsTrailingComment), + IsAlmostTrailingComment(IsAlmostTrailingComment), + BeginLineValid(false), EndLineValid(false) + { } + + StringRef getRawTextSlow(const SourceManager &SourceMgr) const; + + const char *extractBriefText(const ASTContext &Context) const; + + comments::FullComment *parse(const ASTContext &Context) const; + + friend class ASTReader; +}; + +/// \brief Compare comments' source locations. +template<> +class BeforeThanCompare<RawComment> { + const SourceManager &SM; + +public: + explicit BeforeThanCompare(const SourceManager &SM) : SM(SM) { } + + bool operator()(const RawComment &LHS, const RawComment &RHS) { + return SM.isBeforeInTranslationUnit(LHS.getSourceRange().getBegin(), + RHS.getSourceRange().getBegin()); + } + + bool operator()(const RawComment *LHS, const RawComment *RHS) { + return operator()(*LHS, *RHS); + } +}; + +/// \brief This class represents all comments included in the translation unit, +/// sorted in order of appearance in the translation unit. +class RawCommentList { +public: + RawCommentList(SourceManager &SourceMgr) : + SourceMgr(SourceMgr), OnlyWhitespaceSeen(true) { } + + void addComment(const RawComment &RC, llvm::BumpPtrAllocator &Allocator); + + ArrayRef<RawComment *> getComments() const { + return Comments; + } + +private: + SourceManager &SourceMgr; + std::vector<RawComment *> Comments; + RawComment LastComment; + bool OnlyWhitespaceSeen; + + void addCommentsToFront(const std::vector<RawComment *> &C) { + size_t OldSize = Comments.size(); + Comments.resize(C.size() + OldSize); + std::copy_backward(Comments.begin(), Comments.begin() + OldSize, + Comments.end()); + std::copy(C.begin(), C.end(), Comments.begin()); + } + + friend class ASTReader; +}; + +} // end namespace clang + +#endif + diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index ec07267..3a870d0 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -14,10 +14,9 @@ #ifndef LLVM_CLANG_AST_LAYOUTINFO_H #define LLVM_CLANG_AST_LAYOUTINFO_H -#include "llvm/Support/DataTypes.h" -#include "llvm/ADT/DenseMap.h" #include "clang/AST/CharUnits.h" #include "clang/AST/DeclCXX.h" +#include "llvm/ADT/DenseMap.h" namespace clang { class ASTContext; @@ -33,18 +32,43 @@ namespace clang { /// ObjCInterfaceDecl. FIXME - Find appropriate name. /// These objects are managed by ASTContext. class ASTRecordLayout { +public: + struct VBaseInfo { + /// The offset to this virtual base in the complete-object layout + /// of this class. + CharUnits VBaseOffset; + + private: + /// Whether this virtual base requires a vtordisp field in the + /// Microsoft ABI. These fields are required for certain operations + /// in constructors and destructors. + bool HasVtorDisp; + + public: + bool hasVtorDisp() const { return HasVtorDisp; } + + VBaseInfo() : HasVtorDisp(false) {} + + VBaseInfo(CharUnits VBaseOffset, bool hasVtorDisp) : + VBaseOffset(VBaseOffset), HasVtorDisp(hasVtorDisp) {} + }; + + typedef llvm::DenseMap<const CXXRecordDecl *, VBaseInfo> + VBaseOffsetsMapTy; + +private: /// Size - Size of record in characters. CharUnits Size; /// DataSize - Size of record in characters without tail padding. CharUnits DataSize; - /// FieldOffsets - Array of field offsets in bits. - uint64_t *FieldOffsets; - // Alignment - Alignment of record in characters. CharUnits Alignment; + /// FieldOffsets - Array of field offsets in bits. + uint64_t *FieldOffsets; + // FieldCount - Number of fields. unsigned FieldCount; @@ -63,11 +87,13 @@ class ASTRecordLayout { /// any empty subobjects. CharUnits SizeOfLargestEmptySubobject; - /// VFPtrOffset - Virtual function table offset (Microsoft-only). - CharUnits VFPtrOffset; - /// VBPtrOffset - Virtual base table offset (Microsoft-only). CharUnits VBPtrOffset; + + /// HasOwnVFPtr - Does this class provide a virtual function table + /// (vtable in Itanium, vftbl in Microsoft) that is independent from + /// its base classes? + bool HasOwnVFPtr; // TODO: stash this somewhere more efficient /// PrimaryBase - The primary base info for this record. llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase; @@ -79,7 +105,7 @@ class ASTRecordLayout { BaseOffsetsMapTy BaseOffsets; /// VBaseOffsets - Contains a map from vbase classes to their offset. - BaseOffsetsMapTy VBaseOffsets; + VBaseOffsetsMapTy VBaseOffsets; }; /// CXXInfo - If the record layout is for a C++ record, this will have @@ -96,7 +122,7 @@ class ASTRecordLayout { typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy; ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, - CharUnits vfptroffset, CharUnits vbptroffset, + bool hasOwnVFPtr, CharUnits vbptroffset, CharUnits datasize, const uint64_t *fieldoffsets, unsigned fieldcount, CharUnits nonvirtualsize, CharUnits nonvirtualalign, @@ -104,7 +130,7 @@ class ASTRecordLayout { const CXXRecordDecl *PrimaryBase, bool IsPrimaryBaseVirtual, const BaseOffsetsMapTy& BaseOffsets, - const BaseOffsetsMapTy& VBaseOffsets); + const VBaseOffsetsMapTy& VBaseOffsets); ~ASTRecordLayout() {} @@ -180,27 +206,7 @@ public: assert(CXXInfo && "Record layout does not have C++ specific info!"); assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!"); - return CXXInfo->VBaseOffsets[VBase]; - } - - /// getBaseClassOffsetInBits - Get the offset, in bits, for the given - /// base class. - uint64_t getBaseClassOffsetInBits(const CXXRecordDecl *Base) const { - assert(CXXInfo && "Record layout does not have C++ specific info!"); - assert(CXXInfo->BaseOffsets.count(Base) && "Did not find base!"); - - return getBaseClassOffset(Base).getQuantity() * - Base->getASTContext().getCharWidth(); - } - - /// getVBaseClassOffsetInBits - Get the offset, in bits, for the given - /// base class. - uint64_t getVBaseClassOffsetInBits(const CXXRecordDecl *VBase) const { - assert(CXXInfo && "Record layout does not have C++ specific info!"); - assert(CXXInfo->VBaseOffsets.count(VBase) && "Did not find base!"); - - return getVBaseClassOffset(VBase).getQuantity() * - VBase->getASTContext().getCharWidth(); + return CXXInfo->VBaseOffsets[VBase].VBaseOffset; } CharUnits getSizeOfLargestEmptySubobject() const { @@ -208,11 +214,16 @@ public: return CXXInfo->SizeOfLargestEmptySubobject; } - /// getVFPtrOffset - Get the offset for virtual function table pointer. - /// This is only meaningful with the Microsoft ABI. - CharUnits getVFPtrOffset() const { + /// hasOwnVFPtr - Does this class provide its own virtual-function + /// table pointer, rather than inheriting one from a primary base + /// class? If so, it is at offset zero. + /// + /// This implies that the ABI has no primary base class, meaning + /// that it has no base classes that are suitable under the conditions + /// of the ABI. + bool hasOwnVFPtr() const { assert(CXXInfo && "Record layout does not have C++ specific info!"); - return CXXInfo->VFPtrOffset; + return CXXInfo->HasOwnVFPtr; } /// getVBPtrOffset - Get the offset for virtual base table pointer. @@ -221,6 +232,11 @@ public: assert(CXXInfo && "Record layout does not have C++ specific info!"); return CXXInfo->VBPtrOffset; } + + const VBaseOffsetsMapTy &getVBaseOffsetsMap() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + return CXXInfo->VBaseOffsets; + } }; } // end namespace clang diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index f1b5171..2e56a48 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -148,10 +148,15 @@ public: /// TypeLocs. bool shouldWalkTypesOfTypeLocs() const { return true; } + /// \brief Return whether this visitor should recurse into implicit + /// code, e.g., implicit constructors and destructors. + bool shouldVisitImplicitCode() const { return false; } + /// \brief Return whether \param S should be traversed using data recursion /// to avoid a stack overflow with extreme cases. bool shouldUseDataRecursionFor(Stmt *S) const { - return isa<BinaryOperator>(S) || isa<UnaryOperator>(S) || isa<CaseStmt>(S); + return isa<BinaryOperator>(S) || isa<UnaryOperator>(S) || + isa<CaseStmt>(S) || isa<CXXOperatorCallExpr>(S); } /// \brief Recursively visit a statement or expression, by @@ -392,8 +397,8 @@ public: private: // These are helper methods used by more than one Traverse* method. bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL); - bool TraverseClassInstantiations(ClassTemplateDecl* D, Decl *Pattern); - bool TraverseFunctionInstantiations(FunctionTemplateDecl* D) ; + bool TraverseClassInstantiations(ClassTemplateDecl *D); + bool TraverseFunctionInstantiations(FunctionTemplateDecl *D) ; bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, unsigned Count); bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL); @@ -404,18 +409,14 @@ private: bool TraverseFunctionHelper(FunctionDecl *D); bool TraverseVarHelper(VarDecl *D); - bool Walk(Stmt *S); - struct EnqueueJob { Stmt *S; Stmt::child_iterator StmtIt; - EnqueueJob(Stmt *S) : S(S), StmtIt() { - if (Expr *E = dyn_cast_or_null<Expr>(S)) - S = E->IgnoreParens(); - } + EnqueueJob(Stmt *S) : S(S), StmtIt() {} }; bool dataTraverse(Stmt *S); + bool dataTraverseNode(Stmt *S, bool &EnqueueChildren); }; template<typename Derived> @@ -434,7 +435,12 @@ bool RecursiveASTVisitor<Derived>::dataTraverse(Stmt *S) { if (getDerived().shouldUseDataRecursionFor(CurrS)) { if (job.StmtIt == Stmt::child_iterator()) { - if (!Walk(CurrS)) return false; + bool EnqueueChildren = true; + if (!dataTraverseNode(CurrS, EnqueueChildren)) return false; + if (!EnqueueChildren) { + Queue.pop_back(); + continue; + } job.StmtIt = CurrS->child_begin(); } else { ++job.StmtIt; @@ -455,10 +461,25 @@ bool RecursiveASTVisitor<Derived>::dataTraverse(Stmt *S) { } template<typename Derived> -bool RecursiveASTVisitor<Derived>::Walk(Stmt *S) { - +bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S, + bool &EnqueueChildren) { + +// The cast for DISPATCH_WALK is needed for older versions of g++, but causes +// problems for MSVC. So we'll skip the cast entirely for MSVC. +#if defined(_MSC_VER) + #define GCC_CAST(CLASS) +#else + #define GCC_CAST(CLASS) (bool (RecursiveASTVisitor::*)(CLASS*)) +#endif + + // Dispatch to the corresponding WalkUpFrom* function only if the derived + // class didn't override Traverse* (and thus the traversal is trivial). #define DISPATCH_WALK(NAME, CLASS, VAR) \ - return getDerived().WalkUpFrom##NAME(static_cast<CLASS*>(VAR)); + if (&RecursiveASTVisitor::Traverse##NAME == \ + GCC_CAST(CLASS)&Derived::Traverse##NAME) \ + return getDerived().WalkUpFrom##NAME(static_cast<CLASS*>(VAR)); \ + EnqueueChildren = false; \ + return getDerived().Traverse##NAME(static_cast<CLASS*>(VAR)); if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { switch (BinOp->getOpcode()) { @@ -495,6 +516,7 @@ bool RecursiveASTVisitor<Derived>::Walk(Stmt *S) { } #undef DISPATCH_WALK +#undef GCC_CAST return true; } @@ -591,10 +613,9 @@ bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) { if (!D) return true; - // As a syntax visitor, we want to ignore declarations for - // implicitly-defined declarations (ones not typed explicitly by the - // user). - if (D->isImplicit()) + // As a syntax visitor, by default we want to ignore declarations for + // implicit declarations (ones not typed explicitly by the user). + if (!getDerived().shouldVisitImplicitCode() && D->isImplicit()) return true; switch (D->getKind()) { @@ -1231,7 +1252,8 @@ bool RecursiveASTVisitor<Derived>::Traverse##DECL (DECL *D) { \ DEF_TRAVERSE_DECL(AccessSpecDecl, { }) DEF_TRAVERSE_DECL(BlockDecl, { - TRY_TO(TraverseTypeLoc(D->getSignatureAsWritten()->getTypeLoc())); + if (TypeSourceInfo *TInfo = D->getSignatureAsWritten()) + TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); TRY_TO(TraverseStmt(D->getBody())); // This return statement makes sure the traversal of nodes in // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) @@ -1269,7 +1291,13 @@ DEF_TRAVERSE_DECL(FriendTemplateDecl, { }) DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl, { - TRY_TO(TraverseDecl(D->getSpecialization())); + TRY_TO(TraverseDecl(D->getSpecialization())); + + if (D->hasExplicitTemplateArgs()) { + const TemplateArgumentListInfo& args = D->templateArgs(); + TRY_TO(TraverseTemplateArgumentLocsHelper( + args.getArgumentArray(), args.size())); + } }) DEF_TRAVERSE_DECL(LinkageSpecDecl, { }) @@ -1377,35 +1405,20 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper( } // A helper method for traversing the implicit instantiations of a -// class. +// class template. template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseClassInstantiations( - ClassTemplateDecl* D, Decl *Pattern) { - assert(isa<ClassTemplateDecl>(Pattern) || - isa<ClassTemplatePartialSpecializationDecl>(Pattern)); - + ClassTemplateDecl *D) { ClassTemplateDecl::spec_iterator end = D->spec_end(); for (ClassTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) { ClassTemplateSpecializationDecl* SD = *it; switch (SD->getSpecializationKind()) { // Visit the implicit instantiations with the requested pattern. - case TSK_ImplicitInstantiation: { - llvm::PointerUnion<ClassTemplateDecl *, - ClassTemplatePartialSpecializationDecl *> U - = SD->getInstantiatedFrom(); - - bool ShouldVisit; - if (U.is<ClassTemplateDecl*>()) - ShouldVisit = (U.get<ClassTemplateDecl*>() == Pattern); - else - ShouldVisit - = (U.get<ClassTemplatePartialSpecializationDecl*>() == Pattern); - - if (ShouldVisit) - TRY_TO(TraverseDecl(SD)); + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + TRY_TO(TraverseDecl(SD)); break; - } // We don't need to do anything on an explicit instantiation // or explicit specialization because there will be an explicit @@ -1414,11 +1427,6 @@ bool RecursiveASTVisitor<Derived>::TraverseClassInstantiations( case TSK_ExplicitInstantiationDefinition: case TSK_ExplicitSpecialization: break; - - // We don't need to do anything for an uninstantiated - // specialization. - case TSK_Undeclared: - break; } } @@ -1433,12 +1441,12 @@ DEF_TRAVERSE_DECL(ClassTemplateDecl, { // By default, we do not traverse the instantiations of // class templates since they do not appear in the user code. The // following code optionally traverses them. - if (getDerived().shouldVisitTemplateInstantiations()) { - // If this is the definition of the primary template, visit - // instantiations which were formed from this pattern. - if (D->isThisDeclarationADefinition()) - TRY_TO(TraverseClassInstantiations(D, D)); - } + // + // We only traverse the class instantiations when we see the canonical + // declaration of the template, to ensure we only visit them once. + if (getDerived().shouldVisitTemplateInstantiations() && + D == D->getCanonicalDecl()) + TRY_TO(TraverseClassInstantiations(D)); // Note that getInstantiatedFromMemberTemplate() is just a link // from a template instantiation back to the template from which @@ -1449,24 +1457,25 @@ DEF_TRAVERSE_DECL(ClassTemplateDecl, { // function while skipping its specializations. template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations( - FunctionTemplateDecl* D) { + FunctionTemplateDecl *D) { FunctionTemplateDecl::spec_iterator end = D->spec_end(); for (FunctionTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) { FunctionDecl* FD = *it; switch (FD->getTemplateSpecializationKind()) { + case TSK_Undeclared: case TSK_ImplicitInstantiation: // We don't know what kind of FunctionDecl this is. TRY_TO(TraverseDecl(FD)); break; - // No need to visit explicit instantiations, we'll find the node - // eventually. + // FIXME: For now traverse explicit instantiations here. Change that + // once they are represented as dedicated nodes in the AST. case TSK_ExplicitInstantiationDeclaration: case TSK_ExplicitInstantiationDefinition: + TRY_TO(TraverseDecl(FD)); break; - case TSK_Undeclared: // Declaration of the template definition. case TSK_ExplicitSpecialization: break; } @@ -1480,26 +1489,21 @@ DEF_TRAVERSE_DECL(FunctionTemplateDecl, { TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); // By default, we do not traverse the instantiations of - // function templates since they do not apprear in the user code. The + // function templates since they do not appear in the user code. The // following code optionally traverses them. - if (getDerived().shouldVisitTemplateInstantiations()) { - // Explicit function specializations will be traversed from the - // context of their declaration. There is therefore no need to - // traverse them for here. - // - // In addition, we only traverse the function instantiations when - // the function template is a function template definition. - if (D->isThisDeclarationADefinition()) { - TRY_TO(TraverseFunctionInstantiations(D)); - } - } + // + // We only traverse the function instantiations when we see the canonical + // declaration of the template, to ensure we only visit them once. + if (getDerived().shouldVisitTemplateInstantiations() && + D == D->getCanonicalDecl()) + TRY_TO(TraverseFunctionInstantiations(D)); }) DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, { // D is the "T" in something like // template <template <typename> class T> class container { }; TRY_TO(TraverseDecl(D->getTemplatedDecl())); - if (D->hasDefaultArgument()) { + if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument())); } TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); @@ -1509,7 +1513,7 @@ DEF_TRAVERSE_DECL(TemplateTypeParmDecl, { // D is the "T" in something like "template<typename T> class vector;" if (D->getTypeForDecl()) TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); - if (D->hasDefaultArgument()) + if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc())); }) @@ -1567,7 +1571,7 @@ bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper( CXXRecordDecl *D) { if (!TraverseRecordHelper(D)) return false; - if (D->hasDefinition()) { + if (D->isCompleteDefinition()) { for (CXXRecordDecl::base_class_iterator I = D->bases_begin(), E = D->bases_end(); I != E; ++I) { @@ -1634,11 +1638,7 @@ DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, { // template args here. TRY_TO(TraverseCXXRecordHelper(D)); - // If we're visiting instantiations, visit the instantiations of - // this template now. - if (getDerived().shouldVisitTemplateInstantiations() && - D->isThisDeclarationADefinition()) - TRY_TO(TraverseClassInstantiations(D->getSpecializedTemplate(), D)); + // Instantiations will have been visited with the primary template. }) DEF_TRAVERSE_DECL(EnumConstantDecl, { @@ -1714,7 +1714,9 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { // FunctionNoProtoType or FunctionProtoType, or a typedef. This // also covers the return type and the function parameters, // including exception specifications. - TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); + if (clang::TypeSourceInfo *TSI = D->getTypeSourceInfo()) { + TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); + } if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { // Constructor initializers. @@ -1767,7 +1769,8 @@ template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) { TRY_TO(TraverseDeclaratorHelper(D)); // Default params are taken care of when we traverse the ParmVarDecl. - if (!isa<ParmVarDecl>(D)) + if (!isa<ParmVarDecl>(D) && + (!D->isCXXForRangeDecl() || getDerived().shouldVisitImplicitCode())) TRY_TO(TraverseStmt(D->getInit())); return true; } @@ -1783,7 +1786,8 @@ DEF_TRAVERSE_DECL(ImplicitParamDecl, { DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, { // A non-type template parameter, e.g. "S" in template<int S> class Foo ... TRY_TO(TraverseDeclaratorHelper(D)); - TRY_TO(TraverseStmt(D->getDefaultArgument())); + if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) + TRY_TO(TraverseStmt(D->getDefaultArgument())); }) DEF_TRAVERSE_DECL(ParmVarDecl, { @@ -1837,6 +1841,11 @@ DEF_TRAVERSE_STMT(AsmStmt, { // children() iterates over inputExpr and outputExpr. }) +DEF_TRAVERSE_STMT(MSAsmStmt, { + // FIXME: MS Asm doesn't currently parse Constraints, Clobbers, etc. Once + // added this needs to be implemented. + }) + DEF_TRAVERSE_STMT(CXXCatchStmt, { TRY_TO(TraverseDecl(S->getExceptionDecl())); // children() iterates over the handler block. @@ -1879,7 +1888,15 @@ DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { }) DEF_TRAVERSE_STMT(ObjCAtTryStmt, { }) DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { }) DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, { }) -DEF_TRAVERSE_STMT(CXXForRangeStmt, { }) +DEF_TRAVERSE_STMT(CXXForRangeStmt, { + if (!getDerived().shouldVisitImplicitCode()) { + TRY_TO(TraverseStmt(S->getLoopVarStmt())); + TRY_TO(TraverseStmt(S->getRangeInit())); + TRY_TO(TraverseStmt(S->getBody())); + // Visit everything else only if shouldVisitImplicitCode(). + return true; + } +}) DEF_TRAVERSE_STMT(MSDependentExistsStmt, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo())); @@ -2146,7 +2163,10 @@ DEF_TRAVERSE_STMT(ExtVectorElementExpr, { }) DEF_TRAVERSE_STMT(GNUNullExpr, { }) DEF_TRAVERSE_STMT(ImplicitValueInitExpr, { }) DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, { }) -DEF_TRAVERSE_STMT(ObjCEncodeExpr, { }) +DEF_TRAVERSE_STMT(ObjCEncodeExpr, { + if (TypeSourceInfo *TInfo = S->getEncodedTypeSourceInfo()) + TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); +}) DEF_TRAVERSE_STMT(ObjCIsaExpr, { }) DEF_TRAVERSE_STMT(ObjCIvarRefExpr, { }) DEF_TRAVERSE_STMT(ObjCMessageExpr, { }) @@ -2209,7 +2229,7 @@ DEF_TRAVERSE_STMT(FloatingLiteral, { }) DEF_TRAVERSE_STMT(ImaginaryLiteral, { }) DEF_TRAVERSE_STMT(StringLiteral, { }) DEF_TRAVERSE_STMT(ObjCStringLiteral, { }) -DEF_TRAVERSE_STMT(ObjCNumericLiteral, { }) +DEF_TRAVERSE_STMT(ObjCBoxedExpr, { }) DEF_TRAVERSE_STMT(ObjCArrayLiteral, { }) DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, { }) diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h index 88abadb..e3b340a 100644 --- a/include/clang/AST/Redeclarable.h +++ b/include/clang/AST/Redeclarable.h @@ -25,26 +25,25 @@ template<typename decl_type> class Redeclarable { protected: - // FIXME: PointerIntPair is a value class that should not be inherited from. - // This should change to using containment. - struct DeclLink : public llvm::PointerIntPair<decl_type *, 1, bool> { + class DeclLink { + llvm::PointerIntPair<decl_type *, 1, bool> NextAndIsPrevious; + public: DeclLink(decl_type *D, bool isLatest) - : llvm::PointerIntPair<decl_type *, 1, bool>(D, isLatest) { } - - typedef llvm::PointerIntPair<decl_type *, 1, bool> base_type; + : NextAndIsPrevious(D, isLatest) { } - bool NextIsPrevious() const { return base_type::getInt() == false; } - bool NextIsLatest() const { return base_type::getInt() == true; } - decl_type *getNext() const { return base_type::getPointer(); } + bool NextIsPrevious() const { return !NextAndIsPrevious.getInt(); } + bool NextIsLatest() const { return NextAndIsPrevious.getInt(); } + decl_type *getNext() const { return NextAndIsPrevious.getPointer(); } + void setNext(decl_type *D) { NextAndIsPrevious.setPointer(D); } }; - struct PreviousDeclLink : public DeclLink { - PreviousDeclLink(decl_type *D) : DeclLink(D, false) { } - }; + static DeclLink PreviousDeclLink(decl_type *D) { + return DeclLink(D, false); + } - struct LatestDeclLink : public DeclLink { - LatestDeclLink(decl_type *D) : DeclLink(D, true) { } - }; + static DeclLink LatestDeclLink(decl_type *D) { + return DeclLink(D, true); + } /// \brief Points to the next redeclaration in the chain. /// diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 1b0f576..79e1920 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -19,8 +19,8 @@ #include "clang/AST/PrettyPrinter.h" #include "clang/AST/StmtIterator.h" #include "clang/AST/DeclGroup.h" -#include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" +#include "clang/Lex/Token.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" @@ -37,9 +37,11 @@ namespace clang { class ParmVarDecl; class QualType; class IdentifierInfo; + class LabelDecl; class SourceManager; class StringLiteral; class SwitchStmt; + class VarDecl; //===--------------------------------------------------------------------===// // ExprIterator - Iterators for iterating over Stmt* arrays that contain @@ -499,6 +501,14 @@ public: decl_iterator decl_end() { return DG.end(); } const_decl_iterator decl_begin() const { return DG.begin(); } const_decl_iterator decl_end() const { return DG.end(); } + + typedef std::reverse_iterator<decl_iterator> reverse_decl_iterator; + reverse_decl_iterator decl_rbegin() { + return reverse_decl_iterator(decl_end()); + } + reverse_decl_iterator decl_rend() { + return reverse_decl_iterator(decl_begin()); + } }; /// NullStmt - This is the null statement ";": C99 6.8.3p3. @@ -545,20 +555,13 @@ class CompoundStmt : public Stmt { Stmt** Body; SourceLocation LBracLoc, RBracLoc; public: - CompoundStmt(ASTContext& C, Stmt **StmtStart, unsigned NumStmts, - SourceLocation LB, SourceLocation RB) - : Stmt(CompoundStmtClass), LBracLoc(LB), RBracLoc(RB) { - CompoundStmtBits.NumStmts = NumStmts; - assert(CompoundStmtBits.NumStmts == NumStmts && - "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!"); - - if (NumStmts == 0) { - Body = 0; - return; - } + CompoundStmt(ASTContext &C, Stmt **StmtStart, unsigned NumStmts, + SourceLocation LB, SourceLocation RB); - Body = new (C) Stmt*[NumStmts]; - memcpy(Body, StmtStart, NumStmts * sizeof(*Body)); + // \brief Build an empty compound statment with a location. + explicit CompoundStmt(SourceLocation Loc) + : Stmt(CompoundStmtClass), Body(0), LBracLoc(Loc), RBracLoc(Loc) { + CompoundStmtBits.NumStmts = 0; } // \brief Build an empty compound statement. @@ -803,24 +806,32 @@ public: class AttributedStmt : public Stmt { Stmt *SubStmt; SourceLocation AttrLoc; - AttrVec Attrs; - // TODO: It can be done as Attr *Attrs[1]; and variable size array as in - // StringLiteral + unsigned NumAttrs; + const Attr *Attrs[1]; friend class ASTStmtReader; -public: - AttributedStmt(SourceLocation loc, const AttrVec &attrs, Stmt *substmt) - : Stmt(AttributedStmtClass), SubStmt(substmt), AttrLoc(loc), Attrs(attrs) { + AttributedStmt(SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt) + : Stmt(AttributedStmtClass), SubStmt(SubStmt), AttrLoc(Loc), + NumAttrs(Attrs.size()) { + memcpy(this->Attrs, Attrs.data(), Attrs.size() * sizeof(Attr*)); } - // \brief Build an empty attributed statement. - explicit AttributedStmt(EmptyShell Empty) - : Stmt(AttributedStmtClass, Empty) { + explicit AttributedStmt(EmptyShell Empty, unsigned NumAttrs) + : Stmt(AttributedStmtClass, Empty), NumAttrs(NumAttrs) { + memset(Attrs, 0, NumAttrs * sizeof(Attr*)); } +public: + static AttributedStmt *Create(ASTContext &C, SourceLocation Loc, + ArrayRef<const Attr*> Attrs, Stmt *SubStmt); + // \brief Build an empty attributed statement. + static AttributedStmt *CreateEmpty(ASTContext &C, unsigned NumAttrs); + SourceLocation getAttrLoc() const { return AttrLoc; } - const AttrVec &getAttrs() const { return Attrs; } + ArrayRef<const Attr*> getAttrs() const { + return ArrayRef<const Attr*>(Attrs, NumAttrs); + } Stmt *getSubStmt() { return SubStmt; } const Stmt *getSubStmt() const { return SubStmt; } @@ -1606,6 +1617,69 @@ public: } }; +/// MSAsmStmt - This represents a MS inline-assembly statement extension. +/// +class MSAsmStmt : public Stmt { + SourceLocation AsmLoc, EndLoc; + std::string AsmStr; + + bool IsSimple; + bool IsVolatile; + + unsigned NumAsmToks; + unsigned NumLineEnds; + unsigned NumClobbers; + + Token *AsmToks; + unsigned *LineEnds; + Stmt **Exprs; + StringRef *Clobbers; + +public: + MSAsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, + bool isvolatile, ArrayRef<Token> asmtoks, + ArrayRef<unsigned> lineends, StringRef asmstr, + ArrayRef<StringRef> clobbers, SourceLocation endloc); + + SourceLocation getAsmLoc() const { return AsmLoc; } + void setAsmLoc(SourceLocation L) { AsmLoc = L; } + SourceLocation getEndLoc() const { return EndLoc; } + void setEndLoc(SourceLocation L) { EndLoc = L; } + + unsigned getNumAsmToks() { return NumAsmToks; } + Token *getAsmToks() { return AsmToks; } + unsigned getNumLineEnds() { return NumLineEnds; } + unsigned *getLineEnds() { return LineEnds; } + + bool isVolatile() const { return IsVolatile; } + void setVolatile(bool V) { IsVolatile = V; } + bool isSimple() const { return IsSimple; } + void setSimple(bool V) { IsSimple = V; } + + //===--- Asm String Analysis ---===// + + const std::string *getAsmString() const { return &AsmStr; } + std::string *getAsmString() { return &AsmStr; } + void setAsmString(StringRef &E) { AsmStr = E.str(); } + + //===--- Other ---===// + + unsigned getNumClobbers() const { return NumClobbers; } + StringRef getClobber(unsigned i) { return Clobbers[i]; } + + SourceRange getSourceRange() const LLVM_READONLY { + return SourceRange(AsmLoc, EndLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == MSAsmStmtClass; + } + static bool classof(const MSAsmStmt *) { return true; } + + child_range children() { + return child_range(&Exprs[0], &Exprs[0]); + } +}; + class SEHExceptStmt : public Stmt { SourceLocation Loc; Stmt *Children[2]; diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h index a321041..e7e1232 100644 --- a/include/clang/AST/StmtObjC.h +++ b/include/clang/AST/StmtObjC.h @@ -6,10 +6,9 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the Objective-C statement AST node classes. -// -//===----------------------------------------------------------------------===// + +/// \file +/// \brief Defines the Objective-C statement AST node classes. #ifndef LLVM_CLANG_AST_STMTOBJC_H #define LLVM_CLANG_AST_STMTOBJC_H @@ -19,9 +18,9 @@ namespace clang { -/// ObjCForCollectionStmt - This represents Objective-c's collection statement; -/// represented as 'for (element 'in' collection-expression)' stmt. +/// \brief Represents Objective-C's collection statement. /// +/// This is represented as 'for (element 'in' collection-expression)' stmt. class ObjCForCollectionStmt : public Stmt { enum { ELEM, COLLECTION, BODY, END_EXPR }; Stmt* SubExprs[END_EXPR]; // SubExprs[ELEM] is an expression or declstmt. @@ -70,7 +69,7 @@ public: } }; -/// ObjCAtCatchStmt - This represents objective-c's @catch statement. +/// \brief Represents Objective-C's \@catch statement. class ObjCAtCatchStmt : public Stmt { private: VarDecl *ExceptionDecl; @@ -118,7 +117,7 @@ public: child_range children() { return child_range(&Body, &Body + 1); } }; -/// ObjCAtFinallyStmt - This represent objective-c's @finally Statement +/// \brief Represents Objective-C's \@finally statement class ObjCAtFinallyStmt : public Stmt { Stmt *AtFinallyStmt; SourceLocation AtFinallyLoc; @@ -151,24 +150,23 @@ public: } }; -/// ObjCAtTryStmt - This represent objective-c's over-all -/// @try ... @catch ... @finally statement. +/// \brief Represents Objective-C's \@try ... \@catch ... \@finally statement. class ObjCAtTryStmt : public Stmt { private: - // The location of the + // The location of the @ in the \@try. SourceLocation AtTryLoc; // The number of catch blocks in this statement. unsigned NumCatchStmts : 16; - // Whether this statement has a @finally statement. + // Whether this statement has a \@finally statement. bool HasFinally : 1; - /// \brief Retrieve the statements that are stored after this @try statement. + /// \brief Retrieve the statements that are stored after this \@try statement. /// /// The order of the statements in memory follows the order in the source, - /// with the @try body first, followed by the @catch statements (if any) and, - /// finally, the @finally (if it exists). + /// with the \@try body first, followed by the \@catch statements (if any) + /// and, finally, the \@finally (if it exists). Stmt **getStmts() { return reinterpret_cast<Stmt **> (this + 1); } const Stmt* const *getStmts() const { return reinterpret_cast<const Stmt * const*> (this + 1); @@ -192,26 +190,26 @@ public: unsigned NumCatchStmts, bool HasFinally); - /// \brief Retrieve the location of the @ in the @try. + /// \brief Retrieve the location of the @ in the \@try. SourceLocation getAtTryLoc() const { return AtTryLoc; } void setAtTryLoc(SourceLocation Loc) { AtTryLoc = Loc; } - /// \brief Retrieve the @try body. + /// \brief Retrieve the \@try body. const Stmt *getTryBody() const { return getStmts()[0]; } Stmt *getTryBody() { return getStmts()[0]; } void setTryBody(Stmt *S) { getStmts()[0] = S; } - /// \brief Retrieve the number of @catch statements in this try-catch-finally + /// \brief Retrieve the number of \@catch statements in this try-catch-finally /// block. unsigned getNumCatchStmts() const { return NumCatchStmts; } - /// \brief Retrieve a @catch statement. + /// \brief Retrieve a \@catch statement. const ObjCAtCatchStmt *getCatchStmt(unsigned I) const { assert(I < NumCatchStmts && "Out-of-bounds @catch index"); return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]); } - /// \brief Retrieve a @catch statement. + /// \brief Retrieve a \@catch statement. ObjCAtCatchStmt *getCatchStmt(unsigned I) { assert(I < NumCatchStmts && "Out-of-bounds @catch index"); return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]); @@ -223,7 +221,7 @@ public: getStmts()[I + 1] = S; } - /// Retrieve the @finally statement, if any. + /// \brief Retrieve the \@finally statement, if any. const ObjCAtFinallyStmt *getFinallyStmt() const { if (!HasFinally) return 0; @@ -254,11 +252,14 @@ public: } }; -/// ObjCAtSynchronizedStmt - This is for objective-c's @synchronized statement. -/// Example: @synchronized (sem) { -/// do-something; -/// } +/// \brief Represents Objective-C's \@synchronized statement. /// +/// Example: +/// \code +/// @synchronized (sem) { +/// do-something; +/// } +/// \endcode class ObjCAtSynchronizedStmt : public Stmt { private: enum { SYNC_EXPR, SYNC_BODY, END_EXPR }; @@ -309,7 +310,7 @@ public: } }; -/// ObjCAtThrowStmt - This represents objective-c's @throw statement. +/// \brief Represents Objective-C's \@throw statement. class ObjCAtThrowStmt : public Stmt { Stmt *Throw; SourceLocation AtThrowLoc; @@ -343,8 +344,7 @@ public: child_range children() { return child_range(&Throw, &Throw+1); } }; -/// ObjCAutoreleasePoolStmt - This represent objective-c's -/// @autoreleasepool Statement +/// \brief Represents Objective-C's \@autoreleasepool Statement class ObjCAutoreleasePoolStmt : public Stmt { Stmt *SubStmt; SourceLocation AtLoc; diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 65f5460..54c9f2c 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -73,7 +73,15 @@ private: union { uintptr_t TypeOrValue; struct { - char Value[sizeof(llvm::APSInt)]; + // We store a decomposed APSInt with the data allocated by ASTContext if + // BitWidth > 64. The memory may be shared between multiple + // TemplateArgument instances. + union { + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + const uint64_t *pVal; ///< Used to store the >64 bits integer value. + }; + unsigned BitWidth : 31; + unsigned IsUnsigned : 1; void *Type; } Integer; struct { @@ -104,11 +112,15 @@ public: TypeOrValue = reinterpret_cast<uintptr_t>(D); } - /// \brief Construct an integral constant template argument. - TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) { - // FIXME: Large integral values will get leaked. Do something - // similar to what we did with IntegerLiteral. - new (Integer.Value) llvm::APSInt(Value); + /// \brief Construct an integral constant template argument. The memory to + /// store the value is allocated with Ctx. + TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type); + + /// \brief Construct an integral constant template argument with the same + /// value as Other but a different type. + TemplateArgument(const TemplateArgument &Other, QualType Type) + : Kind(Integral) { + Integer = Other.Integer; Integer.Type = Type.getAsOpaquePtr(); } @@ -165,62 +177,6 @@ public: this->Args.NumArgs = NumArgs; } - /// \brief Copy constructor for a template argument. - TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) { - // FIXME: Large integral values will get leaked. Do something - // similar to what we did with IntegerLiteral. - if (Kind == Integral) { - new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); - Integer.Type = Other.Integer.Type; - } else if (Kind == Pack) { - Args.NumArgs = Other.Args.NumArgs; - Args.Args = Other.Args.Args; - } else if (Kind == Template || Kind == TemplateExpansion) { - TemplateArg.Name = Other.TemplateArg.Name; - TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions; - } else - TypeOrValue = Other.TypeOrValue; - } - - TemplateArgument& operator=(const TemplateArgument& Other) { - using llvm::APSInt; - - if (Kind == Other.Kind && Kind == Integral) { - // Copy integral values. - *this->getAsIntegral() = *Other.getAsIntegral(); - Integer.Type = Other.Integer.Type; - return *this; - } - - // Destroy the current integral value, if that's what we're holding. - if (Kind == Integral) - getAsIntegral()->~APSInt(); - - Kind = Other.Kind; - - if (Other.Kind == Integral) { - new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); - Integer.Type = Other.Integer.Type; - } else if (Other.Kind == Pack) { - Args.NumArgs = Other.Args.NumArgs; - Args.Args = Other.Args.Args; - } else if (Kind == Template || Kind == TemplateExpansion) { - TemplateArg.Name = Other.TemplateArg.Name; - TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions; - } else { - TypeOrValue = Other.TypeOrValue; - } - - return *this; - } - - ~TemplateArgument() { - using llvm::APSInt; - - if (Kind == Integral) - getAsIntegral()->~APSInt(); - } - /// \brief Create a new template argument pack by copying the given set of /// template arguments. static TemplateArgument CreatePackCopy(ASTContext &Context, @@ -286,14 +242,15 @@ public: llvm::Optional<unsigned> getNumTemplateExpansions() const; /// \brief Retrieve the template argument as an integral value. - llvm::APSInt *getAsIntegral() { - if (Kind != Integral) - return 0; - return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]); - } + // FIXME: Provide a way to read the integral data without copying the value. + llvm::APSInt getAsIntegral() const { + using namespace llvm; + if (Integer.BitWidth <= 64) + return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned); - const llvm::APSInt *getAsIntegral() const { - return const_cast<TemplateArgument*>(this)->getAsIntegral(); + unsigned NumWords = APInt::getNumWords(Integer.BitWidth); + return APSInt(APInt(Integer.BitWidth, makeArrayRef(Integer.pVal, NumWords)), + Integer.IsUnsigned); } /// \brief Retrieve the type of the integral value. @@ -342,14 +299,12 @@ public: return Args.NumArgs; } - /// Determines whether two template arguments are superficially the + /// \brief Determines whether two template arguments are superficially the /// same. bool structurallyEquals(const TemplateArgument &Other) const; - /// \brief When the template argument is a pack expansion, returns + /// \brief When the template argument is a pack expansion, returns /// the pattern of the pack expansion. - /// - /// \param Ellipsis Will be set to the location of the ellipsis. TemplateArgument getPackExpansionPattern() const; /// \brief Print this template argument to the given output stream. diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 7b615c1..6564b66 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -29,6 +29,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/Twine.h" #include "clang/Basic/LLVM.h" namespace clang { @@ -377,8 +378,6 @@ public: return hasConst(); } - bool isSupersetOf(Qualifiers Other) const; - /// \brief Determine whether this set of qualifiers is a strict superset of /// another set of qualifiers, not considering qualifier compatibility. bool isStrictSupersetOf(Qualifiers Other) const; @@ -412,12 +411,11 @@ public: } std::string getAsString() const; - std::string getAsString(const PrintingPolicy &Policy) const { - std::string Buffer; - getAsStringInternal(Buffer, Policy); - return Buffer; - } - void getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const; + std::string getAsString(const PrintingPolicy &Policy) const; + + bool isEmptyWhenPrinted(const PrintingPolicy &Policy) const; + void print(raw_ostream &OS, const PrintingPolicy &Policy, + bool appendSpaceIfNonEmpty = false) const; void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Mask); @@ -522,8 +520,6 @@ public: void setLocalFastQualifiers(unsigned Quals) { Value.setInt(Quals); } /// Retrieves a pointer to the underlying (unqualified) type. - /// This should really return a const Type, but it's not worth - /// changing all the users right now. /// /// This function requires that the type not be NULL. If the type might be /// NULL, use the (slightly less efficient) \c getTypePtrOrNull(). @@ -634,6 +630,11 @@ public: /// \brief Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10). bool isPODType(ASTContext &Context) const; + /// isCXX98PODType() - Return true if this is a POD type according to the + /// rules of the C++98 standard, regardless of the current compilation's + /// language. + bool isCXX98PODType(ASTContext &Context) const; + /// isCXX11PODType() - Return true if this is a POD type according to the /// more relaxed rules of the C++11 standard, regardless of the current /// compilation's language. @@ -824,11 +825,20 @@ public: } static std::string getAsString(const Type *ty, Qualifiers qs); - std::string getAsString(const PrintingPolicy &Policy) const { - std::string S; - getAsStringInternal(S, Policy); - return S; + std::string getAsString(const PrintingPolicy &Policy) const; + + void print(raw_ostream &OS, const PrintingPolicy &Policy, + const Twine &PlaceHolder = Twine()) const { + print(split(), OS, Policy, PlaceHolder); + } + static void print(SplitQualType split, raw_ostream &OS, + const PrintingPolicy &policy, const Twine &PlaceHolder) { + return print(split.Ty, split.Quals, OS, policy, PlaceHolder); } + static void print(const Type *ty, Qualifiers qs, + raw_ostream &OS, const PrintingPolicy &policy, + const Twine &PlaceHolder); + void getAsStringInternal(std::string &Str, const PrintingPolicy &Policy) const { return getAsStringInternal(split(), Str, Policy); @@ -841,6 +851,27 @@ public: std::string &out, const PrintingPolicy &policy); + class StreamedQualTypeHelper { + const QualType &T; + const PrintingPolicy &Policy; + const Twine &PlaceHolder; + public: + StreamedQualTypeHelper(const QualType &T, const PrintingPolicy &Policy, + const Twine &PlaceHolder) + : T(T), Policy(Policy), PlaceHolder(PlaceHolder) { } + + friend raw_ostream &operator<<(raw_ostream &OS, + const StreamedQualTypeHelper &SQT) { + SQT.T.print(OS, SQT.Policy, SQT.PlaceHolder); + return OS; + } + }; + + StreamedQualTypeHelper stream(const PrintingPolicy &Policy, + const Twine &PlaceHolder = Twine()) const { + return StreamedQualTypeHelper(*this, Policy, PlaceHolder); + } + void dump(const char *s) const; void dump() const; @@ -1107,8 +1138,6 @@ private: unsigned TC : 8; /// Dependent - Whether this type is a dependent type (C++ [temp.dep.type]). - /// Note that this should stay at the end of the ivars for Type so that - /// subclasses can pack their bitfields into the same word. unsigned Dependent : 1; /// \brief Whether this type somehow involves a template parameter, even @@ -1614,7 +1643,7 @@ public: AutoType *getContainedAutoType() const; /// Member-template getAs<specific type>'. Look through sugar for - /// an instance of <specific type>. This scheme will eventually + /// an instance of \<specific type>. This scheme will eventually /// replace the specific getAsXXXX methods above. /// /// There are some specializations of this member template listed @@ -1626,7 +1655,7 @@ public: const ArrayType *getAsArrayTypeUnsafe() const; /// Member-template castAs<specific type>. Look through sugar for - /// the underlying instance of <specific type>. + /// the underlying instance of \<specific type>. /// /// This method has the same relationship to getAs<T> as cast<T> has /// to dyn_cast<T>; which is to say, the underlying type *must* @@ -1715,9 +1744,9 @@ public: friend class ASTWriter; }; -template <> inline const TypedefType *Type::getAs() const { - return dyn_cast<TypedefType>(this); -} +/// \brief This will check for a TypedefType by removing any existing sugar +/// until it reaches a TypedefType or a non-sugared type. +template <> const TypedefType *Type::getAs() const; // We can do canonical leaf types faster, because we don't have to // worry about preserving child type decoration. @@ -1752,7 +1781,13 @@ public: } Kind getKind() const { return static_cast<Kind>(BuiltinTypeBits.Kind); } - const char *getName(const PrintingPolicy &Policy) const; + StringRef getName(const PrintingPolicy &Policy) const; + const char *getNameAsCString(const PrintingPolicy &Policy) const { + // The StringRef is null-terminated. + StringRef str = getName(Policy); + assert(!str.empty() && str.data()[str.size()] == '\0'); + return str.data(); + } bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2641,6 +2676,9 @@ public: bool getNoReturnAttr() const { return getExtInfo().getNoReturn(); } CallingConv getCallConv() const { return getExtInfo().getCC(); } ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); } + bool isConst() const { return getTypeQuals() & Qualifiers::Const; } + bool isVolatile() const { return getTypeQuals() & Qualifiers::Volatile; } + bool isRestrict() const { return getTypeQuals() & Qualifiers::Restrict; } /// \brief Determine the type of an expression that calls a function of /// this type. @@ -2808,6 +2846,8 @@ public: } else if (EPI.ExceptionSpecType == EST_Uninstantiated) { EPI.ExceptionSpecDecl = getExceptionSpecDecl(); EPI.ExceptionSpecTemplate = getExceptionSpecTemplate(); + } else if (EPI.ExceptionSpecType == EST_Unevaluated) { + EPI.ExceptionSpecDecl = getExceptionSpecDecl(); } if (hasAnyConsumedArgs()) EPI.ConsumedArguments = getConsumedArgsBuffer(); @@ -2851,11 +2891,13 @@ public: // NoexceptExpr sits where the arguments end. return *reinterpret_cast<Expr *const *>(arg_type_end()); } - /// \brief If this function type has an uninstantiated exception - /// specification, this is the function whose exception specification - /// is represented by this type. + /// \brief If this function type has an exception specification which hasn't + /// been determined yet (either because it has not been evaluated or because + /// it has not been instantiated), this is the function whose exception + /// specification is represented by this type. FunctionDecl *getExceptionSpecDecl() const { - if (getExceptionSpecType() != EST_Uninstantiated) + if (getExceptionSpecType() != EST_Uninstantiated && + getExceptionSpecType() != EST_Unevaluated) return 0; return reinterpret_cast<FunctionDecl * const *>(arg_type_end())[0]; } @@ -2870,7 +2912,7 @@ public: } bool isNothrow(ASTContext &Ctx) const { ExceptionSpecificationType EST = getExceptionSpecType(); - assert(EST != EST_Delayed && EST != EST_Uninstantiated); + assert(EST != EST_Unevaluated && EST != EST_Uninstantiated); if (EST == EST_DynamicNone || EST == EST_BasicNoexcept) return true; if (EST != EST_ComputedNoexcept) @@ -2928,8 +2970,11 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } + // FIXME: Remove the string version. void printExceptionSpecification(std::string &S, PrintingPolicy Policy) const; + void printExceptionSpecification(raw_ostream &OS, + PrintingPolicy Policy) const; static bool classof(const Type *T) { return T->getTypeClass() == FunctionProto; @@ -3582,6 +3627,7 @@ public: /// \brief Print a template argument list, including the '<' and '>' /// enclosing the template arguments. + // FIXME: remove the string ones. static std::string PrintTemplateArgumentList(const TemplateArgument *Args, unsigned NumArgs, const PrintingPolicy &Policy, @@ -3594,6 +3640,23 @@ public: static std::string PrintTemplateArgumentList(const TemplateArgumentListInfo &, const PrintingPolicy &Policy); + /// \brief Print a template argument list, including the '<' and '>' + /// enclosing the template arguments. + static void PrintTemplateArgumentList(raw_ostream &OS, + const TemplateArgument *Args, + unsigned NumArgs, + const PrintingPolicy &Policy, + bool SkipBrackets = false); + + static void PrintTemplateArgumentList(raw_ostream &OS, + const TemplateArgumentLoc *Args, + unsigned NumArgs, + const PrintingPolicy &Policy); + + static void PrintTemplateArgumentList(raw_ostream &OS, + const TemplateArgumentListInfo &, + const PrintingPolicy &Policy); + /// True if this template specialization type matches a current /// instantiation in the context in which it is found. bool isCurrentInstantiation() const { @@ -3641,7 +3704,7 @@ public: unsigned getNumArgs() const { return NumArgs; } /// \brief Retrieve a specific template argument as a type. - /// \precondition @c isArgType(Arg) + /// \pre @c isArgType(Arg) const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h bool isSugared() const { @@ -4045,7 +4108,7 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode { PackExpansionType(QualType Pattern, QualType Canon, llvm::Optional<unsigned> NumExpansions) - : Type(PackExpansion, Canon, /*Dependent=*/true, + : Type(PackExpansion, Canon, /*Dependent=*/Pattern->isDependentType(), /*InstantiationDependent=*/true, /*VariableModified=*/Pattern->isVariablyModifiedType(), /*ContainsUnexpandedParameterPack=*/false), @@ -4097,8 +4160,10 @@ public: /// list of protocols. /// /// Given the following declarations: -/// @class C; -/// @protocol P; +/// \code +/// \@class C; +/// \@protocol P; +/// \endcode /// /// 'C' is an ObjCInterfaceType C. It is sugar for an ObjCObjectType /// with base C and no protocols. @@ -4312,11 +4377,13 @@ public: /// This method is equivalent to getPointeeType() except that /// it discards any typedefs (or other sugar) between this /// type and the "outermost" object type. So for: - /// @class A; @protocol P; @protocol Q; + /// \code + /// \@class A; \@protocol P; \@protocol Q; /// typedef A<P> AP; /// typedef A A1; /// typedef A1<P> A1P; /// typedef A1P<Q> A1PQ; + /// \endcode /// For 'A*', getObjectType() will return 'A'. /// For 'A<P>*', getObjectType() will return 'A<P>'. /// For 'AP*', getObjectType() will return 'A<P>'. @@ -4333,7 +4400,7 @@ public: } /// getInterfaceType - If this pointer points to an Objective C - /// @interface type, gets the type for that interface. Any protocol + /// \@interface type, gets the type for that interface. Any protocol /// qualifiers on the interface are ignored. /// /// \return null if the base type for this pointer is 'id' or 'Class' @@ -4341,7 +4408,7 @@ public: return getObjectType()->getBaseType()->getAs<ObjCInterfaceType>(); } - /// getInterfaceDecl - If this pointer points to an Objective @interface + /// getInterfaceDecl - If this pointer points to an Objective \@interface /// type, gets the declaration for that interface. /// /// \return null if the base type for this pointer is 'id' or 'Class' @@ -4970,7 +5037,7 @@ struct ArrayType_cannot_be_used_with_getAs { }; template<typename T> struct ArrayType_cannot_be_used_with_getAs<T, true>; -/// Member-template getAs<specific type>'. +// Member-template getAs<specific type>'. template <typename T> const T *Type::getAs() const { ArrayType_cannot_be_used_with_getAs<T> at; (void)at; diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index aab87be..1d1c1d1 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -831,6 +831,7 @@ public: struct ObjCInterfaceLocInfo { SourceLocation NameLoc; + SourceLocation NameEndLoc; }; /// \brief Wrapper for source info for ObjC interfaces. @@ -850,9 +851,17 @@ public: void setNameLoc(SourceLocation Loc) { getLocalData()->NameLoc = Loc; } - + SourceRange getLocalSourceRange() const { - return SourceRange(getNameLoc()); + return SourceRange(getNameLoc(), getNameEndLoc()); + } + + SourceLocation getNameEndLoc() const { + return getLocalData()->NameEndLoc; + } + + void setNameEndLoc(SourceLocation Loc) { + getLocalData()->NameEndLoc = Loc; } void initializeLocal(ASTContext &Context, SourceLocation Loc) { |