diff options
Diffstat (limited to 'include/clang')
216 files changed, 15799 insertions, 5775 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) { diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h new file mode 100644 index 0000000..dd237ee --- /dev/null +++ b/include/clang/ASTMatchers/ASTMatchFinder.h @@ -0,0 +1,141 @@ +//===--- ASTMatchFinder.h - Structural query framework ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Provides a way to construct an ASTConsumer that runs given matchers +// over the AST and invokes a given callback on every match. +// +// The general idea is to construct a matcher expression that describes a +// subtree match on the AST. Next, a callback that is executed every time the +// expression matches is registered, and the matcher is run over the AST of +// some code. Matched subexpressions can be bound to string IDs and easily +// be accessed from the registered callback. The callback can than use the +// AST nodes that the subexpressions matched on to output information about +// the match or construct changes that can be applied to the code. +// +// Example: +// class HandleMatch : public MatchFinder::MatchCallback { +// public: +// virtual void Run(const MatchFinder::MatchResult &Result) { +// const CXXRecordDecl *Class = +// Result.Nodes.GetDeclAs<CXXRecordDecl>("id"); +// ... +// } +// }; +// +// int main(int argc, char **argv) { +// ClangTool Tool(argc, argv); +// MatchFinder finder; +// finder.AddMatcher(Id("id", record(hasName("::a_namespace::AClass"))), +// new HandleMatch); +// return Tool.Run(newFrontendActionFactory(&finder)); +// } +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H +#define LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H + +#include "clang/ASTMatchers/ASTMatchers.h" + +namespace clang { + +namespace ast_matchers { + +/// \brief A class to allow finding matches over the Clang AST. +/// +/// After creation, you can add multiple matchers to the MatchFinder via +/// calls to addMatcher(...). +/// +/// Once all matchers are added, newASTConsumer() returns an ASTConsumer +/// that will trigger the callbacks specified via addMatcher(...) when a match +/// is found. +/// +/// See ASTMatchers.h for more information about how to create matchers. +/// +/// Not intended to be subclassed. +class MatchFinder { +public: + /// \brief Contains all information for a given match. + /// + /// Every time a match is found, the MatchFinder will invoke the registered + /// MatchCallback with a MatchResult containing information about the match. + struct MatchResult { + MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context); + + /// \brief Contains the nodes bound on the current match. + /// + /// This allows user code to easily extract matched AST nodes. + const BoundNodes Nodes; + + /// \brief Utilities for interpreting the matched AST structures. + /// @{ + clang::ASTContext * const Context; + clang::SourceManager * const SourceManager; + /// @} + }; + + /// \brief Called when the Match registered for it was successfully found + /// in the AST. + class MatchCallback { + public: + virtual ~MatchCallback(); + virtual void run(const MatchResult &Result) = 0; + }; + + /// \brief Called when parsing is finished. Intended for testing only. + class ParsingDoneTestCallback { + public: + virtual ~ParsingDoneTestCallback(); + virtual void run() = 0; + }; + + MatchFinder(); + ~MatchFinder(); + + /// \brief Adds a matcher to execute when running over the AST. + /// + /// Calls 'Action' with the BoundNodes on every match. + /// Adding more than one 'NodeMatch' allows finding different matches in a + /// single pass over the AST. + /// + /// Does not take ownership of 'Action'. + /// @{ + void addMatcher(const DeclarationMatcher &NodeMatch, + MatchCallback *Action); + void addMatcher(const TypeMatcher &NodeMatch, + MatchCallback *Action); + void addMatcher(const StatementMatcher &NodeMatch, + MatchCallback *Action); + /// @} + + /// \brief Creates a clang ASTConsumer that finds all matches. + clang::ASTConsumer *newASTConsumer(); + + /// \brief Registers a callback to notify the end of parsing. + /// + /// The provided closure is called after parsing is done, before the AST is + /// traversed. Useful for benchmarking. + /// Each call to FindAll(...) will call the closure once. + void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone); + +private: + /// \brief The MatchCallback*'s will be called every time the + /// UntypedBaseMatcher matches on the AST. + std::vector< std::pair< + const internal::UntypedBaseMatcher*, + MatchCallback*> > Triggers; + + /// \brief Called when parsing is done. + ParsingDoneTestCallback *ParsingDone; +}; + +} // end namespace ast_matchers +} // end namespace clang + +#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h new file mode 100644 index 0000000..37e82e8 --- /dev/null +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -0,0 +1,1799 @@ +//===--- ASTMatchers.h - Structural query framework -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements matchers to be used together with the MatchFinder to +// match AST nodes. +// +// Matchers are created by generator functions, which can be combined in +// a functional in-language DSL to express queries over the C++ AST. +// +// For example, to match a class with a certain name, one would call: +// record(hasName("MyClass")) +// which returns a matcher that can be used to find all AST nodes that declare +// a class named 'MyClass'. +// +// For more complicated match expressions we're often interested in accessing +// multiple parts of the matched AST nodes once a match is found. In that case, +// use the id(...) matcher around the match expressions that match the nodes +// you want to access. +// +// For example, when we're interested in child classes of a certain class, we +// would write: +// record(hasName("MyClass"), hasChild(id("child", record()))) +// When the match is found via the MatchFinder, a user provided callback will +// be called with a BoundNodes instance that contains a mapping from the +// strings that we provided for the id(...) calls to the nodes that were +// matched. +// In the given example, each time our matcher finds a match we get a callback +// where "child" is bound to the CXXRecordDecl node of the matching child +// class declaration. +// +// See ASTMatchersInternal.h for a more in-depth explanation of the +// implementation details of the matcher framework. +// +// See ASTMatchFinder.h for how to use the generated matchers to run over +// an AST. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H +#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H + +#include "clang/AST/DeclTemplate.h" +#include "clang/ASTMatchers/ASTMatchersInternal.h" +#include "clang/ASTMatchers/ASTMatchersMacros.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Regex.h" + +namespace clang { +namespace ast_matchers { + +/// \brief Maps string IDs to AST nodes matched by parts of a matcher. +/// +/// The bound nodes are generated by adding id(...) matchers into the +/// match expression around the matchers for the nodes we want to access later. +/// +/// The instances of BoundNodes are created by MatchFinder when the user's +/// callbacks are executed every time a match is found. +class BoundNodes { +public: + /// \brief Returns the AST node bound to 'ID'. + /// Returns NULL if there was no node bound to 'ID' or if there is a node but + /// it cannot be converted to the specified type. + /// FIXME: We'll need one of those for every base type. + /// @{ + template <typename T> + const T *getDeclAs(StringRef ID) const { + return getNodeAs<T>(DeclBindings, ID); + } + template <typename T> + const T *getStmtAs(StringRef ID) const { + return getNodeAs<T>(StmtBindings, ID); + } + /// @} + +private: + /// \brief Create BoundNodes from a pre-filled map of bindings. + BoundNodes(const std::map<std::string, const Decl*> &DeclBindings, + const std::map<std::string, const Stmt*> &StmtBindings) + : DeclBindings(DeclBindings), StmtBindings(StmtBindings) {} + + template <typename T, typename MapT> + const T *getNodeAs(const MapT &Bindings, StringRef ID) const { + typename MapT::const_iterator It = Bindings.find(ID); + if (It == Bindings.end()) { + return NULL; + } + return llvm::dyn_cast<T>(It->second); + } + + std::map<std::string, const Decl*> DeclBindings; + std::map<std::string, const Stmt*> StmtBindings; + + friend class internal::BoundNodesTree; +}; + +/// \brief If the provided matcher matches a node, binds the node to 'ID'. +/// +/// FIXME: Add example for accessing it. +template <typename T> +internal::Matcher<T> id(const std::string &ID, + const internal::BindableMatcher<T> &InnerMatcher) { + return InnerMatcher.bind(ID); +} + +/// \brief Types of matchers for the top-level classes in the AST class +/// hierarchy. +/// @{ +typedef internal::Matcher<Decl> DeclarationMatcher; +typedef internal::Matcher<QualType> TypeMatcher; +typedef internal::Matcher<Stmt> StatementMatcher; +/// @} + +/// \brief Matches any node. +/// +/// Useful when another matcher requires a child matcher, but there's no +/// additional constraint. This will often be used with an explicit conversion +/// to a internal::Matcher<> type such as TypeMatcher. +/// +/// Example: DeclarationMatcher(anything()) matches all declarations, e.g., +/// "int* p" and "void f()" in +/// int* p; +/// void f(); +inline internal::PolymorphicMatcherWithParam0<internal::TrueMatcher> anything() { + return internal::PolymorphicMatcherWithParam0<internal::TrueMatcher>(); +} + +/// \brief Matches declarations. +/// +/// Examples matches \c X, \c C, and the friend declaration inside \c C; +/// \code +/// void X(); +/// class C { +/// friend X; +/// }; +/// \endcode +const internal::VariadicDynCastAllOfMatcher<Decl, Decl> decl; + +/// \brief Matches a declaration of anything that could have a name. +/// +/// Example matches X, S, the anonymous union type, i, and U; +/// typedef int X; +/// struct S { +/// union { +/// int i; +/// } U; +/// }; +const internal::VariadicDynCastAllOfMatcher< + Decl, + NamedDecl> nameableDeclaration; + +/// \brief Matches C++ class declarations. +/// +/// Example matches X, Z +/// class X; +/// template<class T> class Z {}; +const internal::VariadicDynCastAllOfMatcher< + Decl, + CXXRecordDecl> record; + +/// \brief Matches C++ class template specializations. +/// +/// Given +/// template<typename T> class A {}; +/// template<> class A<double> {}; +/// A<int> a; +/// classTemplateSpecialization() +/// matches the specializations \c A<int> and \c A<double> +const internal::VariadicDynCastAllOfMatcher< + Decl, + ClassTemplateSpecializationDecl> classTemplateSpecialization; + +/// \brief Matches classTemplateSpecializations that have at least one +/// TemplateArgument matching the given Matcher. +/// +/// Given +/// template<typename T> class A {}; +/// template<> class A<double> {}; +/// A<int> a; +/// classTemplateSpecialization(hasAnyTemplateArgument( +/// refersToType(asString("int")))) +/// matches the specialization \c A<int> +AST_MATCHER_P(ClassTemplateSpecializationDecl, hasAnyTemplateArgument, + internal::Matcher<TemplateArgument>, Matcher) { + const TemplateArgumentList &List = Node.getTemplateArgs(); + for (unsigned i = 0; i < List.size(); ++i) { + if (Matcher.matches(List.get(i), Finder, Builder)) + return true; + } + return false; +} + +/// \brief Matches classTemplateSpecializations where the n'th TemplateArgument +/// matches the given Matcher. +/// +/// Given +/// template<typename T, typename U> class A {}; +/// A<bool, int> b; +/// A<int, bool> c; +/// classTemplateSpecialization(hasTemplateArgument( +/// 1, refersToType(asString("int")))) +/// matches the specialization \c A<bool, int> +AST_MATCHER_P2(ClassTemplateSpecializationDecl, hasTemplateArgument, + unsigned, N, internal::Matcher<TemplateArgument>, Matcher) { + const TemplateArgumentList &List = Node.getTemplateArgs(); + if (List.size() <= N) + return false; + return Matcher.matches(List.get(N), Finder, Builder); +} + +/// \brief Matches a TemplateArgument that refers to a certain type. +/// +/// Given +/// struct X {}; +/// template<typename T> struct A {}; +/// A<X> a; +/// classTemplateSpecialization(hasAnyTemplateArgument( +/// refersToType(class(hasName("X"))))) +/// matches the specialization \c A<X> +AST_MATCHER_P(TemplateArgument, refersToType, + internal::Matcher<QualType>, Matcher) { + if (Node.getKind() != TemplateArgument::Type) + return false; + return Matcher.matches(Node.getAsType(), Finder, Builder); +} + +/// \brief Matches a TemplateArgument that refers to a certain declaration. +/// +/// Given +/// template<typename T> struct A {}; +/// struct B { B* next; }; +/// A<&B::next> a; +/// classTemplateSpecialization(hasAnyTemplateArgument( +/// refersToDeclaration(field(hasName("next")))) +/// matches the specialization \c A<&B::next> with \c field(...) matching +/// \c B::next +AST_MATCHER_P(TemplateArgument, refersToDeclaration, + internal::Matcher<Decl>, Matcher) { + if (const Decl *Declaration = Node.getAsDecl()) + return Matcher.matches(*Declaration, Finder, Builder); + return false; +} + +/// \brief Matches C++ constructor declarations. +/// +/// Example matches Foo::Foo() and Foo::Foo(int) +/// class Foo { +/// public: +/// Foo(); +/// Foo(int); +/// int DoSomething(); +/// }; +const internal::VariadicDynCastAllOfMatcher< + Decl, + CXXConstructorDecl> constructor; + +/// \brief Matches explicit C++ destructor declarations. +/// +/// Example matches Foo::~Foo() +/// class Foo { +/// public: +/// virtual ~Foo(); +/// }; +const internal::VariadicDynCastAllOfMatcher<Decl, CXXDestructorDecl> destructor; + +/// \brief Matches enum declarations. +/// +/// Example matches X +/// enum X { +/// A, B, C +/// }; +const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl; + +/// \brief Matches enum constants. +/// +/// Example matches A, B, C +/// enum X { +/// A, B, C +/// }; +const internal::VariadicDynCastAllOfMatcher< + Decl, + EnumConstantDecl> enumConstant; + +/// \brief Matches method declarations. +/// +/// Example matches y +/// class X { void y() }; +const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> method; + +/// \brief Matches variable declarations. +/// +/// Note: this does not match declarations of member variables, which are +/// "field" declarations in Clang parlance. +/// +/// Example matches a +/// int a; +const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> variable; + +/// \brief Matches field declarations. +/// +/// Given +/// class X { int m; }; +/// field() +/// matches 'm'. +const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> field; + +/// \brief Matches function declarations. +/// +/// Example matches f +/// void f(); +const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> function; + + +/// \brief Matches statements. +/// +/// Given +/// { ++a; } +/// statement() +/// matches both the compound statement '{ ++a; }' and '++a'. +const internal::VariadicDynCastAllOfMatcher<Stmt, Stmt> statement; + +/// \brief Matches declaration statements. +/// +/// Given +/// int a; +/// declarationStatement() +/// matches 'int a'. +const internal::VariadicDynCastAllOfMatcher< + Stmt, + DeclStmt> declarationStatement; + +/// \brief Matches member expressions. +/// +/// Given +/// class Y { +/// void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; } +/// int a; static int b; +/// }; +/// memberExpression() +/// matches this->x, x, y.x, a, this->b +const internal::VariadicDynCastAllOfMatcher< + Stmt, + MemberExpr> memberExpression; + +/// \brief Matches call expressions. +/// +/// Example matches x.y() and y() +/// X x; +/// x.y(); +/// y(); +const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> call; + +/// \brief Matches member call expressions. +/// +/// Example matches x.y() +/// X x; +/// x.y(); +const internal::VariadicDynCastAllOfMatcher<Stmt, CXXMemberCallExpr> memberCall; + +/// \brief Matches init list expressions. +/// +/// Given +/// int a[] = { 1, 2 }; +/// struct B { int x, y; }; +/// B b = { 5, 6 }; +/// initList() +/// matches "{ 1, 2 }" and "{ 5, 6 }" +const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr; + +/// \brief Matches using declarations. +/// +/// Given +/// namespace X { int x; } +/// using X::x; +/// usingDecl() +/// matches \code using X::x \endcode +const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl; + +/// \brief Matches constructor call expressions (including implicit ones). +/// +/// Example matches string(ptr, n) and ptr within arguments of f +/// (matcher = constructorCall()) +/// void f(const string &a, const string &b); +/// char *ptr; +/// int n; +/// f(string(ptr, n), ptr); +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CXXConstructExpr> constructorCall; + +/// \brief Matches nodes where temporaries are created. +/// +/// Example matches FunctionTakesString(GetStringByValue()) +/// (matcher = bindTemporaryExpression()) +/// FunctionTakesString(GetStringByValue()); +/// FunctionTakesStringByPointer(GetStringPointer()); +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CXXBindTemporaryExpr> bindTemporaryExpression; + +/// \brief Matches new expressions. +/// +/// Given +/// new X; +/// newExpression() +/// matches 'new X'. +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CXXNewExpr> newExpression; + +/// \brief Matches delete expressions. +/// +/// Given +/// delete X; +/// deleteExpression() +/// matches 'delete X'. +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CXXDeleteExpr> deleteExpression; + +/// \brief Matches array subscript expressions. +/// +/// Given +/// int i = a[1]; +/// arraySubscriptExpr() +/// matches "a[1]" +const internal::VariadicDynCastAllOfMatcher< + Stmt, + ArraySubscriptExpr> arraySubscriptExpr; + +/// \brief Matches the value of a default argument at the call site. +/// +/// Example matches the CXXDefaultArgExpr placeholder inserted for the +/// default value of the second parameter in the call expression f(42) +/// (matcher = defaultArgument()) +/// void f(int x, int y = 0); +/// f(42); +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CXXDefaultArgExpr> defaultArgument; + +/// \brief Matches overloaded operator calls. +/// +/// Note that if an operator isn't overloaded, it won't match. Instead, use +/// binaryOperator matcher. +/// Currently it does not match operators such as new delete. +/// FIXME: figure out why these do not match? +/// +/// Example matches both operator<<((o << b), c) and operator<<(o, b) +/// (matcher = overloadedOperatorCall()) +/// ostream &operator<< (ostream &out, int i) { }; +/// ostream &o; int b = 1, c = 1; +/// o << b << c; +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CXXOperatorCallExpr> overloadedOperatorCall; + +/// \brief Matches expressions. +/// +/// Example matches x() +/// void f() { x(); } +const internal::VariadicDynCastAllOfMatcher< + Stmt, + Expr> expression; + +/// \brief Matches expressions that refer to declarations. +/// +/// Example matches x in if (x) +/// bool x; +/// if (x) {} +const internal::VariadicDynCastAllOfMatcher< + Stmt, + DeclRefExpr> declarationReference; + +/// \brief Matches if statements. +/// +/// Example matches 'if (x) {}' +/// if (x) {} +const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt; + +/// \brief Matches for statements. +/// +/// Example matches 'for (;;) {}' +/// for (;;) {} +const internal::VariadicDynCastAllOfMatcher< + Stmt, ForStmt> forStmt; + +/// \brief Matches the increment statement of a for loop. +/// +/// Example: +/// forStmt(hasIncrement(unaryOperator(hasOperatorName("++")))) +/// matches '++x' in +/// for (x; x < N; ++x) { } +AST_MATCHER_P(ForStmt, hasIncrement, internal::Matcher<Stmt>, + InnerMatcher) { + const Stmt *const Increment = Node.getInc(); + return (Increment != NULL && + InnerMatcher.matches(*Increment, Finder, Builder)); +} + +/// \brief Matches the initialization statement of a for loop. +/// +/// Example: +/// forStmt(hasLoopInit(declarationStatement())) +/// matches 'int x = 0' in +/// for (int x = 0; x < N; ++x) { } +AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher<Stmt>, + InnerMatcher) { + const Stmt *const Init = Node.getInit(); + return (Init != NULL && InnerMatcher.matches(*Init, Finder, Builder)); +} + +/// \brief Matches while statements. +/// +/// Given +/// while (true) {} +/// whileStmt() +/// matches 'while (true) {}'. +const internal::VariadicDynCastAllOfMatcher< + Stmt, + WhileStmt> whileStmt; + +/// \brief Matches do statements. +/// +/// Given +/// do {} while (true); +/// doStmt() +/// matches 'do {} while(true)' +const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt; + +/// \brief Matches case and default statements inside switch statements. +/// +/// Given +/// switch(a) { case 42: break; default: break; } +/// switchCase() +/// matches 'case 42: break;' and 'default: break;'. +const internal::VariadicDynCastAllOfMatcher< + Stmt, + SwitchCase> switchCase; + +/// \brief Matches compound statements. +/// +/// Example matches '{}' and '{{}}'in 'for (;;) {{}}' +/// for (;;) {{}} +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CompoundStmt> compoundStatement; + +/// \brief Matches bool literals. +/// +/// Example matches true +/// true +const internal::VariadicDynCastAllOfMatcher< + Expr, + CXXBoolLiteralExpr> boolLiteral; + +/// \brief Matches string literals (also matches wide string literals). +/// +/// Example matches "abcd", L"abcd" +/// char *s = "abcd"; wchar_t *ws = L"abcd" +const internal::VariadicDynCastAllOfMatcher< + Expr, + StringLiteral> stringLiteral; + +/// \brief Matches character literals (also matches wchar_t). +/// +/// Not matching Hex-encoded chars (e.g. 0x1234, which is a IntegerLiteral), +/// though. +/// +/// Example matches 'a', L'a' +/// char ch = 'a'; wchar_t chw = L'a'; +const internal::VariadicDynCastAllOfMatcher< + Expr, + CharacterLiteral> characterLiteral; + +/// \brief Matches integer literals of all sizes / encodings. +/// +/// Not matching character-encoded integers such as L'a'. +/// +/// Example matches 1, 1L, 0x1, 1U +const internal::VariadicDynCastAllOfMatcher< + Expr, + IntegerLiteral> integerLiteral; + +/// \brief Matches binary operator expressions. +/// +/// Example matches a || b +/// !(a || b) +const internal::VariadicDynCastAllOfMatcher< + Stmt, + BinaryOperator> binaryOperator; + +/// \brief Matches unary operator expressions. +/// +/// Example matches !a +/// !a || b +const internal::VariadicDynCastAllOfMatcher< + Stmt, + UnaryOperator> unaryOperator; + +/// \brief Matches conditional operator expressions. +/// +/// Example matches a ? b : c +/// (a ? b : c) + 42 +const internal::VariadicDynCastAllOfMatcher< + Stmt, + ConditionalOperator> conditionalOperator; + +/// \brief Matches a reinterpret_cast expression. +/// +/// Either the source expression or the destination type can be matched +/// using has(), but hasDestinationType() is more specific and can be +/// more readable. +/// +/// Example matches reinterpret_cast<char*>(&p) in +/// void* p = reinterpret_cast<char*>(&p); +const internal::VariadicDynCastAllOfMatcher< + Expr, + CXXReinterpretCastExpr> reinterpretCast; + +/// \brief Matches a C++ static_cast expression. +/// +/// \see hasDestinationType +/// \see reinterpretCast +/// +/// Example: +/// staticCast() +/// matches +/// static_cast<long>(8) +/// in +/// long eight(static_cast<long>(8)); +const internal::VariadicDynCastAllOfMatcher< + Expr, + CXXStaticCastExpr> staticCast; + +/// \brief Matches a dynamic_cast expression. +/// +/// Example: +/// dynamicCast() +/// matches +/// dynamic_cast<D*>(&b); +/// in +/// struct B { virtual ~B() {} }; struct D : B {}; +/// B b; +/// D* p = dynamic_cast<D*>(&b); +const internal::VariadicDynCastAllOfMatcher< + Expr, + CXXDynamicCastExpr> dynamicCast; + +/// \brief Matches a const_cast expression. +/// +/// Example: Matches const_cast<int*>(&r) in +/// int n = 42; +/// const int& r(n); +/// int* p = const_cast<int*>(&r); +const internal::VariadicDynCastAllOfMatcher< + Expr, + CXXConstCastExpr> constCast; + +/// \brief Matches explicit cast expressions. +/// +/// Matches any cast expression written in user code, whether it be a +/// C-style cast, a functional-style cast, or a keyword cast. +/// +/// Does not match implicit conversions. +/// +/// Note: the name "explicitCast" is chosen to match Clang's terminology, as +/// Clang uses the term "cast" to apply to implicit conversions as well as to +/// actual cast expressions. +/// +/// \see hasDestinationType. +/// +/// Example: matches all five of the casts in +/// int((int)(reinterpret_cast<int>(static_cast<int>(const_cast<int>(42))))) +/// but does not match the implicit conversion in +/// long ell = 42; +const internal::VariadicDynCastAllOfMatcher< + Expr, + ExplicitCastExpr> explicitCast; + +/// \brief Matches the implicit cast nodes of Clang's AST. +/// +/// This matches many different places, including function call return value +/// eliding, as well as any type conversions. +const internal::VariadicDynCastAllOfMatcher< + Expr, + ImplicitCastExpr> implicitCast; + +/// \brief Matches functional cast expressions +/// +/// Example: Matches Foo(bar); +/// Foo f = bar; +/// Foo g = (Foo) bar; +/// Foo h = Foo(bar); +const internal::VariadicDynCastAllOfMatcher< + Expr, + CXXFunctionalCastExpr> functionalCast; + +/// \brief Various overloads for the anyOf matcher. +/// @{ +template<typename C1, typename C2> +internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C1, C2> +anyOf(const C1 &P1, const C2 &P2) { + return internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, + C1, C2 >(P1, P2); +} +template<typename C1, typename C2, typename C3> +internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C1, + internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C2, C3> > +anyOf(const C1 &P1, const C2 &P2, const C3 &P3) { + return anyOf(P1, anyOf(P2, P3)); +} +template<typename C1, typename C2, typename C3, typename C4> +internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C1, + internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C2, + internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, + C3, C4> > > +anyOf(const C1 &P1, const C2 &P2, const C3 &P3, const C4 &P4) { + return anyOf(P1, anyOf(P2, anyOf(P3, P4))); +} +template<typename C1, typename C2, typename C3, typename C4, typename C5> +internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C1, + internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C2, + internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, C3, + internal::PolymorphicMatcherWithParam2<internal::AnyOfMatcher, + C4, C5> > > > +anyOf(const C1& P1, const C2& P2, const C3& P3, const C4& P4, const C5& P5) { + return anyOf(P1, anyOf(P2, anyOf(P3, anyOf(P4, P5)))); +} +/// @} + +/// \brief Various overloads for the allOf matcher. +/// @{ +template<typename C1, typename C2> +internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, C1, C2> +allOf(const C1 &P1, const C2 &P2) { + return internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, + C1, C2>(P1, P2); +} +template<typename C1, typename C2, typename C3> +internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, C1, + internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, C2, C3> > +allOf(const C1& P1, const C2& P2, const C3& P3) { + return allOf(P1, allOf(P2, P3)); +} +/// @} + +/// \brief Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL) +/// +/// Given +/// Foo x = bar; +/// int y = sizeof(x) + alignof(x); +/// unaryExprOrTypeTraitExpr() +/// matches \c sizeof(x) and \c alignof(x) +const internal::VariadicDynCastAllOfMatcher< + Stmt, + UnaryExprOrTypeTraitExpr> unaryExprOrTypeTraitExpr; + +/// \brief Matches unary expressions that have a specific type of argument. +/// +/// Given +/// int a, c; float b; int s = sizeof(a) + sizeof(b) + alignof(c); +/// unaryExprOrTypeTraitExpr(hasArgumentOfType(asString("int")) +/// matches \c sizeof(a) and \c alignof(c) +AST_MATCHER_P(UnaryExprOrTypeTraitExpr, hasArgumentOfType, + internal::Matcher<QualType>, Matcher) { + const QualType ArgumentType = Node.getTypeOfArgument(); + return Matcher.matches(ArgumentType, Finder, Builder); +} + +/// \brief Matches unary expressions of a certain kind. +/// +/// Given +/// int x; +/// int s = sizeof(x) + alignof(x) +/// unaryExprOrTypeTraitExpr(ofKind(UETT_SizeOf)) +/// matches \c sizeof(x) +AST_MATCHER_P(UnaryExprOrTypeTraitExpr, ofKind, UnaryExprOrTypeTrait, Kind) { + return Node.getKind() == Kind; +} + +/// \brief Same as unaryExprOrTypeTraitExpr, but only matching +/// alignof. +inline internal::Matcher<Stmt> alignOfExpr( + const internal::Matcher<UnaryExprOrTypeTraitExpr> &Matcher) { + return internal::Matcher<Stmt>(unaryExprOrTypeTraitExpr(allOf( + ofKind(UETT_AlignOf), Matcher))); +} + +/// \brief Same as unaryExprOrTypeTraitExpr, but only matching +/// sizeof. +inline internal::Matcher<Stmt> sizeOfExpr( + const internal::Matcher<UnaryExprOrTypeTraitExpr> &Matcher) { + return internal::Matcher<Stmt>(unaryExprOrTypeTraitExpr(allOf( + ofKind(UETT_SizeOf), Matcher))); +} + +/// \brief Matches NamedDecl nodes that have the specified name. +/// +/// Supports specifying enclosing namespaces or classes by prefixing the name +/// with '<enclosing>::'. +/// Does not match typedefs of an underlying type with the given name. +/// +/// Example matches X (Name == "X") +/// class X; +/// +/// Example matches X (Name is one of "::a::b::X", "a::b::X", "b::X", "X") +/// namespace a { namespace b { class X; } } +AST_MATCHER_P(NamedDecl, hasName, std::string, Name) { + assert(!Name.empty()); + const std::string FullNameString = "::" + Node.getQualifiedNameAsString(); + const llvm::StringRef FullName = FullNameString; + const llvm::StringRef Pattern = Name; + if (Pattern.startswith("::")) { + return FullName == Pattern; + } else { + return FullName.endswith(("::" + Pattern).str()); + } +} + +/// \brief Matches NamedDecl nodes whose full names partially match the +/// given RegExp. +/// +/// Supports specifying enclosing namespaces or classes by +/// prefixing the name with '<enclosing>::'. Does not match typedefs +/// of an underlying type with the given name. +/// +/// Example matches X (regexp == "::X") +/// class X; +/// +/// Example matches X (regexp is one of "::X", "^foo::.*X", among others) +/// namespace foo { namespace bar { class X; } } +AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) { + assert(!RegExp.empty()); + std::string FullNameString = "::" + Node.getQualifiedNameAsString(); + llvm::Regex RE(RegExp); + return RE.match(FullNameString); +} + +/// \brief Matches overloaded operator names. +/// +/// Matches overloaded operator names specified in strings without the +/// "operator" prefix, such as "<<", for OverloadedOperatorCall's. +/// +/// Example matches a << b +/// (matcher == overloadedOperatorCall(hasOverloadedOperatorName("<<"))) +/// a << b; +/// c && d; // assuming both operator<< +/// // and operator&& are overloaded somewhere. +AST_MATCHER_P(CXXOperatorCallExpr, + hasOverloadedOperatorName, std::string, Name) { + return getOperatorSpelling(Node.getOperator()) == Name; +} + +/// \brief Matches C++ classes that are directly or indirectly derived from +/// a class matching \c Base. +/// +/// Note that a class is considered to be also derived from itself. +/// +/// Example matches X, Y, Z, C (Base == hasName("X")) +/// class X; // A class is considered to be derived from itself +/// class Y : public X {}; // directly derived +/// class Z : public Y {}; // indirectly derived +/// typedef X A; +/// typedef A B; +/// class C : public B {}; // derived from a typedef of X +/// +/// In the following example, Bar matches isDerivedFrom(hasName("X")): +/// class Foo; +/// typedef Foo X; +/// class Bar : public Foo {}; // derived from a type that X is a typedef of +AST_MATCHER_P(CXXRecordDecl, isDerivedFrom, + internal::Matcher<NamedDecl>, Base) { + return Finder->classIsDerivedFrom(&Node, Base, Builder); +} + +/// \brief Overloaded method as shortcut for \c isDerivedFrom(hasName(...)). +inline internal::Matcher<CXXRecordDecl> isDerivedFrom(StringRef BaseName) { + assert(!BaseName.empty()); + return isDerivedFrom(hasName(BaseName)); +} + +/// \brief Matches AST nodes that have child AST nodes that match the +/// provided matcher. +/// +/// Example matches X, Y (matcher = record(has(record(hasName("X"))) +/// class X {}; // Matches X, because X::X is a class of name X inside X. +/// class Y { class X {}; }; +/// class Z { class Y { class X {}; }; }; // Does not match Z. +/// +/// ChildT must be an AST base type. +template <typename ChildT> +internal::ArgumentAdaptingMatcher<internal::HasMatcher, ChildT> has( + const internal::Matcher<ChildT> &ChildMatcher) { + return internal::ArgumentAdaptingMatcher<internal::HasMatcher, + ChildT>(ChildMatcher); +} + +/// \brief Matches AST nodes that have descendant AST nodes that match the +/// provided matcher. +/// +/// Example matches X, Y, Z +/// (matcher = record(hasDescendant(record(hasName("X"))))) +/// class X {}; // Matches X, because X::X is a class of name X inside X. +/// class Y { class X {}; }; +/// class Z { class Y { class X {}; }; }; +/// +/// DescendantT must be an AST base type. +template <typename DescendantT> +internal::ArgumentAdaptingMatcher<internal::HasDescendantMatcher, DescendantT> +hasDescendant(const internal::Matcher<DescendantT> &DescendantMatcher) { + return internal::ArgumentAdaptingMatcher< + internal::HasDescendantMatcher, + DescendantT>(DescendantMatcher); +} + + +/// \brief Matches AST nodes that have child AST nodes that match the +/// provided matcher. +/// +/// Example matches X, Y (matcher = record(forEach(record(hasName("X"))) +/// class X {}; // Matches X, because X::X is a class of name X inside X. +/// class Y { class X {}; }; +/// class Z { class Y { class X {}; }; }; // Does not match Z. +/// +/// ChildT must be an AST base type. +/// +/// As opposed to 'has', 'forEach' will cause a match for each result that +/// matches instead of only on the first one. +template <typename ChildT> +internal::ArgumentAdaptingMatcher<internal::ForEachMatcher, ChildT> forEach( + const internal::Matcher<ChildT>& ChildMatcher) { + return internal::ArgumentAdaptingMatcher< + internal::ForEachMatcher, + ChildT>(ChildMatcher); +} + +/// \brief Matches AST nodes that have descendant AST nodes that match the +/// provided matcher. +/// +/// Example matches X, A, B, C +/// (matcher = record(forEachDescendant(record(hasName("X"))))) +/// class X {}; // Matches X, because X::X is a class of name X inside X. +/// class A { class X {}; }; +/// class B { class C { class X {}; }; }; +/// +/// DescendantT must be an AST base type. +/// +/// As opposed to 'hasDescendant', 'forEachDescendant' will cause a match for +/// each result that matches instead of only on the first one. +/// +/// Note: Recursively combined ForEachDescendant can cause many matches: +/// record(forEachDescendant(record(forEachDescendant(record())))) +/// will match 10 times (plus injected class name matches) on: +/// class A { class B { class C { class D { class E {}; }; }; }; }; +template <typename DescendantT> +internal::ArgumentAdaptingMatcher<internal::ForEachDescendantMatcher, DescendantT> +forEachDescendant( + const internal::Matcher<DescendantT>& DescendantMatcher) { + return internal::ArgumentAdaptingMatcher< + internal::ForEachDescendantMatcher, + DescendantT>(DescendantMatcher); +} + +/// \brief Matches if the provided matcher does not match. +/// +/// Example matches Y (matcher = record(unless(hasName("X")))) +/// class X {}; +/// class Y {}; +template <typename M> +internal::PolymorphicMatcherWithParam1<internal::NotMatcher, M> unless(const M &InnerMatcher) { + return internal::PolymorphicMatcherWithParam1< + internal::NotMatcher, M>(InnerMatcher); +} + +/// \brief Matches a type if the declaration of the type matches the given +/// matcher. +/// +/// Usable as: Matcher<QualType>, Matcher<CallExpr>, Matcher<CXXConstructExpr> +inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, + internal::Matcher<Decl> > + hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) { + return internal::PolymorphicMatcherWithParam1< + internal::HasDeclarationMatcher, + internal::Matcher<Decl> >(InnerMatcher); +} + +/// \brief Matches on the implicit object argument of a member call expression. +/// +/// Example matches y.x() (matcher = call(on(hasType(record(hasName("Y")))))) +/// class Y { public: void x(); }; +/// void z() { Y y; y.x(); }", +/// +/// FIXME: Overload to allow directly matching types? +AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>, + InnerMatcher) { + const Expr *ExprNode = const_cast<CXXMemberCallExpr&>(Node) + .getImplicitObjectArgument() + ->IgnoreParenImpCasts(); + return (ExprNode != NULL && + InnerMatcher.matches(*ExprNode, Finder, Builder)); +} + +/// \brief Matches if the call expression's callee expression matches. +/// +/// Given +/// class Y { void x() { this->x(); x(); Y y; y.x(); } }; +/// void f() { f(); } +/// call(callee(expression())) +/// matches this->x(), x(), y.x(), f() +/// with callee(...) +/// matching this->x, x, y.x, f respectively +/// +/// Note: Callee cannot take the more general internal::Matcher<Expr> +/// because this introduces ambiguous overloads with calls to Callee taking a +/// internal::Matcher<Decl>, as the matcher hierarchy is purely +/// implemented in terms of implicit casts. +AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>, + InnerMatcher) { + const Expr *ExprNode = Node.getCallee(); + return (ExprNode != NULL && + InnerMatcher.matches(*ExprNode, Finder, Builder)); +} + +/// \brief Matches if the call expression's callee's declaration matches the +/// given matcher. +/// +/// Example matches y.x() (matcher = call(callee(method(hasName("x"))))) +/// class Y { public: void x(); }; +/// void z() { Y y; y.x(); +inline internal::Matcher<CallExpr> callee( + const internal::Matcher<Decl> &InnerMatcher) { + return internal::Matcher<CallExpr>(hasDeclaration(InnerMatcher)); +} + +/// \brief Matches if the expression's or declaration's type matches a type +/// matcher. +/// +/// Example matches x (matcher = expression(hasType( +/// hasDeclaration(record(hasName("X")))))) +/// and z (matcher = variable(hasType( +/// hasDeclaration(record(hasName("X")))))) +/// class X {}; +/// void y(X &x) { x; X z; } +AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher<QualType>, + InnerMatcher) { + TOOLING_COMPILE_ASSERT((llvm::is_base_of<Expr, NodeType>::value || + llvm::is_base_of<ValueDecl, NodeType>::value), + instantiated_with_wrong_types); + return InnerMatcher.matches(Node.getType(), Finder, Builder); +} + +/// \brief Overloaded to match the declaration of the expression's or value +/// declaration's type. +/// +/// In case of a value declaration (for example a variable declaration), +/// this resolves one layer of indirection. For example, in the value +/// declaration "X x;", record(hasName("X")) matches the declaration of X, +/// while variable(hasType(record(hasName("X")))) matches the declaration +/// of x." +/// +/// Example matches x (matcher = expression(hasType(record(hasName("X"))))) +/// and z (matcher = variable(hasType(record(hasName("X"))))) +/// class X {}; +/// void y(X &x) { x; X z; } +/// +/// Usable as: Matcher<Expr>, Matcher<ValueDecl> +inline internal::PolymorphicMatcherWithParam1< + internal::matcher_hasTypeMatcher, + internal::Matcher<QualType> > +hasType(const internal::Matcher<Decl> &InnerMatcher) { + return hasType(internal::Matcher<QualType>( + hasDeclaration(InnerMatcher))); +} + +/// \brief Matches if the matched type is represented by the given string. +/// +/// Given +/// class Y { public: void x(); }; +/// void z() { Y* y; y->x(); } +/// call(on(hasType(asString("class Y *")))) +/// matches y->x() +AST_MATCHER_P(QualType, asString, std::string, Name) { + return Name == Node.getAsString(); +} + +/// \brief Matches if the matched type is a pointer type and the pointee type +/// matches the specified matcher. +/// +/// Example matches y->x() +/// (matcher = call(on(hasType(pointsTo(record(hasName("Y"))))))) +/// class Y { public: void x(); }; +/// void z() { Y *y; y->x(); } +AST_MATCHER_P( + QualType, pointsTo, internal::Matcher<QualType>, + InnerMatcher) { + return (!Node.isNull() && Node->isPointerType() && + InnerMatcher.matches(Node->getPointeeType(), Finder, Builder)); +} + +/// \brief Overloaded to match the pointee type's declaration. +inline internal::Matcher<QualType> pointsTo( + const internal::Matcher<Decl> &InnerMatcher) { + return pointsTo(internal::Matcher<QualType>( + hasDeclaration(InnerMatcher))); +} + +/// \brief Matches if the matched type is a reference type and the referenced +/// type matches the specified matcher. +/// +/// Example matches X &x and const X &y +/// (matcher = variable(hasType(references(record(hasName("X")))))) +/// class X { +/// void a(X b) { +/// X &x = b; +/// const X &y = b; +/// }; +AST_MATCHER_P(QualType, references, internal::Matcher<QualType>, + InnerMatcher) { + return (!Node.isNull() && Node->isReferenceType() && + InnerMatcher.matches(Node->getPointeeType(), Finder, Builder)); +} + +/// \brief Overloaded to match the referenced type's declaration. +inline internal::Matcher<QualType> references( + const internal::Matcher<Decl> &InnerMatcher) { + return references(internal::Matcher<QualType>( + hasDeclaration(InnerMatcher))); +} + +AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument, + internal::Matcher<Expr>, InnerMatcher) { + const Expr *ExprNode = + const_cast<CXXMemberCallExpr&>(Node).getImplicitObjectArgument(); + return (ExprNode != NULL && + InnerMatcher.matches(*ExprNode, Finder, Builder)); +} + +/// \brief Matches if the expression's type either matches the specified +/// matcher, or is a pointer to a type that matches the InnerMatcher. +inline internal::Matcher<CXXMemberCallExpr> thisPointerType( + const internal::Matcher<QualType> &InnerMatcher) { + return onImplicitObjectArgument( + anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher)))); +} + +/// \brief Overloaded to match the type's declaration. +inline internal::Matcher<CXXMemberCallExpr> thisPointerType( + const internal::Matcher<Decl> &InnerMatcher) { + return onImplicitObjectArgument( + anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher)))); +} + +/// \brief Matches a DeclRefExpr that refers to a declaration that matches the +/// specified matcher. +/// +/// Example matches x in if(x) +/// (matcher = declarationReference(to(variable(hasName("x"))))) +/// bool x; +/// if (x) {} +AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>, + InnerMatcher) { + const Decl *DeclNode = Node.getDecl(); + return (DeclNode != NULL && + InnerMatcher.matches(*DeclNode, Finder, Builder)); +} + +/// \brief Matches a \c DeclRefExpr that refers to a declaration through a +/// specific using shadow declaration. +/// +/// FIXME: This currently only works for functions. Fix. +/// +/// Given +/// namespace a { void f() {} } +/// using a::f; +/// void g() { +/// f(); // Matches this .. +/// a::f(); // .. but not this. +/// } +/// declarationReference(throughUsingDeclaration(anything())) +/// matches \c f() +AST_MATCHER_P(DeclRefExpr, throughUsingDecl, + internal::Matcher<UsingShadowDecl>, Matcher) { + const NamedDecl *FoundDecl = Node.getFoundDecl(); + if (const UsingShadowDecl *UsingDecl = + llvm::dyn_cast<UsingShadowDecl>(FoundDecl)) + return Matcher.matches(*UsingDecl, Finder, Builder); + return false; +} + +/// \brief Matches a variable declaration that has an initializer expression +/// that matches the given matcher. +/// +/// Example matches x (matcher = variable(hasInitializer(call()))) +/// bool y() { return true; } +/// bool x = y(); +AST_MATCHER_P( + VarDecl, hasInitializer, internal::Matcher<Expr>, + InnerMatcher) { + const Expr *Initializer = Node.getAnyInitializer(); + return (Initializer != NULL && + InnerMatcher.matches(*Initializer, Finder, Builder)); +} + +/// \brief Checks that a call expression or a constructor call expression has +/// a specific number of arguments (including absent default arguments). +/// +/// Example matches f(0, 0) (matcher = call(argumentCountIs(2))) +/// void f(int x, int y); +/// f(0, 0); +AST_POLYMORPHIC_MATCHER_P(argumentCountIs, unsigned, N) { + TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value || + llvm::is_base_of<CXXConstructExpr, + NodeType>::value), + instantiated_with_wrong_types); + return Node.getNumArgs() == N; +} + +/// \brief Matches the n'th argument of a call expression or a constructor +/// call expression. +/// +/// Example matches y in x(y) +/// (matcher = call(hasArgument(0, declarationReference()))) +/// void x(int) { int y; x(y); } +AST_POLYMORPHIC_MATCHER_P2( + hasArgument, unsigned, N, internal::Matcher<Expr>, InnerMatcher) { + TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value || + llvm::is_base_of<CXXConstructExpr, + NodeType>::value), + instantiated_with_wrong_types); + return (N < Node.getNumArgs() && + InnerMatcher.matches( + *Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder)); +} + +/// \brief Matches a constructor initializer. +/// +/// Given +/// struct Foo { +/// Foo() : foo_(1) { } +/// int foo_; +/// }; +/// record(has(constructor(hasAnyConstructorInitializer(anything())))) +/// record matches Foo, hasAnyConstructorInitializer matches foo_(1) +AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer, + internal::Matcher<CXXCtorInitializer>, InnerMatcher) { + for (CXXConstructorDecl::init_const_iterator I = Node.init_begin(); + I != Node.init_end(); ++I) { + if (InnerMatcher.matches(**I, Finder, Builder)) { + return true; + } + } + return false; +} + +/// \brief Matches the field declaration of a constructor initializer. +/// +/// Given +/// struct Foo { +/// Foo() : foo_(1) { } +/// int foo_; +/// }; +/// record(has(constructor(hasAnyConstructorInitializer( +/// forField(hasName("foo_")))))) +/// matches Foo +/// with forField matching foo_ +AST_MATCHER_P(CXXCtorInitializer, forField, + internal::Matcher<FieldDecl>, InnerMatcher) { + const FieldDecl *NodeAsDecl = Node.getMember(); + return (NodeAsDecl != NULL && + InnerMatcher.matches(*NodeAsDecl, Finder, Builder)); +} + +/// \brief Matches the initializer expression of a constructor initializer. +/// +/// Given +/// struct Foo { +/// Foo() : foo_(1) { } +/// int foo_; +/// }; +/// record(has(constructor(hasAnyConstructorInitializer( +/// withInitializer(integerLiteral(equals(1))))))) +/// matches Foo +/// with withInitializer matching (1) +AST_MATCHER_P(CXXCtorInitializer, withInitializer, + internal::Matcher<Expr>, InnerMatcher) { + const Expr* NodeAsExpr = Node.getInit(); + return (NodeAsExpr != NULL && + InnerMatcher.matches(*NodeAsExpr, Finder, Builder)); +} + +/// \brief Matches a contructor initializer if it is explicitly written in +/// code (as opposed to implicitly added by the compiler). +/// +/// Given +/// struct Foo { +/// Foo() { } +/// Foo(int) : foo_("A") { } +/// string foo_; +/// }; +/// constructor(hasAnyConstructorInitializer(isWritten())) +/// will match Foo(int), but not Foo() +AST_MATCHER(CXXCtorInitializer, isWritten) { + return Node.isWritten(); +} + +/// \brief Matches a constructor declaration that has been implicitly added +/// by the compiler (eg. implicit default/copy constructors). +AST_MATCHER(CXXConstructorDecl, isImplicit) { + return Node.isImplicit(); +} + +/// \brief Matches any argument of a call expression or a constructor call +/// expression. +/// +/// Given +/// void x(int, int, int) { int y; x(1, y, 42); } +/// call(hasAnyArgument(declarationReference())) +/// matches x(1, y, 42) +/// with hasAnyArgument(...) +/// matching y +AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, internal::Matcher<Expr>, + InnerMatcher) { + TOOLING_COMPILE_ASSERT((llvm::is_base_of<CallExpr, NodeType>::value || + llvm::is_base_of<CXXConstructExpr, + NodeType>::value), + instantiated_with_wrong_types); + for (unsigned I = 0; I < Node.getNumArgs(); ++I) { + if (InnerMatcher.matches(*Node.getArg(I)->IgnoreParenImpCasts(), + Finder, Builder)) { + return true; + } + } + return false; +} + +/// \brief Matches the n'th parameter of a function declaration. +/// +/// Given +/// class X { void f(int x) {} }; +/// method(hasParameter(0, hasType(variable()))) +/// matches f(int x) {} +/// with hasParameter(...) +/// matching int x +AST_MATCHER_P2(FunctionDecl, hasParameter, + unsigned, N, internal::Matcher<ParmVarDecl>, + InnerMatcher) { + return (N < Node.getNumParams() && + InnerMatcher.matches( + *Node.getParamDecl(N), Finder, Builder)); +} + +/// \brief Matches any parameter of a function declaration. +/// +/// Does not match the 'this' parameter of a method. +/// +/// Given +/// class X { void f(int x, int y, int z) {} }; +/// method(hasAnyParameter(hasName("y"))) +/// matches f(int x, int y, int z) {} +/// with hasAnyParameter(...) +/// matching int y +AST_MATCHER_P(FunctionDecl, hasAnyParameter, + internal::Matcher<ParmVarDecl>, InnerMatcher) { + for (unsigned I = 0; I < Node.getNumParams(); ++I) { + if (InnerMatcher.matches(*Node.getParamDecl(I), Finder, Builder)) { + return true; + } + } + return false; +} + +/// \brief Matches the return type of a function declaration. +/// +/// Given: +/// class X { int f() { return 1; } }; +/// method(returns(asString("int"))) +/// matches int f() { return 1; } +AST_MATCHER_P(FunctionDecl, returns, internal::Matcher<QualType>, Matcher) { + return Matcher.matches(Node.getResultType(), Finder, Builder); +} + +/// \brief Matches the condition expression of an if statement, for loop, +/// or conditional operator. +/// +/// Example matches true (matcher = hasCondition(boolLiteral(equals(true)))) +/// if (true) {} +AST_POLYMORPHIC_MATCHER_P(hasCondition, internal::Matcher<Expr>, + InnerMatcher) { + TOOLING_COMPILE_ASSERT( + (llvm::is_base_of<IfStmt, NodeType>::value) || + (llvm::is_base_of<ForStmt, NodeType>::value) || + (llvm::is_base_of<WhileStmt, NodeType>::value) || + (llvm::is_base_of<DoStmt, NodeType>::value) || + (llvm::is_base_of<ConditionalOperator, NodeType>::value), + has_condition_requires_if_statement_conditional_operator_or_loop); + const Expr *const Condition = Node.getCond(); + return (Condition != NULL && + InnerMatcher.matches(*Condition, Finder, Builder)); +} + +/// \brief Matches the condition variable statement in an if statement. +/// +/// Given +/// if (A* a = GetAPointer()) {} +/// hasConditionVariableStatment(...) +/// matches 'A* a = GetAPointer()'. +AST_MATCHER_P(IfStmt, hasConditionVariableStatement, + internal::Matcher<DeclStmt>, InnerMatcher) { + const DeclStmt* const DeclarationStatement = + Node.getConditionVariableDeclStmt(); + return DeclarationStatement != NULL && + InnerMatcher.matches(*DeclarationStatement, Finder, Builder); +} + +/// \brief Matches the index expression of an array subscript expression. +/// +/// Given +/// int i[5]; +/// void f() { i[1] = 42; } +/// arraySubscriptExpression(hasIndex(integerLiteral())) +/// matches \c i[1] with the \c integerLiteral() matching \c 1 +AST_MATCHER_P(ArraySubscriptExpr, hasIndex, + internal::Matcher<Expr>, matcher) { + if (const Expr* Expression = Node.getIdx()) + return matcher.matches(*Expression, Finder, Builder); + return false; +} + +/// \brief Matches the base expression of an array subscript expression. +/// +/// Given +/// int i[5]; +/// void f() { i[1] = 42; } +/// arraySubscriptExpression(hasBase(implicitCast( +/// hasSourceExpression(declarationReference())))) +/// matches \c i[1] with the \c declarationReference() matching \c i +AST_MATCHER_P(ArraySubscriptExpr, hasBase, + internal::Matcher<Expr>, matcher) { + if (const Expr* Expression = Node.getBase()) + return matcher.matches(*Expression, Finder, Builder); + return false; +} + +/// \brief Matches a 'for', 'while', or 'do while' statement that has +/// a given body. +/// +/// Given +/// for (;;) {} +/// hasBody(compoundStatement()) +/// matches 'for (;;) {}' +/// with compoundStatement() +/// matching '{}' +AST_POLYMORPHIC_MATCHER_P(hasBody, internal::Matcher<Stmt>, + InnerMatcher) { + TOOLING_COMPILE_ASSERT( + (llvm::is_base_of<DoStmt, NodeType>::value) || + (llvm::is_base_of<ForStmt, NodeType>::value) || + (llvm::is_base_of<WhileStmt, NodeType>::value), + has_body_requires_for_while_or_do_statement); + const Stmt *const Statement = Node.getBody(); + return (Statement != NULL && + InnerMatcher.matches(*Statement, Finder, Builder)); +} + +/// \brief Matches compound statements where at least one substatement matches +/// a given matcher. +/// +/// Given +/// { {}; 1+2; } +/// hasAnySubstatement(compoundStatement()) +/// matches '{ {}; 1+2; }' +/// with compoundStatement() +/// matching '{}' +AST_MATCHER_P(CompoundStmt, hasAnySubstatement, + internal::Matcher<Stmt>, InnerMatcher) { + for (CompoundStmt::const_body_iterator It = Node.body_begin(); + It != Node.body_end(); + ++It) { + if (InnerMatcher.matches(**It, Finder, Builder)) return true; + } + return false; +} + +/// \brief Checks that a compound statement contains a specific number of +/// child statements. +/// +/// Example: Given +/// { for (;;) {} } +/// compoundStatement(statementCountIs(0))) +/// matches '{}' +/// but does not match the outer compound statement. +AST_MATCHER_P(CompoundStmt, statementCountIs, unsigned, N) { + return Node.size() == N; +} + +/// \brief Matches literals that are equal to the given value. +/// +/// Example matches true (matcher = boolLiteral(equals(true))) +/// true +/// +/// Usable as: Matcher<CharacterLiteral>, Matcher<CXXBoolLiteral>, +/// Matcher<FloatingLiteral>, Matcher<IntegerLiteral> +template <typename ValueT> +internal::PolymorphicMatcherWithParam1<internal::ValueEqualsMatcher, ValueT> +equals(const ValueT &Value) { + return internal::PolymorphicMatcherWithParam1< + internal::ValueEqualsMatcher, + ValueT>(Value); +} + +/// \brief Matches the operator Name of operator expressions (binary or +/// unary). +/// +/// Example matches a || b (matcher = binaryOperator(hasOperatorName("||"))) +/// !(a || b) +AST_POLYMORPHIC_MATCHER_P(hasOperatorName, std::string, Name) { + TOOLING_COMPILE_ASSERT( + (llvm::is_base_of<BinaryOperator, NodeType>::value) || + (llvm::is_base_of<UnaryOperator, NodeType>::value), + has_condition_requires_if_statement_or_conditional_operator); + return Name == Node.getOpcodeStr(Node.getOpcode()); +} + +/// \brief Matches the left hand side of binary operator expressions. +/// +/// Example matches a (matcher = binaryOperator(hasLHS())) +/// a || b +AST_MATCHER_P(BinaryOperator, hasLHS, + internal::Matcher<Expr>, InnerMatcher) { + Expr *LeftHandSide = Node.getLHS(); + return (LeftHandSide != NULL && + InnerMatcher.matches(*LeftHandSide, Finder, Builder)); +} + +/// \brief Matches the right hand side of binary operator expressions. +/// +/// Example matches b (matcher = binaryOperator(hasRHS())) +/// a || b +AST_MATCHER_P(BinaryOperator, hasRHS, + internal::Matcher<Expr>, InnerMatcher) { + Expr *RightHandSide = Node.getRHS(); + return (RightHandSide != NULL && + InnerMatcher.matches(*RightHandSide, Finder, Builder)); +} + +/// \brief Matches if either the left hand side or the right hand side of a +/// binary operator matches. +inline internal::Matcher<BinaryOperator> hasEitherOperand( + const internal::Matcher<Expr> &InnerMatcher) { + return anyOf(hasLHS(InnerMatcher), hasRHS(InnerMatcher)); +} + +/// \brief Matches if the operand of a unary operator matches. +/// +/// Example matches true (matcher = hasOperand(boolLiteral(equals(true)))) +/// !true +AST_MATCHER_P(UnaryOperator, hasUnaryOperand, + internal::Matcher<Expr>, InnerMatcher) { + const Expr * const Operand = Node.getSubExpr(); + return (Operand != NULL && + InnerMatcher.matches(*Operand, Finder, Builder)); +} + +/// \brief Matches if the cast's source expression matches the given matcher. +/// +/// Example: matches "a string" (matcher = +/// hasSourceExpression(constructorCall())) +/// +/// class URL { URL(string); }; +/// URL url = "a string"; +AST_MATCHER_P(CastExpr, hasSourceExpression, + internal::Matcher<Expr>, InnerMatcher) { + const Expr* const SubExpression = Node.getSubExpr(); + return (SubExpression != NULL && + InnerMatcher.matches(*SubExpression, Finder, Builder)); +} + +/// \brief Matches casts whose destination type matches a given matcher. +/// +/// (Note: Clang's AST refers to other conversions as "casts" too, and calls +/// actual casts "explicit" casts.) +AST_MATCHER_P(ExplicitCastExpr, hasDestinationType, + internal::Matcher<QualType>, InnerMatcher) { + const QualType NodeType = Node.getTypeAsWritten(); + return InnerMatcher.matches(NodeType, Finder, Builder); +} + +/// \brief Matches implicit casts whose destination type matches a given +/// matcher. +/// +/// FIXME: Unit test this matcher +AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType, + internal::Matcher<QualType>, InnerMatcher) { + return InnerMatcher.matches(Node.getType(), Finder, Builder); +} + +/// \brief Matches the true branch expression of a conditional operator. +/// +/// Example matches a +/// condition ? a : b +AST_MATCHER_P(ConditionalOperator, hasTrueExpression, + internal::Matcher<Expr>, InnerMatcher) { + Expr *Expression = Node.getTrueExpr(); + return (Expression != NULL && + InnerMatcher.matches(*Expression, Finder, Builder)); +} + +/// \brief Matches the false branch expression of a conditional operator. +/// +/// Example matches b +/// condition ? a : b +AST_MATCHER_P(ConditionalOperator, hasFalseExpression, + internal::Matcher<Expr>, InnerMatcher) { + Expr *Expression = Node.getFalseExpr(); + return (Expression != NULL && + InnerMatcher.matches(*Expression, Finder, Builder)); +} + +/// \brief Matches if a declaration has a body attached. +/// +/// Example matches A, va, fa +/// class A {}; +/// class B; // Doesn't match, as it has no body. +/// int va; +/// extern int vb; // Doesn't match, as it doesn't define the variable. +/// void fa() {} +/// void fb(); // Doesn't match, as it has no body. +/// +/// Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl> +inline internal::PolymorphicMatcherWithParam0<internal::IsDefinitionMatcher> +isDefinition() { + return internal::PolymorphicMatcherWithParam0< + internal::IsDefinitionMatcher>(); +} + +/// \brief Matches the class declaration that the given method declaration +/// belongs to. +/// +/// FIXME: Generalize this for other kinds of declarations. +/// FIXME: What other kind of declarations would we need to generalize +/// this to? +/// +/// Example matches A() in the last line +/// (matcher = constructorCall(hasDeclaration(method( +/// ofClass(hasName("A")))))) +/// class A { +/// public: +/// A(); +/// }; +/// A a = A(); +AST_MATCHER_P(CXXMethodDecl, ofClass, + internal::Matcher<CXXRecordDecl>, InnerMatcher) { + const CXXRecordDecl *Parent = Node.getParent(); + return (Parent != NULL && + InnerMatcher.matches(*Parent, Finder, Builder)); +} + +/// \brief Matches member expressions that are called with '->' as opposed +/// to '.'. +/// +/// Member calls on the implicit this pointer match as called with '->'. +/// +/// Given +/// class Y { +/// void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; } +/// int a; +/// static int b; +/// }; +/// memberExpression(isArrow()) +/// matches this->x, x, y.x, a, this->b +inline internal::Matcher<MemberExpr> isArrow() { + return makeMatcher(new internal::IsArrowMatcher()); +} + +/// \brief Matches QualType nodes that are of integer type. +/// +/// Given +/// void a(int); +/// void b(long); +/// void c(double); +/// function(hasAnyParameter(hasType(isInteger()))) +/// matches "a(int)", "b(long)", but not "c(double)". +AST_MATCHER(QualType, isInteger) { + return Node->isIntegerType(); +} + +/// \brief Matches QualType nodes that are const-qualified, i.e., that +/// include "top-level" const. +/// +/// Given +/// void a(int); +/// void b(int const); +/// void c(const int); +/// void d(const int*); +/// void e(int const) {}; +/// function(hasAnyParameter(hasType(isConstQualified()))) +/// matches "void b(int const)", "void c(const int)" and +/// "void e(int const) {}". It does not match d as there +/// is no top-level const on the parameter type "const int *". +inline internal::Matcher<QualType> isConstQualified() { + return makeMatcher(new internal::IsConstQualifiedMatcher()); +} + +/// \brief Matches a member expression where the member is matched by a +/// given matcher. +/// +/// Given +/// struct { int first, second; } first, second; +/// int i(second.first); +/// int j(first.second); +/// memberExpression(member(hasName("first"))) +/// matches second.first +/// but not first.second (because the member name there is "second"). +AST_MATCHER_P(MemberExpr, member, + internal::Matcher<ValueDecl>, InnerMatcher) { + return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder); +} + +/// \brief Matches a member expression where the object expression is +/// matched by a given matcher. +/// +/// Given +/// struct X { int m; }; +/// void f(X x) { x.m; m; } +/// memberExpression(hasObjectExpression(hasType(record(hasName("X"))))))) +/// matches "x.m" and "m" +/// with hasObjectExpression(...) +/// matching "x" and the implicit object expression of "m" which has type X*. +AST_MATCHER_P(MemberExpr, hasObjectExpression, + internal::Matcher<Expr>, InnerMatcher) { + return InnerMatcher.matches(*Node.getBase(), Finder, Builder); +} + +/// \brief Matches any using shadow declaration. +/// +/// Given +/// namespace X { void b(); } +/// using X::b; +/// usingDecl(hasAnyUsingShadowDecl(hasName("b")))) +/// matches \code using X::b \endcode +AST_MATCHER_P(UsingDecl, hasAnyUsingShadowDecl, + internal::Matcher<UsingShadowDecl>, Matcher) { + for (UsingDecl::shadow_iterator II = Node.shadow_begin(); + II != Node.shadow_end(); ++II) { + if (Matcher.matches(**II, Finder, Builder)) + return true; + } + return false; +} + +/// \brief Matches a using shadow declaration where the target declaration is +/// matched by the given matcher. +/// +/// Given +/// namespace X { int a; void b(); } +/// using X::a; +/// using X::b; +/// usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(function()))) +/// matches \code using X::b \endcode +/// but not \code using X::a \endcode +AST_MATCHER_P(UsingShadowDecl, hasTargetDecl, + internal::Matcher<NamedDecl>, Matcher) { + return Matcher.matches(*Node.getTargetDecl(), Finder, Builder); +} + +/// \brief Matches template instantiations of function, class, or static +/// member variable template instantiations. +/// +/// Given +/// template <typename T> class X {}; class A {}; X<A> x; +/// or +/// template <typename T> class X {}; class A {}; template class X<A>; +/// record(hasName("::X"), isTemplateInstantiation()) +/// matches the template instantiation of X<A>. +/// +/// But given +/// template <typename T> class X {}; class A {}; +/// template <> class X<A> {}; X<A> x; +/// record(hasName("::X"), isTemplateInstantiation()) +/// does not match, as X<A> is an explicit template specialization. +/// +/// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl> +inline internal::PolymorphicMatcherWithParam0< + internal::IsTemplateInstantiationMatcher> +isTemplateInstantiation() { + return internal::PolymorphicMatcherWithParam0< + internal::IsTemplateInstantiationMatcher>(); +} + +} // end namespace ast_matchers +} // end namespace clang + +#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h new file mode 100644 index 0000000..3f55685 --- /dev/null +++ b/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -0,0 +1,901 @@ +//===--- ASTMatchersInternal.h - Structural query framework -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implements the base layer of the matcher framework. +// +// Matchers are methods that return a Matcher<T> which provides a method +// Matches(...) which is a predicate on an AST node. The Matches method's +// parameters define the context of the match, which allows matchers to recurse +// or store the current node as bound to a specific string, so that it can be +// retrieved later. +// +// In general, matchers have two parts: +// 1. A function Matcher<T> MatcherName(<arguments>) which returns a Matcher<T> +// based on the arguments and optionally on template type deduction based +// on the arguments. Matcher<T>s form an implicit reverse hierarchy +// to clang's AST class hierarchy, meaning that you can use a Matcher<Base> +// everywhere a Matcher<Derived> is required. +// 2. An implementation of a class derived from MatcherInterface<T>. +// +// The matcher functions are defined in ASTMatchers.h. To make it possible +// to implement both the matcher function and the implementation of the matcher +// interface in one place, ASTMatcherMacros.h defines macros that allow +// implementing a matcher in a single place. +// +// This file contains the base classes needed to construct the actual matchers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H +#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H + +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/Stmt.h" +#include "llvm/ADT/VariadicFunction.h" +#include <map> +#include <string> +#include <vector> + +namespace clang { +namespace ast_matchers { + +/// FIXME: Move into the llvm support library. +template <bool> struct CompileAssert {}; +#define TOOLING_COMPILE_ASSERT(Expr, Msg) \ + typedef CompileAssert<(bool(Expr))> Msg[bool(Expr) ? 1 : -1] + +class BoundNodes; + +namespace internal { + +class BoundNodesTreeBuilder; + +/// \brief A tree of bound nodes in match results. +/// +/// If a match can contain multiple matches on the same node with different +/// matching subexpressions, BoundNodesTree contains a branch for each of +/// those matching subexpressions. +/// +/// BoundNodesTree's are created during the matching process; when a match +/// is found, we iterate over the tree and create a BoundNodes object containing +/// the union of all bound nodes on the path from the root to a each leaf. +class BoundNodesTree { +public: + /// \brief A visitor interface to visit all BoundNodes results for a + /// BoundNodesTree. + class Visitor { + public: + virtual ~Visitor() {} + + /// \brief Called multiple times during a single call to VisitMatches(...). + /// + /// 'BoundNodesView' contains the bound nodes for a single match. + virtual void visitMatch(const BoundNodes& BoundNodesView) = 0; + }; + + BoundNodesTree(); + + /// \brief Create a BoundNodesTree from pre-filled maps of bindings. + BoundNodesTree(const std::map<std::string, const Decl*>& DeclBindings, + const std::map<std::string, const Stmt*>& StmtBindings, + const std::vector<BoundNodesTree> RecursiveBindings); + + /// \brief Adds all bound nodes to bound_nodes_builder. + void copyTo(BoundNodesTreeBuilder* Builder) const; + + /// \brief Visits all matches that this BoundNodesTree represents. + /// + /// The ownership of 'ResultVisitor' remains at the caller. + void visitMatches(Visitor* ResultVisitor); + +private: + void visitMatchesRecursively( + Visitor* ResultVistior, + std::map<std::string, const Decl*> DeclBindings, + std::map<std::string, const Stmt*> StmtBindings); + + template <typename T> + void copyBindingsTo(const T& bindings, BoundNodesTreeBuilder* Builder) const; + + // FIXME: Find out whether we want to use different data structures here - + // first benchmarks indicate that it doesn't matter though. + + std::map<std::string, const Decl*> DeclBindings; + std::map<std::string, const Stmt*> StmtBindings; + + std::vector<BoundNodesTree> RecursiveBindings; +}; + +/// \brief Creates BoundNodesTree objects. +/// +/// The tree builder is used during the matching process to insert the bound +/// nodes from the Id matcher. +class BoundNodesTreeBuilder { +public: + BoundNodesTreeBuilder(); + + /// \brief Add a binding from an id to a node. + /// + /// FIXME: Add overloads for all AST base types. + /// @{ + void setBinding(const std::string &Id, const Decl *Node); + void setBinding(const std::string &Id, const Stmt *Node); + /// @} + + /// \brief Adds a branch in the tree. + void addMatch(const BoundNodesTree& Bindings); + + /// \brief Returns a BoundNodes object containing all current bindings. + BoundNodesTree build() const; + +private: + BoundNodesTreeBuilder(const BoundNodesTreeBuilder&); // DO NOT IMPLEMENT + void operator=(const BoundNodesTreeBuilder&); // DO NOT IMPLEMENT + + std::map<std::string, const Decl*> DeclBindings; + std::map<std::string, const Stmt*> StmtBindings; + + std::vector<BoundNodesTree> RecursiveBindings; +}; + +class ASTMatchFinder; + +/// \brief Generic interface for matchers on an AST node of type T. +/// +/// Implement this if your matcher may need to inspect the children or +/// descendants of the node or bind matched nodes to names. If you are +/// writing a simple matcher that only inspects properties of the +/// current node and doesn't care about its children or descendants, +/// implement SingleNodeMatcherInterface instead. +template <typename T> +class MatcherInterface : public llvm::RefCountedBaseVPTR { +public: + virtual ~MatcherInterface() {} + + /// \brief Returns true if 'Node' can be matched. + /// + /// May bind 'Node' to an ID via 'Builder', or recurse into + /// the AST via 'Finder'. + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const = 0; +}; + +/// \brief Interface for matchers that only evaluate properties on a single node. +template <typename T> +class SingleNodeMatcherInterface : public MatcherInterface<T> { +public: + /// \brief Returns true if the matcher matches the provided node. + /// + /// A subclass must implement this instead of Matches(). + virtual bool matchesNode(const T &Node) const = 0; + +private: + /// Implements MatcherInterface::Matches. + virtual bool matches(const T &Node, + ASTMatchFinder * /* Finder */, + BoundNodesTreeBuilder * /* Builder */) const { + return matchesNode(Node); + } +}; + +/// \brief Wrapper of a MatcherInterface<T> *that allows copying. +/// +/// A Matcher<Base> can be used anywhere a Matcher<Derived> is +/// required. This establishes an is-a relationship which is reverse +/// to the AST hierarchy. In other words, Matcher<T> is contravariant +/// with respect to T. The relationship is built via a type conversion +/// operator rather than a type hierarchy to be able to templatize the +/// type hierarchy instead of spelling it out. +template <typename T> +class Matcher { +public: + /// \brief Takes ownership of the provided implementation pointer. + explicit Matcher(MatcherInterface<T> *Implementation) + : Implementation(Implementation) {} + + /// \brief Forwards the call to the underlying MatcherInterface<T> pointer. + bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return Implementation->matches(Node, Finder, Builder); + } + + /// \brief Implicitly converts this object to a Matcher<Derived>. + /// + /// Requires Derived to be derived from T. + template <typename Derived> + operator Matcher<Derived>() const { + return Matcher<Derived>(new ImplicitCastMatcher<Derived>(*this)); + } + + /// \brief Returns an ID that uniquely identifies the matcher. + uint64_t getID() const { + /// FIXME: Document the requirements this imposes on matcher + /// implementations (no new() implementation_ during a Matches()). + return reinterpret_cast<uint64_t>(Implementation.getPtr()); + } + +private: + /// \brief Allows conversion from Matcher<T> to Matcher<Derived> if Derived + /// is derived from T. + template <typename Derived> + class ImplicitCastMatcher : public MatcherInterface<Derived> { + public: + explicit ImplicitCastMatcher(const Matcher<T> &From) + : From(From) {} + + virtual bool matches(const Derived &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return From.matches(Node, Finder, Builder); + } + + private: + const Matcher<T> From; + }; + + llvm::IntrusiveRefCntPtr< MatcherInterface<T> > Implementation; +}; // class Matcher + +/// \brief A convenient helper for creating a Matcher<T> without specifying +/// the template type argument. +template <typename T> +inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) { + return Matcher<T>(Implementation); +} + +/// \brief Matches declarations for QualType and CallExpr. +/// +/// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but +/// not actually used. +template <typename T, typename DeclMatcherT> +class HasDeclarationMatcher : public MatcherInterface<T> { + TOOLING_COMPILE_ASSERT((llvm::is_same< DeclMatcherT, + Matcher<Decl> >::value), + instantiated_with_wrong_types); +public: + explicit HasDeclarationMatcher(const Matcher<Decl> &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return matchesSpecialized(Node, Finder, Builder); + } + +private: + /// \brief Extracts the CXXRecordDecl of a QualType and returns whether the + /// inner matcher matches on it. + bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + /// FIXME: Add other ways to convert... + if (Node.isNull()) + return false; + CXXRecordDecl *NodeAsRecordDecl = Node->getAsCXXRecordDecl(); + return NodeAsRecordDecl != NULL && + InnerMatcher.matches(*NodeAsRecordDecl, Finder, Builder); + } + + /// \brief Extracts the Decl of the callee of a CallExpr and returns whether + /// the inner matcher matches on it. + bool matchesSpecialized(const CallExpr &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + const Decl *NodeAsDecl = Node.getCalleeDecl(); + return NodeAsDecl != NULL && + InnerMatcher.matches(*NodeAsDecl, Finder, Builder); + } + + /// \brief Extracts the Decl of the constructor call and returns whether the + /// inner matcher matches on it. + bool matchesSpecialized(const CXXConstructExpr &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + const Decl *NodeAsDecl = Node.getConstructor(); + return NodeAsDecl != NULL && + InnerMatcher.matches(*NodeAsDecl, Finder, Builder); + } + + const Matcher<Decl> InnerMatcher; +}; + +/// \brief IsBaseType<T>::value is true if T is a "base" type in the AST +/// node class hierarchies (i.e. if T is Decl, Stmt, or QualType). +template <typename T> +struct IsBaseType { + static const bool value = + (llvm::is_same<T, Decl>::value || + llvm::is_same<T, Stmt>::value || + llvm::is_same<T, QualType>::value || + llvm::is_same<T, CXXCtorInitializer>::value); +}; +template <typename T> +const bool IsBaseType<T>::value; + +/// \brief Interface that can match any AST base node type and contains default +/// implementations returning false. +class UntypedBaseMatcher : public llvm::RefCountedBaseVPTR { +public: + virtual ~UntypedBaseMatcher() {} + + virtual bool matches(const Decl &DeclNode, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return false; + } + virtual bool matches(const QualType &TypeNode, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return false; + } + virtual bool matches(const Stmt &StmtNode, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return false; + } + virtual bool matches(const CXXCtorInitializer &CtorInitNode, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return false; + } + + /// \brief Returns a unique ID for the matcher. + virtual uint64_t getID() const = 0; +}; + +/// \brief An UntypedBaseMatcher that overwrites the Matches(...) method for +/// node type T. T must be an AST base type. +template <typename T> +class TypedBaseMatcher : public UntypedBaseMatcher { + TOOLING_COMPILE_ASSERT(IsBaseType<T>::value, + typed_base_matcher_can_only_be_used_with_base_type); +public: + explicit TypedBaseMatcher(const Matcher<T> &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + using UntypedBaseMatcher::matches; + /// \brief Implements UntypedBaseMatcher::Matches. + /// + /// Since T is guaranteed to be a "base" AST node type, this method is + /// guaranteed to override one of the matches() methods from + /// UntypedBaseMatcher. + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return InnerMatcher.matches(Node, Finder, Builder); + } + + /// \brief Implements UntypedBaseMatcher::getID. + virtual uint64_t getID() const { + return InnerMatcher.getID(); + } + +private: + Matcher<T> InnerMatcher; +}; + +/// \brief Interface that allows matchers to traverse the AST. +/// FIXME: Find a better name. +/// +/// This provides two entry methods for each base node type in the AST: +/// - matchesChildOf: +/// Matches a matcher on every child node of the given node. Returns true +/// if at least one child node could be matched. +/// - matchesDescendantOf: +/// Matches a matcher on all descendant nodes of the given node. Returns true +/// if at least one descendant matched. +class ASTMatchFinder { +public: + /// \brief Defines how we descend a level in the AST when we pass + /// through expressions. + enum TraversalKind { + /// Will traverse any child nodes. + TK_AsIs, + /// Will not traverse implicit casts and parentheses. + TK_IgnoreImplicitCastsAndParentheses + }; + + /// \brief Defines how bindings are processed on recursive matches. + enum BindKind { + /// Stop at the first match and only bind the first match. + BK_First, + /// Create results for all combinations of bindings that match. + BK_All + }; + + virtual ~ASTMatchFinder() {} + + /// \brief Returns true if the given class is directly or indirectly derived + /// from a base type matching \c base. + /// + /// A class is considered to be also derived from itself. + virtual bool classIsDerivedFrom(const CXXRecordDecl *Declaration, + const Matcher<NamedDecl> &Base, + BoundNodesTreeBuilder *Builder) = 0; + + // FIXME: Implement for other base nodes. + virtual bool matchesChildOf(const Decl &DeclNode, + const UntypedBaseMatcher &BaseMatcher, + BoundNodesTreeBuilder *Builder, + TraversalKind Traverse, + BindKind Bind) = 0; + virtual bool matchesChildOf(const Stmt &StmtNode, + const UntypedBaseMatcher &BaseMatcher, + BoundNodesTreeBuilder *Builder, + TraversalKind Traverse, + BindKind Bind) = 0; + + virtual bool matchesDescendantOf(const Decl &DeclNode, + const UntypedBaseMatcher &BaseMatcher, + BoundNodesTreeBuilder *Builder, + BindKind Bind) = 0; + virtual bool matchesDescendantOf(const Stmt &StmtNode, + const UntypedBaseMatcher &BaseMatcher, + BoundNodesTreeBuilder *Builder, + BindKind Bind) = 0; +}; + +/// \brief Converts a \c Matcher<T> to a matcher of desired type \c To by +/// "adapting" a \c To into a \c T. +/// +/// The \c ArgumentAdapterT argument specifies how the adaptation is done. +/// +/// For example: +/// \c ArgumentAdaptingMatcher<HasMatcher, T>(InnerMatcher); +/// Given that \c InnerMatcher is of type \c Matcher<T>, this returns a matcher +/// that is convertible into any matcher of type \c To by constructing +/// \c HasMatcher<To, T>(InnerMatcher). +/// +/// If a matcher does not need knowledge about the inner type, prefer to use +/// PolymorphicMatcherWithParam1. +template <template <typename ToArg, typename FromArg> class ArgumentAdapterT, + typename T> +class ArgumentAdaptingMatcher { +public: + explicit ArgumentAdaptingMatcher(const Matcher<T> &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + template <typename To> + operator Matcher<To>() const { + return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher)); + } + +private: + const Matcher<T> InnerMatcher; +}; + +/// \brief A PolymorphicMatcherWithParamN<MatcherT, P1, ..., PN> object can be +/// created from N parameters p1, ..., pN (of type P1, ..., PN) and +/// used as a Matcher<T> where a MatcherT<T, P1, ..., PN>(p1, ..., pN) +/// can be constructed. +/// +/// For example: +/// - PolymorphicMatcherWithParam0<IsDefinitionMatcher>() +/// creates an object that can be used as a Matcher<T> for any type T +/// where an IsDefinitionMatcher<T>() can be constructed. +/// - PolymorphicMatcherWithParam1<ValueEqualsMatcher, int>(42) +/// creates an object that can be used as a Matcher<T> for any type T +/// where a ValueEqualsMatcher<T, int>(42) can be constructed. +template <template <typename T> class MatcherT> +class PolymorphicMatcherWithParam0 { +public: + template <typename T> + operator Matcher<T>() const { + return Matcher<T>(new MatcherT<T>()); + } +}; + +template <template <typename T, typename P1> class MatcherT, + typename P1> +class PolymorphicMatcherWithParam1 { +public: + explicit PolymorphicMatcherWithParam1(const P1 &Param1) + : Param1(Param1) {} + + template <typename T> + operator Matcher<T>() const { + return Matcher<T>(new MatcherT<T, P1>(Param1)); + } + +private: + const P1 Param1; +}; + +template <template <typename T, typename P1, typename P2> class MatcherT, + typename P1, typename P2> +class PolymorphicMatcherWithParam2 { +public: + PolymorphicMatcherWithParam2(const P1 &Param1, const P2 &Param2) + : Param1(Param1), Param2(Param2) {} + + template <typename T> + operator Matcher<T>() const { + return Matcher<T>(new MatcherT<T, P1, P2>(Param1, Param2)); + } + +private: + const P1 Param1; + const P2 Param2; +}; + +/// \brief Matches any instance of the given NodeType. +/// +/// This is useful when a matcher syntactically requires a child matcher, +/// but the context doesn't care. See for example: anything(). +/// +/// FIXME: Alternatively we could also create a IsAMatcher or something +/// that checks that a dyn_cast is possible. This is purely needed for the +/// difference between calling for example: +/// record() +/// and +/// record(SomeMatcher) +/// In the second case we need the correct type we were dyn_cast'ed to in order +/// to get the right type for the inner matcher. In the first case we don't need +/// that, but we use the type conversion anyway and insert a TrueMatcher. +template <typename T> +class TrueMatcher : public SingleNodeMatcherInterface<T> { +public: + virtual bool matchesNode(const T &Node) const { + return true; + } +}; + +/// \brief Provides a MatcherInterface<T> for a Matcher<To> that matches if T is +/// dyn_cast'able into To and the given Matcher<To> matches on the dyn_cast'ed +/// node. +template <typename T, typename To> +class DynCastMatcher : public MatcherInterface<T> { +public: + explicit DynCastMatcher(const Matcher<To> &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + const To *InnerMatchValue = llvm::dyn_cast<To>(&Node); + return InnerMatchValue != NULL && + InnerMatcher.matches(*InnerMatchValue, Finder, Builder); + } + +private: + const Matcher<To> InnerMatcher; +}; + +/// \brief Matcher<T> that wraps an inner Matcher<T> and binds the matched node +/// to an ID if the inner matcher matches on the node. +template <typename T> +class IdMatcher : public MatcherInterface<T> { +public: + /// \brief Creates an IdMatcher that binds to 'ID' if 'InnerMatcher' matches + /// the node. + IdMatcher(StringRef ID, const Matcher<T> &InnerMatcher) + : ID(ID), InnerMatcher(InnerMatcher) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + bool Result = InnerMatcher.matches(Node, Finder, Builder); + if (Result) { + Builder->setBinding(ID, &Node); + } + return Result; + } + +private: + const std::string ID; + const Matcher<T> InnerMatcher; +}; + +/// \brief A Matcher that allows binding the node it matches to an id. +/// +/// BindableMatcher provides a \a bind() method that allows binding the +/// matched node to an id if the match was successful. +template <typename T> +class BindableMatcher : public Matcher<T> { +public: + BindableMatcher(MatcherInterface<T> *Implementation) + : Matcher<T>(Implementation) {} + + /// \brief Returns a matcher that will bind the matched node on a match. + /// + /// The returned matcher is equivalent to this matcher, but will + /// bind the matched node on a match. + Matcher<T> bind(StringRef ID) const { + TOOLING_COMPILE_ASSERT((llvm::is_base_of<Stmt, T>::value || + llvm::is_base_of<Decl, T>::value), + trying_to_bind_unsupported_node_type__only_decl_and_stmt_supported); + return Matcher<T>(new IdMatcher<T>(ID, *this)); + } +}; + +/// \brief Matches nodes of type T that have child nodes of type ChildT for +/// which a specified child matcher matches. +/// +/// ChildT must be an AST base type. +template <typename T, typename ChildT> +class HasMatcher : public MatcherInterface<T> { + TOOLING_COMPILE_ASSERT(IsBaseType<ChildT>::value, + has_only_accepts_base_type_matcher); +public: + explicit HasMatcher(const Matcher<ChildT> &ChildMatcher) + : ChildMatcher(ChildMatcher) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return Finder->matchesChildOf( + Node, ChildMatcher, Builder, + ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses, + ASTMatchFinder::BK_First); + } + + private: + const TypedBaseMatcher<ChildT> ChildMatcher; +}; + +/// \brief Matches nodes of type T that have child nodes of type ChildT for +/// which a specified child matcher matches. ChildT must be an AST base +/// type. +/// As opposed to the HasMatcher, the ForEachMatcher will produce a match +/// for each child that matches. +template <typename T, typename ChildT> +class ForEachMatcher : public MatcherInterface<T> { + TOOLING_COMPILE_ASSERT(IsBaseType<ChildT>::value, + for_each_only_accepts_base_type_matcher); + public: + explicit ForEachMatcher(const Matcher<ChildT> &ChildMatcher) + : ChildMatcher(ChildMatcher) {} + + virtual bool matches(const T& Node, + ASTMatchFinder* Finder, + BoundNodesTreeBuilder* Builder) const { + return Finder->matchesChildOf( + Node, ChildMatcher, Builder, + ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses, + ASTMatchFinder::BK_All); + } + +private: + const TypedBaseMatcher<ChildT> ChildMatcher; +}; + +/// \brief Matches nodes of type T if the given Matcher<T> does not match. +/// +/// Type argument MatcherT is required by PolymorphicMatcherWithParam1 +/// but not actually used. It will always be instantiated with a type +/// convertible to Matcher<T>. +template <typename T, typename MatcherT> +class NotMatcher : public MatcherInterface<T> { +public: + explicit NotMatcher(const Matcher<T> &InnerMatcher) + : InnerMatcher(InnerMatcher) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return !InnerMatcher.matches(Node, Finder, Builder); + } + +private: + const Matcher<T> InnerMatcher; +}; + +/// \brief Matches nodes of type T for which both provided matchers match. +/// +/// Type arguments MatcherT1 and MatcherT2 are required by +/// PolymorphicMatcherWithParam2 but not actually used. They will +/// always be instantiated with types convertible to Matcher<T>. +template <typename T, typename MatcherT1, typename MatcherT2> +class AllOfMatcher : public MatcherInterface<T> { +public: + AllOfMatcher(const Matcher<T> &InnerMatcher1, const Matcher<T> &InnerMatcher2) + : InnerMatcher1(InnerMatcher1), InnerMatcher2(InnerMatcher2) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return InnerMatcher1.matches(Node, Finder, Builder) && + InnerMatcher2.matches(Node, Finder, Builder); + } + +private: + const Matcher<T> InnerMatcher1; + const Matcher<T> InnerMatcher2; +}; + +/// \brief Matches nodes of type T for which at least one of the two provided +/// matchers matches. +/// +/// Type arguments MatcherT1 and MatcherT2 are +/// required by PolymorphicMatcherWithParam2 but not actually +/// used. They will always be instantiated with types convertible to +/// Matcher<T>. +template <typename T, typename MatcherT1, typename MatcherT2> +class AnyOfMatcher : public MatcherInterface<T> { +public: + AnyOfMatcher(const Matcher<T> &InnerMatcher1, const Matcher<T> &InnerMatcher2) + : InnerMatcher1(InnerMatcher1), InnertMatcher2(InnerMatcher2) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return InnerMatcher1.matches(Node, Finder, Builder) || + InnertMatcher2.matches(Node, Finder, Builder); + } + +private: + const Matcher<T> InnerMatcher1; + const Matcher<T> InnertMatcher2; +}; + +/// \brief Creates a Matcher<T> that matches if +/// T is dyn_cast'able into InnerT and all inner matchers match. +/// +/// Returns BindableMatcher, as matchers that use dyn_cast have +/// the same object both to match on and to run submatchers on, +/// so there is no ambiguity with what gets bound. +template<typename T, typename InnerT> +BindableMatcher<T> makeDynCastAllOfComposite( + ArrayRef<const Matcher<InnerT> *> InnerMatchers) { + if (InnerMatchers.empty()) { + Matcher<InnerT> InnerMatcher = makeMatcher(new TrueMatcher<InnerT>); + return BindableMatcher<T>(new DynCastMatcher<T, InnerT>(InnerMatcher)); + } + Matcher<InnerT> InnerMatcher = *InnerMatchers.back(); + for (int i = InnerMatchers.size() - 2; i >= 0; --i) { + InnerMatcher = makeMatcher( + new AllOfMatcher<InnerT, Matcher<InnerT>, Matcher<InnerT> >( + *InnerMatchers[i], InnerMatcher)); + } + return BindableMatcher<T>(new DynCastMatcher<T, InnerT>(InnerMatcher)); +} + +/// \brief Matches nodes of type T that have at least one descendant node of +/// type DescendantT for which the given inner matcher matches. +/// +/// DescendantT must be an AST base type. +template <typename T, typename DescendantT> +class HasDescendantMatcher : public MatcherInterface<T> { + TOOLING_COMPILE_ASSERT(IsBaseType<DescendantT>::value, + has_descendant_only_accepts_base_type_matcher); +public: + explicit HasDescendantMatcher(const Matcher<DescendantT> &DescendantMatcher) + : DescendantMatcher(DescendantMatcher) {} + + virtual bool matches(const T &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return Finder->matchesDescendantOf( + Node, DescendantMatcher, Builder, ASTMatchFinder::BK_First); + } + + private: + const TypedBaseMatcher<DescendantT> DescendantMatcher; +}; + +/// \brief Matches nodes of type T that have at least one descendant node of +/// type DescendantT for which the given inner matcher matches. +/// +/// DescendantT must be an AST base type. +/// As opposed to HasDescendantMatcher, ForEachDescendantMatcher will match +/// for each descendant node that matches instead of only for the first. +template <typename T, typename DescendantT> +class ForEachDescendantMatcher : public MatcherInterface<T> { + TOOLING_COMPILE_ASSERT(IsBaseType<DescendantT>::value, + for_each_descendant_only_accepts_base_type_matcher); + public: + explicit ForEachDescendantMatcher( + const Matcher<DescendantT>& DescendantMatcher) + : DescendantMatcher(DescendantMatcher) {} + + virtual bool matches(const T& Node, + ASTMatchFinder* Finder, + BoundNodesTreeBuilder* Builder) const { + return Finder->matchesDescendantOf(Node, DescendantMatcher, Builder, + ASTMatchFinder::BK_All); + } + +private: + const TypedBaseMatcher<DescendantT> DescendantMatcher; +}; + +/// \brief Matches on nodes that have a getValue() method if getValue() equals +/// the value the ValueEqualsMatcher was constructed with. +template <typename T, typename ValueT> +class ValueEqualsMatcher : public SingleNodeMatcherInterface<T> { + TOOLING_COMPILE_ASSERT((llvm::is_base_of<CharacterLiteral, T>::value || + llvm::is_base_of<CXXBoolLiteralExpr, + T>::value || + llvm::is_base_of<FloatingLiteral, T>::value || + llvm::is_base_of<IntegerLiteral, T>::value), + the_node_must_have_a_getValue_method); +public: + explicit ValueEqualsMatcher(const ValueT &ExpectedValue) + : ExpectedValue(ExpectedValue) {} + + virtual bool matchesNode(const T &Node) const { + return Node.getValue() == ExpectedValue; + } + +private: + const ValueT ExpectedValue; +}; + +template <typename T> +class IsDefinitionMatcher : public SingleNodeMatcherInterface<T> { + TOOLING_COMPILE_ASSERT( + (llvm::is_base_of<TagDecl, T>::value) || + (llvm::is_base_of<VarDecl, T>::value) || + (llvm::is_base_of<FunctionDecl, T>::value), + is_definition_requires_isThisDeclarationADefinition_method); +public: + virtual bool matchesNode(const T &Node) const { + return Node.isThisDeclarationADefinition(); + } +}; + +/// \brief Matches on template instantiations for FunctionDecl, VarDecl or +/// CXXRecordDecl nodes. +template <typename T> +class IsTemplateInstantiationMatcher : public MatcherInterface<T> { + TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, T>::value) || + (llvm::is_base_of<VarDecl, T>::value) || + (llvm::is_base_of<CXXRecordDecl, T>::value), + requires_getTemplateSpecializationKind_method); + public: + virtual bool matches(const T& Node, + ASTMatchFinder* Finder, + BoundNodesTreeBuilder* Builder) const { + return (Node.getTemplateSpecializationKind() == + TSK_ImplicitInstantiation || + Node.getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDefinition); + } +}; + +class IsArrowMatcher : public SingleNodeMatcherInterface<MemberExpr> { +public: + virtual bool matchesNode(const MemberExpr &Node) const { + return Node.isArrow(); + } +}; + +class IsConstQualifiedMatcher + : public SingleNodeMatcherInterface<QualType> { + public: + virtual bool matchesNode(const QualType& Node) const { + return Node.isConstQualified(); + } +}; + +/// \brief A VariadicDynCastAllOfMatcher<SourceT, TargetT> object is a +/// variadic functor that takes a number of Matcher<TargetT> and returns a +/// Matcher<SourceT> that matches TargetT nodes that are matched by all of the +/// given matchers, if SourceT can be dynamically casted into TargetT. +/// +/// For example: +/// const VariadicDynCastAllOfMatcher< +/// Decl, CXXRecordDecl> record; +/// Creates a functor record(...) that creates a Matcher<Decl> given +/// a variable number of arguments of type Matcher<CXXRecordDecl>. +/// The returned matcher matches if the given Decl can by dynamically +/// casted to CXXRecordDecl and all given matchers match. +template <typename SourceT, typename TargetT> +class VariadicDynCastAllOfMatcher + : public llvm::VariadicFunction< + BindableMatcher<SourceT>, Matcher<TargetT>, + makeDynCastAllOfComposite<SourceT, TargetT> > { +public: + VariadicDynCastAllOfMatcher() {} +}; + +} // end namespace internal +} // end namespace ast_matchers +} // end namespace clang + +#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H diff --git a/include/clang/ASTMatchers/ASTMatchersMacros.h b/include/clang/ASTMatchers/ASTMatchersMacros.h new file mode 100644 index 0000000..c68534a --- /dev/null +++ b/include/clang/ASTMatchers/ASTMatchersMacros.h @@ -0,0 +1,224 @@ +//===--- ASTMatchersMacros.h - Structural query framework -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines macros that enable us to define new matchers in a single place. +// Since a matcher is a function which returns a Matcher<T> object, where +// T is the type of the actual implementation of the matcher, the macros allow +// us to write matchers like functions and take care of the definition of the +// class boilerplate. +// +// Note that when you define a matcher with an AST_MATCHER* macro, only the +// function which creates the matcher goes into the current namespace - the +// class that implements the actual matcher, which gets returned by the +// generator function, is put into the 'internal' namespace. This allows us +// to only have the functions (which is all the user cares about) in the +// 'ast_matchers' namespace and hide the boilerplate. +// +// To define a matcher in user code, always put it into the clang::ast_matchers +// namespace and refer to the internal types via the 'internal::': +// +// namespace clang { +// namespace ast_matchers { +// AST_MATCHER_P(MemberExpr, Member, +// internal::Matcher<ValueDecl>, InnerMatcher) { +// return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder); +// } +// } // end namespace ast_matchers +// } // end namespace clang +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H +#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H + +/// \brief AST_MATCHER(Type, DefineMatcher) { ... } +/// defines a zero parameter function named DefineMatcher() that returns a +/// Matcher<Type> object. +/// +/// The code between the curly braces has access to the following variables: +/// +/// Node: the AST node being matched; its type is Type. +/// Finder: an ASTMatchFinder*. +/// Builder: a BoundNodesTreeBuilder*. +/// +/// The code should return true if 'Node' matches. +#define AST_MATCHER(Type, DefineMatcher) \ + namespace internal { \ + class matcher_##DefineMatcher##Matcher \ + : public MatcherInterface<Type> { \ + public: \ + explicit matcher_##DefineMatcher##Matcher() {} \ + virtual bool matches( \ + const Type &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const; \ + }; \ + } \ + inline internal::Matcher<Type> DefineMatcher() { \ + return internal::makeMatcher( \ + new internal::matcher_##DefineMatcher##Matcher()); \ + } \ + inline bool internal::matcher_##DefineMatcher##Matcher::matches( \ + const Type &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const + +/// \brief AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) { ... } +/// defines a single-parameter function named DefineMatcher() that returns a +/// Matcher<Type> object. +/// +/// The code between the curly braces has access to the following variables: +/// +/// Node: the AST node being matched; its type is Type. +/// Param: the parameter passed to the function; its type +/// is ParamType. +/// Finder: an ASTMatchFinder*. +/// Builder: a BoundNodesTreeBuilder*. +/// +/// The code should return true if 'Node' matches. +#define AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) \ + namespace internal { \ + class matcher_##DefineMatcher##Matcher \ + : public MatcherInterface<Type> { \ + public: \ + explicit matcher_##DefineMatcher##Matcher( \ + const ParamType &A##Param) : Param(A##Param) {} \ + virtual bool matches( \ + const Type &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const; \ + private: \ + const ParamType Param; \ + }; \ + } \ + inline internal::Matcher<Type> DefineMatcher(const ParamType &Param) { \ + return internal::makeMatcher( \ + new internal::matcher_##DefineMatcher##Matcher(Param)); \ + } \ + inline bool internal::matcher_##DefineMatcher##Matcher::matches( \ + const Type &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const + +/// \brief AST_MATCHER_P2( +/// Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... } +/// defines a two-parameter function named DefineMatcher() that returns a +/// Matcher<Type> object. +/// +/// The code between the curly braces has access to the following variables: +/// +/// Node: the AST node being matched; its type is Type. +/// Param1, Param2: the parameters passed to the function; their types +/// are ParamType1 and ParamType2. +/// Finder: an ASTMatchFinder*. +/// Builder: a BoundNodesTreeBuilder*. +/// +/// The code should return true if 'Node' matches. +#define AST_MATCHER_P2( \ + Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) \ + namespace internal { \ + class matcher_##DefineMatcher##Matcher \ + : public MatcherInterface<Type> { \ + public: \ + matcher_##DefineMatcher##Matcher( \ + const ParamType1 &A##Param1, const ParamType2 &A##Param2) \ + : Param1(A##Param1), Param2(A##Param2) {} \ + virtual bool matches( \ + const Type &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const; \ + private: \ + const ParamType1 Param1; \ + const ParamType2 Param2; \ + }; \ + } \ + inline internal::Matcher<Type> DefineMatcher( \ + const ParamType1 &Param1, const ParamType2 &Param2) { \ + return internal::makeMatcher( \ + new internal::matcher_##DefineMatcher##Matcher( \ + Param1, Param2)); \ + } \ + inline bool internal::matcher_##DefineMatcher##Matcher::matches( \ + const Type &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const + +/// \brief AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) { ... } +/// defines a single-parameter function named DefineMatcher() that is +/// polymorphic in the return type. +/// +/// The variables are the same as for +/// AST_MATCHER_P, with the addition of NodeType, which specifies the node type +/// of the matcher Matcher<NodeType> returned by the function matcher(). +/// +/// FIXME: Pull out common code with above macro? +#define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) \ + namespace internal { \ + template <typename NodeType, typename ParamT> \ + class matcher_##DefineMatcher##Matcher \ + : public MatcherInterface<NodeType> { \ + public: \ + explicit matcher_##DefineMatcher##Matcher( \ + const ParamType &A##Param) : Param(A##Param) {} \ + virtual bool matches( \ + const NodeType &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const; \ + private: \ + const ParamType Param; \ + }; \ + } \ + inline internal::PolymorphicMatcherWithParam1< \ + internal::matcher_##DefineMatcher##Matcher, \ + ParamType > \ + DefineMatcher(const ParamType &Param) { \ + return internal::PolymorphicMatcherWithParam1< \ + internal::matcher_##DefineMatcher##Matcher, \ + ParamType >(Param); \ + } \ + template <typename NodeType, typename ParamT> \ + bool internal::matcher_##DefineMatcher##Matcher<NodeType, ParamT>::matches( \ + const NodeType &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const + +/// \brief AST_POLYMORPHIC_MATCHER_P2( +/// DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... } +/// defines a two-parameter function named matcher() that is polymorphic in +/// the return type. +/// +/// The variables are the same as for AST_MATCHER_P2, with the +/// addition of NodeType, which specifies the node type of the matcher +/// Matcher<NodeType> returned by the function DefineMatcher(). +#define AST_POLYMORPHIC_MATCHER_P2( \ + DefineMatcher, ParamType1, Param1, ParamType2, Param2) \ + namespace internal { \ + template <typename NodeType, typename ParamT1, typename ParamT2> \ + class matcher_##DefineMatcher##Matcher \ + : public MatcherInterface<NodeType> { \ + public: \ + matcher_##DefineMatcher##Matcher( \ + const ParamType1 &A##Param1, const ParamType2 &A##Param2) \ + : Param1(A##Param1), Param2(A##Param2) {} \ + virtual bool matches( \ + const NodeType &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const; \ + private: \ + const ParamType1 Param1; \ + const ParamType2 Param2; \ + }; \ + } \ + inline internal::PolymorphicMatcherWithParam2< \ + internal::matcher_##DefineMatcher##Matcher, \ + ParamType1, ParamType2 > \ + DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) { \ + return internal::PolymorphicMatcherWithParam2< \ + internal::matcher_##DefineMatcher##Matcher, \ + ParamType1, ParamType2 >( \ + Param1, Param2); \ + } \ + template <typename NodeType, typename ParamT1, typename ParamT2> \ + bool internal::matcher_##DefineMatcher##Matcher< \ + NodeType, ParamT1, ParamT2>::matches( \ + const NodeType &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const + +#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h index 9ec27ce..7f50ee3 100644 --- a/include/clang/Analysis/Analyses/FormatString.h +++ b/include/clang/Analysis/Analyses/FormatString.h @@ -175,6 +175,7 @@ public: switch (kind) { case PrintErrno: assert(IsPrintf); + return false; case PercentArg: return false; default: @@ -200,7 +201,7 @@ protected: Kind kind; }; -class ArgTypeResult { +class ArgType { public: enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy, AnyCharTy, CStrTy, WCStrTy, WIntTy }; @@ -208,26 +209,26 @@ private: const Kind K; QualType T; const char *Name; - ArgTypeResult(bool) : K(InvalidTy), Name(0) {} + bool Ptr; public: - ArgTypeResult(Kind k = UnknownTy) : K(k), Name(0) {} - ArgTypeResult(Kind k, const char *n) : K(k), Name(n) {} - ArgTypeResult(QualType t) : K(SpecificTy), T(t), Name(0) {} - ArgTypeResult(QualType t, const char *n) : K(SpecificTy), T(t), Name(n) {} - ArgTypeResult(CanQualType t) : K(SpecificTy), T(t), Name(0) {} - - static ArgTypeResult Invalid() { return ArgTypeResult(true); } + ArgType(Kind k = UnknownTy, const char *n = 0) : K(k), Name(n), Ptr(false) {} + ArgType(QualType t, const char *n = 0) + : K(SpecificTy), T(t), Name(n), Ptr(false) {} + ArgType(CanQualType t) : K(SpecificTy), T(t), Name(0), Ptr(false) {} + static ArgType Invalid() { return ArgType(InvalidTy); } bool isValid() const { return K != InvalidTy; } - const QualType *getSpecificType() const { - return K == SpecificTy ? &T : 0; + /// Create an ArgType which corresponds to the type pointer to A. + static ArgType PtrTo(const ArgType& A) { + assert(A.K >= InvalidTy && "ArgType cannot be pointer to invalid/unknown"); + ArgType Res = A; + Res.Ptr = true; + return Res; } bool matchesType(ASTContext &C, QualType argTy) const; - bool matchesAnyObjCObjectRef() const { return K == ObjCPointerTy; } - QualType getRepresentativeType(ASTContext &C) const; std::string getRepresentativeTypeName(ASTContext &C) const; @@ -278,7 +279,7 @@ public: return length + UsesDotPrefix; } - ArgTypeResult getArgType(ASTContext &Ctx) const; + ArgType getArgType(ASTContext &Ctx) const; void toString(raw_ostream &os) const; @@ -354,6 +355,10 @@ public: bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const; bool hasStandardLengthConversionCombination() const; + + /// For a TypedefType QT, if it is a named integer type such as size_t, + /// assign the appropriate value to LM and return true. + static bool namedTypeToLengthModifier(QualType QT, LengthModifier &LM); }; } // end analyze_format_string namespace @@ -387,7 +392,7 @@ public: } }; -using analyze_format_string::ArgTypeResult; +using analyze_format_string::ArgType; using analyze_format_string::LengthModifier; using analyze_format_string::OptionalAmount; using analyze_format_string::OptionalFlag; @@ -462,7 +467,7 @@ public: /// will return null if the format specifier does not have /// a matching data argument or the matching argument matches /// more than one type. - ArgTypeResult getArgType(ASTContext &Ctx, bool IsObjCLiteral) const; + ArgType getArgType(ASTContext &Ctx, bool IsObjCLiteral) const; const OptionalFlag &hasThousandsGrouping() const { return HasThousandsGrouping; @@ -516,35 +521,11 @@ public: } }; -using analyze_format_string::ArgTypeResult; +using analyze_format_string::ArgType; using analyze_format_string::LengthModifier; using analyze_format_string::OptionalAmount; using analyze_format_string::OptionalFlag; -class ScanfArgTypeResult : public ArgTypeResult { -public: - enum Kind { UnknownTy, InvalidTy, CStrTy, WCStrTy, PtrToArgTypeResultTy }; -private: - Kind K; - ArgTypeResult A; - const char *Name; - QualType getRepresentativeType(ASTContext &C) const; -public: - ScanfArgTypeResult(Kind k = UnknownTy, const char* n = 0) : K(k), Name(n) {} - ScanfArgTypeResult(ArgTypeResult a, const char *n = 0) - : K(PtrToArgTypeResultTy), A(a), Name(n) { - assert(A.isValid()); - } - - static ScanfArgTypeResult Invalid() { return ScanfArgTypeResult(InvalidTy); } - - bool isValid() const { return K != InvalidTy; } - - bool matchesType(ASTContext& C, QualType argTy) const; - - std::string getRepresentativeTypeName(ASTContext& C) const; -}; - class ScanfSpecifier : public analyze_format_string::FormatSpecifier { OptionalFlag SuppressAssignment; // '*' public: @@ -573,7 +554,7 @@ public: return CS.consumesDataArgument() && !SuppressAssignment; } - ScanfArgTypeResult getArgType(ASTContext &Ctx) const; + ArgType getArgType(ASTContext &Ctx) const; bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx); diff --git a/include/clang/Analysis/Analyses/ThreadSafety.h b/include/clang/Analysis/Analyses/ThreadSafety.h index 26e258d..742cc04 100644 --- a/include/clang/Analysis/Analyses/ThreadSafety.h +++ b/include/clang/Analysis/Analyses/ThreadSafety.h @@ -60,7 +60,8 @@ enum AccessKind { enum LockErrorKind { LEK_LockedSomeLoopIterations, LEK_LockedSomePredecessors, - LEK_LockedAtEndOfFunction + LEK_LockedAtEndOfFunction, + LEK_NotLockedAtEndOfFunction }; /// Handler class for thread safety warnings. @@ -123,11 +124,11 @@ public: /// Warn when a protected operation occurs while the specific mutex protecting /// the operation is not locked. - /// \param LockName -- A StringRef name for the lock expression, to be printed - /// in the error message. /// \param D -- The decl for the protected variable or function /// \param POK -- The kind of protected operation (e.g. variable access) - /// \param AK -- The kind of access (i.e. read or write) that occurred + /// \param LockName -- A StringRef name for the lock expression, to be printed + /// in the error message. + /// \param LK -- The kind of access (i.e. read or write) that occurred /// \param Loc -- The location of the protected operation. virtual void handleMutexNotHeld(const NamedDecl *D, ProtectedOperationKind POK, Name LockName, diff --git a/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h index 4ee6698..45ce4de 100644 --- a/include/clang/Analysis/Analyses/UninitializedValues.h +++ b/include/clang/Analysis/Analyses/UninitializedValues.h @@ -15,6 +15,8 @@ #ifndef LLVM_CLANG_UNINIT_VALS_H #define LLVM_CLANG_UNINIT_VALS_H +#include "llvm/ADT/SmallVector.h" + namespace clang { class AnalysisDeclContext; @@ -23,15 +25,67 @@ class DeclContext; class Expr; class VarDecl; +/// A use of a variable, which might be uninitialized. +class UninitUse { +public: + struct Branch { + const Stmt *Terminator; + unsigned Output; + }; + +private: + /// The expression which uses this variable. + const Expr *User; + + /// Does this use always see an uninitialized value? + bool AlwaysUninit; + + /// This use is always uninitialized if it occurs after any of these branches + /// is taken. + llvm::SmallVector<Branch, 2> UninitBranches; + +public: + UninitUse(const Expr *User, bool AlwaysUninit) : + User(User), AlwaysUninit(AlwaysUninit) {} + + void addUninitBranch(Branch B) { + UninitBranches.push_back(B); + } + + /// Get the expression containing the uninitialized use. + const Expr *getUser() const { return User; } + + /// The kind of uninitialized use. + enum Kind { + /// The use might be uninitialized. + Maybe, + /// The use is uninitialized whenever a certain branch is taken. + Sometimes, + /// The use is always uninitialized. + Always + }; + + /// Get the kind of uninitialized use. + Kind getKind() const { + return AlwaysUninit ? Always : + !branch_empty() ? Sometimes : Maybe; + } + + typedef llvm::SmallVectorImpl<Branch>::const_iterator branch_iterator; + /// Branches which inevitably result in the variable being used uninitialized. + branch_iterator branch_begin() const { return UninitBranches.begin(); } + branch_iterator branch_end() const { return UninitBranches.end(); } + bool branch_empty() const { return UninitBranches.empty(); } +}; + class UninitVariablesHandler { public: UninitVariablesHandler() {} virtual ~UninitVariablesHandler(); /// Called when the uninitialized variable is used at the given expression. - virtual void handleUseOfUninitVariable(const Expr *ex, - const VarDecl *vd, - bool isAlwaysUninit) {} + virtual void handleUseOfUninitVariable(const VarDecl *vd, + const UninitUse &use) {} /// Called when the uninitialized variable analysis detects the /// idiom 'int x = x'. All other uses of 'x' within the initializer diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h index 6b6f8ef..46b4e93 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisContext.h @@ -38,6 +38,7 @@ class PseudoConstantAnalysis; class ImplicitParamDecl; class LocationContextManager; class StackFrameContext; +class BlockInvocationContext; class AnalysisDeclContextManager; class LocationContext; @@ -73,9 +74,6 @@ class AnalysisDeclContext { const Decl *D; - // TranslationUnit is NULL if we don't have multiple translation units. - idx::TranslationUnit *TU; - OwningPtr<CFG> cfg, completeCFG; OwningPtr<CFGStmtMap> cfgStmtMap; @@ -98,12 +96,10 @@ class AnalysisDeclContext { public: AnalysisDeclContext(AnalysisDeclContextManager *Mgr, - const Decl *D, - idx::TranslationUnit *TU); + const Decl *D); AnalysisDeclContext(AnalysisDeclContextManager *Mgr, const Decl *D, - idx::TranslationUnit *TU, const CFG::BuildOptions &BuildOptions); ~AnalysisDeclContext(); @@ -111,8 +107,6 @@ public: ASTContext &getASTContext() { return D->getASTContext(); } const Decl *getDecl() const { return D; } - idx::TranslationUnit *getTranslationUnit() const { return TU; } - /// Return the build options used to construct the CFG. CFG::BuildOptions &getCFGBuildOptions() { return cfgBuildOptions; @@ -169,6 +163,11 @@ public: const Stmt *S, const CFGBlock *Blk, unsigned Idx); + + const BlockInvocationContext * + getBlockInvocationContext(const LocationContext *parent, + const BlockDecl *BD, + const void *ContextData); /// Return the specified analysis object, lazily running the analysis if /// necessary. Return NULL if the analysis could not run. @@ -212,10 +211,6 @@ public: AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; } - idx::TranslationUnit *getTranslationUnit() const { - return Ctx->getTranslationUnit(); - } - const LocationContext *getParent() const { return Parent; } bool isParentOf(const LocationContext *LC) const; @@ -238,8 +233,6 @@ public: } const StackFrameContext *getCurrentStackFrame() const; - const StackFrameContext * - getStackFrameForDeclContext(const DeclContext *DC) const; virtual void Profile(llvm::FoldingSetNodeID &ID) = 0; @@ -318,27 +311,32 @@ public: }; class BlockInvocationContext : public LocationContext { - // FIXME: Add back context-sensivity (we don't want libAnalysis to know - // about MemRegion). const BlockDecl *BD; + + // FIXME: Come up with a more type-safe way to model context-sensitivity. + const void *ContextData; friend class LocationContextManager; BlockInvocationContext(AnalysisDeclContext *ctx, const LocationContext *parent, - const BlockDecl *bd) - : LocationContext(Block, ctx, parent), BD(bd) {} + const BlockDecl *bd, const void *contextData) + : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {} public: ~BlockInvocationContext() {} const BlockDecl *getBlockDecl() const { return BD; } + + const void *getContextData() const { return ContextData; } void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx, - const LocationContext *parent, const BlockDecl *bd) { + const LocationContext *parent, const BlockDecl *bd, + const void *contextData) { ProfileCommon(ID, Block, ctx, parent, bd); + ID.AddPointer(contextData); } static bool classof(const LocationContext *Ctx) { @@ -359,6 +357,12 @@ public: const ScopeContext *getScope(AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s); + + const BlockInvocationContext * + getBlockInvocationContext(AnalysisDeclContext *ctx, + const LocationContext *parent, + const BlockDecl *BD, + const void *ContextData); /// Discard all previously created LocationContext objects. void clear(); @@ -383,7 +387,7 @@ public: ~AnalysisDeclContextManager(); - AnalysisDeclContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0); + AnalysisDeclContext *getContext(const Decl *D); bool getUseUnoptimizedCFG() const { return !cfgBuildOptions.PruneTriviallyFalseEdges; @@ -402,9 +406,8 @@ public: } // Get the top level stack frame. - const StackFrameContext *getStackFrame(Decl const *D, - idx::TranslationUnit *TU) { - return LocContexts.getStackFrame(getContext(D, TU), 0, 0, 0, 0); + const StackFrameContext *getStackFrame(const Decl *D) { + return LocContexts.getStackFrame(getContext(D), 0, 0, 0, 0); } // Get a stack frame with parent. @@ -416,7 +419,6 @@ public: return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx); } - /// Discard all previously created AnalysisDeclContexts. void clear(); diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index 27b22b8..4d087e7 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -21,10 +21,10 @@ #include "llvm/Support/Casting.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/BitVector.h" #include "clang/AST/Stmt.h" #include "clang/Analysis/Support/BumpVector.h" #include "clang/Basic/SourceLocation.h" +#include <bitset> #include <cassert> #include <iterator> @@ -277,6 +277,7 @@ class CFGBlock { typedef std::reverse_iterator<ImplTy::const_iterator> const_iterator; typedef ImplTy::iterator reverse_iterator; typedef ImplTy::const_iterator const_reverse_iterator; + typedef ImplTy::const_reference const_reference; void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); } reverse_iterator insert(reverse_iterator I, size_t Cnt, CFGElement E, @@ -284,8 +285,8 @@ class CFGBlock { return Impl.insert(I, Cnt, E, C); } - CFGElement front() const { return Impl.back(); } - CFGElement back() const { return Impl.front(); } + const_reference front() const { return Impl.back(); } + const_reference back() const { return Impl.front(); } iterator begin() { return Impl.rbegin(); } iterator end() { return Impl.rend(); } @@ -558,7 +559,7 @@ public: //===--------------------------------------------------------------------===// class BuildOptions { - llvm::BitVector alwaysAddMask; + std::bitset<Stmt::lastStmtConstant> alwaysAddMask; public: typedef llvm::DenseMap<const Stmt *, const CFGBlock*> ForcedBlkExprs; ForcedBlkExprs **forcedBlkExprs; @@ -583,8 +584,7 @@ public: } BuildOptions() - : alwaysAddMask(Stmt::lastStmtConstant, false) - ,forcedBlkExprs(0), PruneTriviallyFalseEdges(true) + : forcedBlkExprs(0), PruneTriviallyFalseEdges(true) ,AddEHEdges(false) ,AddInitializers(false) ,AddImplicitDtors(false) {} diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h index 9b68073..509de7b 100644 --- a/include/clang/Analysis/CallGraph.h +++ b/include/clang/Analysis/CallGraph.h @@ -26,7 +26,7 @@ namespace clang { class CallGraphNode; -/// \class The AST-based call graph. +/// \brief The AST-based call graph. /// /// The call graph extends itself with the given declarations by implementing /// the recursive AST visitor, which constructs the graph by visiting the given @@ -102,7 +102,8 @@ public: void dump() const; void viewGraph() const; - /// Part of recursive declaration visitation. + /// Part of recursive declaration visitation. We recursively visit all the + /// Declarations to collect the root functions. bool VisitFunctionDecl(FunctionDecl *FD) { // We skip function template definitions, as their semantics is // only determined when they are instantiated. @@ -121,6 +122,11 @@ public: return true; } + // We are only collecting the declarations, so do not step into the bodies. + bool TraverseStmt(Stmt *S) { return true; } + + bool shouldWalkTypesOfTypeLocs() const { return false; } + private: /// \brief Add the given declaration to the call graph. void addNodeForDecl(Decl *D, bool IsGlobal); diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index aa7a33c..5de06cd 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -40,30 +40,36 @@ public: BlockEntranceKind, BlockExitKind, PreStmtKind, + PreStmtPurgeDeadSymbolsKind, + PostStmtPurgeDeadSymbolsKind, PostStmtKind, PreLoadKind, PostLoadKind, PreStoreKind, PostStoreKind, - PostPurgeDeadSymbolsKind, PostConditionKind, PostLValueKind, + MinPostStmtKind = PostStmtKind, + MaxPostStmtKind = PostLValueKind, PostInitializerKind, CallEnterKind, - CallExitKind, - MinPostStmtKind = PostStmtKind, - MaxPostStmtKind = CallExitKind, + CallExitBeginKind, + CallExitEndKind, + PreImplicitCallKind, + PostImplicitCallKind, + MinImplicitCallKind = PreImplicitCallKind, + MaxImplicitCallKind = PostImplicitCallKind, EpsilonKind}; private: - llvm::PointerIntPair<const void *, 2, unsigned> Data1; + const void *Data1; llvm::PointerIntPair<const void *, 2, unsigned> Data2; // The LocationContext could be NULL to allow ProgramPoint to be used in // context insensitive analysis. llvm::PointerIntPair<const LocationContext *, 2, unsigned> L; - const ProgramPointTag *Tag; + llvm::PointerIntPair<const ProgramPointTag *, 2, unsigned> Tag; ProgramPoint(); @@ -72,10 +78,10 @@ protected: Kind k, const LocationContext *l, const ProgramPointTag *tag = 0) - : Data1(P, ((unsigned) k) & 0x3), - Data2(0, (((unsigned) k) >> 2) & 0x3), - L(l, (((unsigned) k) >> 4) & 0x3), - Tag(tag) { + : Data1(P), + Data2(0, (((unsigned) k) >> 0) & 0x3), + L(l, (((unsigned) k) >> 2) & 0x3), + Tag(tag, (((unsigned) k) >> 4) & 0x3) { assert(getKind() == k); assert(getLocationContext() == l); assert(getData1() == P); @@ -86,13 +92,13 @@ protected: Kind k, const LocationContext *l, const ProgramPointTag *tag = 0) - : Data1(P1, ((unsigned) k) & 0x3), - Data2(P2, (((unsigned) k) >> 2) & 0x3), - L(l, (((unsigned) k) >> 4) & 0x3), - Tag(tag) {} + : Data1(P1), + Data2(P2, (((unsigned) k) >> 0) & 0x3), + L(l, (((unsigned) k) >> 2) & 0x3), + Tag(tag, (((unsigned) k) >> 4) & 0x3) {} protected: - const void *getData1() const { return Data1.getPointer(); } + const void *getData1() const { return Data1; } const void *getData2() const { return Data2.getPointer(); } void setData2(const void *d) { Data2.setPointer(d); } @@ -105,15 +111,23 @@ public: } Kind getKind() const { - unsigned x = L.getInt(); + unsigned x = Tag.getInt(); x <<= 2; - x |= Data2.getInt(); + x |= L.getInt(); x <<= 2; - x |= Data1.getInt(); + x |= Data2.getInt(); return (Kind) x; } - const ProgramPointTag *getTag() const { return Tag; } + /// \brief Is this a program point corresponding to purge/removal of dead + /// symbols and bindings. + bool isPurgeKind() { + Kind K = getKind(); + return (K == PostStmtPurgeDeadSymbolsKind || + K == PreStmtPurgeDeadSymbolsKind); + } + + const ProgramPointTag *getTag() const { return Tag.getPointer(); } const LocationContext *getLocationContext() const { return L.getPointer(); @@ -147,7 +161,7 @@ public: ID.AddPointer(getData1()); ID.AddPointer(getData2()); ID.AddPointer(getLocationContext()); - ID.AddPointer(Tag); + ID.AddPointer(getTag()); } static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K, @@ -304,7 +318,7 @@ public: } }; -/// \class Represents a program point after a store evaluation. +/// \brief Represents a program point after a store evaluation. class PostStore : public PostStmt { public: /// Construct the post store point. @@ -340,14 +354,29 @@ public: } }; -class PostPurgeDeadSymbols : public PostStmt { +/// Represents a point after we ran remove dead bindings BEFORE +/// processing the given statement. +class PreStmtPurgeDeadSymbols : public StmtPoint { public: - PostPurgeDeadSymbols(const Stmt *S, const LocationContext *L, + PreStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag = 0) - : PostStmt(S, PostPurgeDeadSymbolsKind, L, tag) {} + : StmtPoint(S, 0, PreStmtPurgeDeadSymbolsKind, L, tag) { } static bool classof(const ProgramPoint* Location) { - return Location->getKind() == PostPurgeDeadSymbolsKind; + return Location->getKind() == PreStmtPurgeDeadSymbolsKind; + } +}; + +/// Represents a point after we ran remove dead bindings AFTER +/// processing the given statement. +class PostStmtPurgeDeadSymbols : public StmtPoint { +public: + PostStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L, + const ProgramPointTag *tag = 0) + : StmtPoint(S, 0, PostStmtPurgeDeadSymbolsKind, L, tag) { } + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PostStmtPurgeDeadSymbolsKind; } }; @@ -383,11 +412,60 @@ public: } }; -class CallEnter : public StmtPoint { +/// Represents an implicit call event. +/// +/// The nearest statement is provided for diagnostic purposes. +class ImplicitCallPoint : public ProgramPoint { +public: + ImplicitCallPoint(const Decl *D, SourceLocation Loc, Kind K, + const LocationContext *L, const ProgramPointTag *Tag) + : ProgramPoint(Loc.getPtrEncoding(), D, K, L, Tag) {} + + const Decl *getDecl() const { return static_cast<const Decl *>(getData2()); } + SourceLocation getLocation() const { + return SourceLocation::getFromPtrEncoding(getData1()); + } + + static bool classof(const ProgramPoint *Location) { + return Location->getKind() >= MinImplicitCallKind && + Location->getKind() <= MaxImplicitCallKind; + } +}; + +/// Represents a program point just before an implicit call event. +/// +/// Explicit calls will appear as PreStmt program points. +class PreImplicitCall : public ImplicitCallPoint { +public: + PreImplicitCall(const Decl *D, SourceLocation Loc, + const LocationContext *L, const ProgramPointTag *Tag = 0) + : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag) {} + + static bool classof(const ProgramPoint *Location) { + return Location->getKind() == PreImplicitCallKind; + } +}; + +/// Represents a program point just after an implicit call event. +/// +/// Explicit calls will appear as PostStmt program points. +class PostImplicitCall : public ImplicitCallPoint { +public: + PostImplicitCall(const Decl *D, SourceLocation Loc, + const LocationContext *L, const ProgramPointTag *Tag = 0) + : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {} + + static bool classof(const ProgramPoint *Location) { + return Location->getKind() == PostImplicitCallKind; + } +}; + +/// Represents a point when we begin processing an inlined call. +class CallEnter : public ProgramPoint { public: CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx, const LocationContext *callerCtx) - : StmtPoint(stmt, calleeCtx, CallEnterKind, callerCtx, 0) {} + : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, 0) {} const Stmt *getCallExpr() const { return static_cast<const Stmt *>(getData1()); @@ -402,14 +480,41 @@ public: } }; -class CallExit : public StmtPoint { +/// Represents a point when we start the call exit sequence (for inlined call). +/// +/// The call exit is simulated with a sequence of nodes, which occur between +/// CallExitBegin and CallExitEnd. The following operations occur between the +/// two program points: +/// - CallExitBegin +/// - Bind the return value +/// - Run Remove dead bindings (to clean up the dead symbols from the callee). +/// - CallExitEnd +class CallExitBegin : public ProgramPoint { +public: + // CallExitBegin uses the callee's location context. + CallExitBegin(const StackFrameContext *L) + : ProgramPoint(0, CallExitBeginKind, L, 0) {} + + static bool classof(const ProgramPoint *Location) { + return Location->getKind() == CallExitBeginKind; + } +}; + +/// Represents a point when we finish the call exit sequence (for inlined call). +/// \sa CallExitBegin +class CallExitEnd : public ProgramPoint { public: - // CallExit uses the callee's location context. - CallExit(const Stmt *S, const LocationContext *L) - : StmtPoint(S, 0, CallExitKind, L, 0) {} + // CallExitEnd uses the caller's location context. + CallExitEnd(const StackFrameContext *CalleeCtx, + const LocationContext *CallerCtx) + : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, 0) {} + + const StackFrameContext *getCalleeContext() const { + return static_cast<const StackFrameContext *>(getData1()); + } static bool classof(const ProgramPoint *Location) { - return Location->getKind() == CallExitKind; + return Location->getKind() == CallExitEndKind; } }; diff --git a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h index 97eb287..c510e20 100644 --- a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h +++ b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h @@ -69,6 +69,7 @@ public: DISPATCH_CASE(Field) DISPATCH_CASE(UsingDirective) DISPATCH_CASE(Using) + DISPATCH_CASE(NamespaceAlias) default: llvm_unreachable("Subtype of ScopedDecl not handled."); } @@ -90,6 +91,7 @@ public: DEFAULT_DISPATCH(ObjCCategory) DEFAULT_DISPATCH(UsingDirective) DEFAULT_DISPATCH(Using) + DEFAULT_DISPATCH(NamespaceAlias) void VisitCXXRecordDecl(CXXRecordDecl *D) { static_cast<ImplClass*>(this)->VisitRecordDecl(D); diff --git a/include/clang/Basic/ABI.h b/include/clang/Basic/ABI.h index 018f500..fecf613 100644 --- a/include/clang/Basic/ABI.h +++ b/include/clang/Basic/ABI.h @@ -6,10 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// These enums/classes describe ABI related information about constructors, -// destructors and thunks. -// +/// +/// \file +/// \brief Enums/classes describing ABI related information about constructors, +/// destructors and thunks. +/// //===----------------------------------------------------------------------===// #ifndef CLANG_BASIC_ABI_H @@ -19,27 +20,27 @@ namespace clang { -/// CXXCtorType - C++ constructor types +/// \brief C++ constructor types. enum CXXCtorType { - Ctor_Complete, // Complete object ctor - Ctor_Base, // Base object ctor - Ctor_CompleteAllocating // Complete object allocating ctor + Ctor_Complete, ///< Complete object ctor + Ctor_Base, ///< Base object ctor + Ctor_CompleteAllocating ///< Complete object allocating ctor }; -/// CXXDtorType - C++ destructor types +/// \brief C++ destructor types. enum CXXDtorType { - Dtor_Deleting, // Deleting dtor - Dtor_Complete, // Complete object dtor - Dtor_Base // Base object dtor + Dtor_Deleting, ///< Deleting dtor + Dtor_Complete, ///< Complete object dtor + Dtor_Base ///< Base object dtor }; -/// ReturnAdjustment - A return adjustment. +/// \brief A return adjustment. struct ReturnAdjustment { - /// NonVirtual - The non-virtual adjustment from the derived object to its + /// \brief The non-virtual adjustment from the derived object to its /// nearest virtual base. int64_t NonVirtual; - /// VBaseOffsetOffset - The offset (in bytes), relative to the address point + /// \brief The offset (in bytes), relative to the address point /// of the virtual base class offset. int64_t VBaseOffsetOffset; @@ -63,13 +64,13 @@ struct ReturnAdjustment { } }; -/// ThisAdjustment - A 'this' pointer adjustment. +/// \brief A \c this pointer adjustment. struct ThisAdjustment { - /// NonVirtual - The non-virtual adjustment from the derived object to its + /// \brief The non-virtual adjustment from the derived object to its /// nearest virtual base. int64_t NonVirtual; - /// VCallOffsetOffset - The offset (in bytes), relative to the address point, + /// \brief The offset (in bytes), relative to the address point, /// of the virtual call offset. int64_t VCallOffsetOffset; @@ -93,13 +94,13 @@ struct ThisAdjustment { } }; -/// ThunkInfo - The 'this' pointer adjustment as well as an optional return +/// \brief The \c this pointer adjustment as well as an optional return /// adjustment for a thunk. struct ThunkInfo { - /// This - The 'this' pointer adjustment. + /// \brief The \c this pointer adjustment. ThisAdjustment This; - /// Return - The return adjustment. + /// \brief The return adjustment. ReturnAdjustment Return; ThunkInfo() { } diff --git a/include/clang/Basic/AddressSpaces.h b/include/clang/Basic/AddressSpaces.h index d44a9c3b..4b1cea5 100644 --- a/include/clang/Basic/AddressSpaces.h +++ b/include/clang/Basic/AddressSpaces.h @@ -6,10 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file provides definitions for the various language-specific address -// spaces. -// +/// +/// \file +/// \brief Provides definitions for the various language-specific address +/// spaces. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_ADDRESSSPACES_H @@ -19,8 +20,9 @@ namespace clang { namespace LangAS { -/// This enum defines the set of possible language-specific address spaces. -/// It uses a high starting offset so as not to conflict with any address +/// \brief Defines the set of possible language-specific address spaces. +/// +/// This uses a high starting offset so as not to conflict with any address /// space used by a target. enum ID { Offset = 0xFFFF00, @@ -29,6 +31,10 @@ enum ID { opencl_local, opencl_constant, + cuda_device, + cuda_constant, + cuda_shared, + Last, Count = Last-Offset }; diff --git a/include/clang/Basic/AllDiagnostics.h b/include/clang/Basic/AllDiagnostics.h index 7e77435..7304c8f 100644 --- a/include/clang/Basic/AllDiagnostics.h +++ b/include/clang/Basic/AllDiagnostics.h @@ -6,16 +6,17 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file includes all the separate Diagnostic headers & some related -// helpers. -// +/// +/// \file +/// \brief Includes all the separate Diagnostic headers & some related helpers. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_ALL_DIAGNOSTICS_H #define LLVM_CLANG_ALL_DIAGNOSTICS_H #include "clang/AST/ASTDiagnostic.h" +#include "clang/AST/CommentDiagnostic.h" #include "clang/Analysis/AnalysisDiagnostic.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Frontend/FrontendDiagnostic.h" diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index e8e0f35..99180e4 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -80,23 +80,40 @@ class EnumArgument<string name, string type, list<string> values, list<string> Enums = enums; } +// This handles one spelling of an attribute. +class Spelling<string name, string variety> { + string Name = name; + string Variety = variety; +} + +class GNU<string name> : Spelling<name, "GNU">; +class Declspec<string name> : Spelling<name, "Declspec">; +class CXX11<string namespace, string name> : Spelling<name, "CXX11"> { + string Namespace = namespace; +} + class Attr { // The various ways in which an attribute can be spelled in source - list<string> Spellings; + list<Spelling> Spellings; // The things to which an attribute can appertain list<AttrSubject> Subjects; // The arguments allowed on an attribute list<Argument> Args = []; - // The namespaces in which the attribute appears in C++0x attributes. - // The attribute will not be permitted in C++0x attribute-specifiers if - // this is empty; the empty string can be used as a namespace. - list<string> Namespaces = []; // Set to true for attributes with arguments which require delayed parsing. bit LateParsed = 0; + // Set to false to prevent an attribute from being propagated from a template + // to the instantiation. + bit Clone = 1; // Set to true for attributes which must be instantiated within templates bit TemplateDependent = 0; + // Set to true for attributes that have a corresponding AST node. + bit ASTNode = 1; // Set to true for attributes which have handler in Sema. bit SemaHandler = 1; + // Set to true for attributes that are completely ignored. + bit Ignored = 0; + // Set to true if each of the spellings is a distinct attribute. + bit DistinctSpellings = 0; // Any additional text that should be included verbatim in the class. code AdditionalMembers = [{}]; } @@ -112,16 +129,21 @@ class InheritableParamAttr : InheritableAttr; // Attributes begin here // +def AddressSpace : Attr { + let Spellings = [GNU<"address_space">]; + let Args = [IntArgument<"AddressSpace">]; + let ASTNode = 0; +} + def Alias : InheritableAttr { - let Spellings = ["alias"]; + let Spellings = [GNU<"alias">]; let Args = [StringArgument<"Aliasee">]; } def Aligned : InheritableAttr { - let Spellings = ["aligned"]; + let Spellings = [GNU<"aligned">, GNU<"align">]; let Subjects = [NonBitField, NormalVar, Tag]; - let Args = [AlignedArgument<"Alignment">]; - let Namespaces = ["", "std"]; + let Args = [AlignedArgument<"Alignment">, BoolArgument<"IsMSDeclSpec">]; } def AlignMac68k : InheritableAttr { @@ -129,16 +151,27 @@ def AlignMac68k : InheritableAttr { let SemaHandler = 0; } +def AllocSize : Attr { + let Spellings = [GNU<"alloc_size">]; + let Args = [VariadicUnsignedArgument<"Args">]; +} + def AlwaysInline : InheritableAttr { - let Spellings = ["always_inline"]; + let Spellings = [GNU<"always_inline">]; +} + +def TLSModel : InheritableAttr { + let Spellings = [GNU<"tls_model">]; + let Subjects = [Var]; + let Args = [StringArgument<"Model">]; } def AnalyzerNoReturn : InheritableAttr { - let Spellings = ["analyzer_noreturn"]; + let Spellings = [GNU<"analyzer_noreturn">]; } def Annotate : InheritableParamAttr { - let Spellings = ["annotate"]; + let Spellings = [GNU<"annotate">]; let Args = [StringArgument<"Annotation">]; } @@ -149,7 +182,7 @@ def AsmLabel : InheritableAttr { } def Availability : InheritableAttr { - let Spellings = ["availability"]; + let Spellings = [GNU<"availability">]; let Args = [IdentifierArgument<"platform">, VersionArgument<"introduced">, VersionArgument<"deprecated">, VersionArgument<"obsoleted">, BoolArgument<"unavailable">, StringArgument<"message">]; @@ -163,18 +196,25 @@ def Availability : InheritableAttr { } def Blocks : InheritableAttr { - let Spellings = ["blocks"]; + let Spellings = [GNU<"blocks">]; let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>]; } +def Bounded : Attr { + let Spellings = [GNU<"bounded">]; + let ASTNode = 0; + let SemaHandler = 0; + let Ignored = 1; +} + def CarriesDependency : InheritableParamAttr { - let Spellings = ["carries_dependency"]; + let Spellings = [GNU<"carries_dependency">, CXX11<"","carries_dependency">, + CXX11<"std","carries_dependency">]; let Subjects = [ParmVar, Function]; - let Namespaces = ["", "std"]; } def CDecl : InheritableAttr { - let Spellings = ["cdecl", "__cdecl"]; + let Spellings = [GNU<"cdecl">, GNU<"__cdecl">]; } // cf_audited_transfer indicates that the given function has been @@ -182,7 +222,7 @@ def CDecl : InheritableAttr { // cf_returns_retained attributes. It is generally applied by // '#pragma clang arc_cf_code_audited' rather than explicitly. def CFAuditedTransfer : InheritableAttr { - let Spellings = ["cf_audited_transfer"]; + let Spellings = [GNU<"cf_audited_transfer">]; let Subjects = [Function]; } @@ -190,133 +230,151 @@ def CFAuditedTransfer : InheritableAttr { // It indicates that the function has unknown or unautomatable // transfer semantics. def CFUnknownTransfer : InheritableAttr { - let Spellings = ["cf_unknown_transfer"]; + let Spellings = [GNU<"cf_unknown_transfer">]; let Subjects = [Function]; } +def CFReturnsAutoreleased : Attr { + let Spellings = [GNU<"cf_returns_autoreleased">]; + let ASTNode = 0; +} + def CFReturnsRetained : InheritableAttr { - let Spellings = ["cf_returns_retained"]; + let Spellings = [GNU<"cf_returns_retained">]; let Subjects = [ObjCMethod, Function]; } def CFReturnsNotRetained : InheritableAttr { - let Spellings = ["cf_returns_not_retained"]; + let Spellings = [GNU<"cf_returns_not_retained">]; let Subjects = [ObjCMethod, Function]; } def CFConsumed : InheritableParamAttr { - let Spellings = ["cf_consumed"]; + let Spellings = [GNU<"cf_consumed">]; let Subjects = [ParmVar]; } def Cleanup : InheritableAttr { - let Spellings = ["cleanup"]; + let Spellings = [GNU<"cleanup">]; let Args = [FunctionArgument<"FunctionDecl">]; } +def Cold : InheritableAttr { + let Spellings = [GNU<"cold">]; +} + def Common : InheritableAttr { - let Spellings = ["common"]; + let Spellings = [GNU<"common">]; } def Const : InheritableAttr { - let Spellings = ["const"]; + let Spellings = [GNU<"const">, GNU<"__const">]; } def Constructor : InheritableAttr { - let Spellings = ["constructor"]; + let Spellings = [GNU<"constructor">]; let Args = [IntArgument<"Priority">]; } def CUDAConstant : InheritableAttr { - let Spellings = ["constant"]; + let Spellings = [GNU<"constant">]; } -def CUDADevice : Attr { - let Spellings = ["device"]; +def CUDADevice : InheritableAttr { + let Spellings = [GNU<"device">]; } def CUDAGlobal : InheritableAttr { - let Spellings = ["global"]; + let Spellings = [GNU<"global">]; } -def CUDAHost : Attr { - let Spellings = ["host"]; +def CUDAHost : InheritableAttr { + let Spellings = [GNU<"host">]; } def CUDALaunchBounds : InheritableAttr { - let Spellings = ["launch_bounds"]; + let Spellings = [GNU<"launch_bounds">]; let Args = [IntArgument<"MaxThreads">, DefaultIntArgument<"MinBlocks", 0>]; } def CUDAShared : InheritableAttr { - let Spellings = ["shared"]; + let Spellings = [GNU<"shared">]; } def OpenCLKernel : Attr { - let Spellings = ["opencl_kernel_function"]; + let Spellings = [GNU<"opencl_kernel_function">]; +} + +def OpenCLImageAccess : Attr { + let Spellings = [GNU<"opencl_image_access">]; + let Args = [IntArgument<"Access">]; + let ASTNode = 0; } def Deprecated : InheritableAttr { - let Spellings = ["deprecated"]; + let Spellings = [GNU<"deprecated">]; let Args = [StringArgument<"Message">]; } def Destructor : InheritableAttr { - let Spellings = ["destructor"]; + let Spellings = [GNU<"destructor">]; let Args = [IntArgument<"Priority">]; } -def DLLExport : InheritableAttr { - let Spellings = ["dllexport"]; +def ExtVectorType : Attr { + let Spellings = [GNU<"ext_vector_type">]; + let Args = [ExprArgument<"NumElements">]; + let ASTNode = 0; } -def DLLImport : InheritableAttr { - let Spellings = ["dllimport"]; +def FallThrough : Attr { + let Spellings = [CXX11<"clang","fallthrough">]; + let Subjects = [NullStmt]; } def FastCall : InheritableAttr { - let Spellings = ["fastcall", "__fastcall"]; + let Spellings = [GNU<"fastcall">, GNU<"__fastcall">]; } -def Final : InheritableAttr { +def Final : InheritableAttr { let Spellings = []; let SemaHandler = 0; } -def MsStruct : InheritableAttr { - let Spellings = ["__ms_struct__"]; -} - def Format : InheritableAttr { - let Spellings = ["format"]; + let Spellings = [GNU<"format">]; let Args = [StringArgument<"Type">, IntArgument<"FormatIdx">, IntArgument<"FirstArg">]; } def FormatArg : InheritableAttr { - let Spellings = ["format_arg"]; + let Spellings = [GNU<"format_arg">]; let Args = [IntArgument<"FormatIdx">]; } def GNUInline : InheritableAttr { - let Spellings = ["gnu_inline"]; + let Spellings = [GNU<"gnu_inline">]; +} + +def Hot : InheritableAttr { + let Spellings = [GNU<"hot">]; } def IBAction : InheritableAttr { - let Spellings = ["ibaction"]; + let Spellings = [GNU<"ibaction">]; } def IBOutlet : InheritableAttr { - let Spellings = ["iboutlet"]; + let Spellings = [GNU<"iboutlet">]; } def IBOutletCollection : InheritableAttr { - let Spellings = ["iboutletcollection"]; + let Spellings = [GNU<"iboutletcollection">]; let Args = [TypeArgument<"Interface">, SourceLocArgument<"InterfaceLoc">]; } def Malloc : InheritableAttr { - let Spellings = ["malloc"]; + let Spellings = [GNU<"malloc">]; } def MaxFieldAlignment : InheritableAttr { @@ -326,7 +384,7 @@ def MaxFieldAlignment : InheritableAttr { } def MayAlias : InheritableAttr { - let Spellings = ["may_alias"]; + let Spellings = [GNU<"may_alias">]; } def MSP430Interrupt : InheritableAttr { @@ -345,28 +403,46 @@ def MBlazeSaveVolatiles : InheritableAttr { let SemaHandler = 0; } +def Mode : Attr { + let Spellings = [GNU<"mode">]; + let Args = [IdentifierArgument<"Mode">]; + let ASTNode = 0; +} + def Naked : InheritableAttr { - let Spellings = ["naked"]; + let Spellings = [GNU<"naked">]; +} + +def NeonPolyVectorType : Attr { + let Spellings = [GNU<"neon_polyvector_type">]; + let Args = [IntArgument<"NumElements">]; + let ASTNode = 0; +} + +def NeonVectorType : Attr { + let Spellings = [GNU<"neon_vector_type">]; + let Args = [IntArgument<"NumElements">]; + let ASTNode = 0; } def ReturnsTwice : InheritableAttr { - let Spellings = ["returns_twice"]; + let Spellings = [GNU<"returns_twice">]; } def NoCommon : InheritableAttr { - let Spellings = ["nocommon"]; + let Spellings = [GNU<"nocommon">]; } def NoDebug : InheritableAttr { - let Spellings = ["nodebug"]; + let Spellings = [GNU<"nodebug">]; } def NoInline : InheritableAttr { - let Spellings = ["noinline"]; + let Spellings = [GNU<"noinline">]; } def NonNull : InheritableAttr { - let Spellings = ["nonnull"]; + let Spellings = [GNU<"nonnull">]; let Args = [VariadicUnsignedArgument<"Args">]; let AdditionalMembers = [{bool isNonNull(unsigned idx) const { @@ -379,58 +455,58 @@ def NonNull : InheritableAttr { } def NoReturn : InheritableAttr { - let Spellings = ["noreturn"]; + let Spellings = [GNU<"noreturn">, CXX11<"","noreturn">, + CXX11<"std","noreturn">]; // FIXME: Does GCC allow this on the function instead? let Subjects = [Function]; - let Namespaces = ["", "std"]; } def NoInstrumentFunction : InheritableAttr { - let Spellings = ["no_instrument_function"]; + let Spellings = [GNU<"no_instrument_function">]; let Subjects = [Function]; } def NoThrow : InheritableAttr { - let Spellings = ["nothrow"]; + let Spellings = [GNU<"nothrow">]; } def NSBridged : InheritableAttr { - let Spellings = ["ns_bridged"]; + let Spellings = [GNU<"ns_bridged">]; let Subjects = [Record]; let Args = [IdentifierArgument<"BridgedType">]; } def NSReturnsRetained : InheritableAttr { - let Spellings = ["ns_returns_retained"]; + let Spellings = [GNU<"ns_returns_retained">]; let Subjects = [ObjCMethod, Function]; } def NSReturnsNotRetained : InheritableAttr { - let Spellings = ["ns_returns_not_retained"]; + let Spellings = [GNU<"ns_returns_not_retained">]; let Subjects = [ObjCMethod, Function]; } def NSReturnsAutoreleased : InheritableAttr { - let Spellings = ["ns_returns_autoreleased"]; + let Spellings = [GNU<"ns_returns_autoreleased">]; let Subjects = [ObjCMethod, Function]; } def NSConsumesSelf : InheritableAttr { - let Spellings = ["ns_consumes_self"]; + let Spellings = [GNU<"ns_consumes_self">]; let Subjects = [ObjCMethod]; } def NSConsumed : InheritableParamAttr { - let Spellings = ["ns_consumed"]; + let Spellings = [GNU<"ns_consumed">]; let Subjects = [ParmVar]; } def ObjCException : InheritableAttr { - let Spellings = ["objc_exception"]; + let Spellings = [GNU<"objc_exception">]; } def ObjCMethodFamily : InheritableAttr { - let Spellings = ["objc_method_family"]; + let Spellings = [GNU<"objc_method_family">]; let Subjects = [ObjCMethod]; let Args = [EnumArgument<"Family", "FamilyKind", ["none", "alloc", "copy", "init", "mutableCopy", "new"], @@ -439,26 +515,26 @@ def ObjCMethodFamily : InheritableAttr { } def ObjCNSObject : InheritableAttr { - let Spellings = ["NSObject"]; + let Spellings = [GNU<"NSObject">]; } def ObjCPreciseLifetime : Attr { - let Spellings = ["objc_precise_lifetime"]; + let Spellings = [GNU<"objc_precise_lifetime">]; let Subjects = [Var]; } def ObjCReturnsInnerPointer : Attr { - let Spellings = ["objc_returns_inner_pointer"]; + let Spellings = [GNU<"objc_returns_inner_pointer">]; let Subjects = [ObjCMethod]; } def ObjCRootClass : Attr { - let Spellings = ["objc_root_class"]; + let Spellings = [GNU<"objc_root_class">]; let Subjects = [ObjCInterface]; } def Overloadable : Attr { - let Spellings = ["overloadable"]; + let Spellings = [GNU<"overloadable">]; } def Override : InheritableAttr { @@ -467,7 +543,9 @@ def Override : InheritableAttr { } def Ownership : InheritableAttr { - let Spellings = ["ownership_holds", "ownership_returns", "ownership_takes"]; + let Spellings = [GNU<"ownership_holds">, GNU<"ownership_returns">, + GNU<"ownership_takes">]; + let DistinctSpellings = 1; let Args = [EnumArgument<"OwnKind", "OwnershipKind", ["ownership_holds", "ownership_returns", "ownership_takes"], ["Holds", "Returns", "Takes"]>, @@ -475,118 +553,151 @@ def Ownership : InheritableAttr { } def Packed : InheritableAttr { - let Spellings = ["packed"]; + let Spellings = [GNU<"packed">]; } def Pcs : InheritableAttr { - let Spellings = ["pcs"]; + let Spellings = [GNU<"pcs">]; let Args = [EnumArgument<"PCS", "PCSType", ["aapcs", "aapcs-vfp"], ["AAPCS", "AAPCS_VFP"]>]; } def Pure : InheritableAttr { - let Spellings = ["pure"]; + let Spellings = [GNU<"pure">]; } def Regparm : InheritableAttr { - let Spellings = ["regparm"]; + let Spellings = [GNU<"regparm">]; let Args = [UnsignedArgument<"NumParams">]; } def ReqdWorkGroupSize : InheritableAttr { - let Spellings = ["reqd_work_group_size"]; + let Spellings = [GNU<"reqd_work_group_size">]; let Args = [UnsignedArgument<"XDim">, UnsignedArgument<"YDim">, UnsignedArgument<"ZDim">]; } +def WorkGroupSizeHint : InheritableAttr { + let Spellings = [GNU<"work_group_size_hint">]; + let Args = [UnsignedArgument<"XDim">, + UnsignedArgument<"YDim">, + UnsignedArgument<"ZDim">]; +} + def InitPriority : InheritableAttr { - let Spellings = ["init_priority"]; + let Spellings = [GNU<"init_priority">]; let Args = [UnsignedArgument<"Priority">]; } def Section : InheritableAttr { - let Spellings = ["section"]; + let Spellings = [GNU<"section">]; let Args = [StringArgument<"Name">]; } def Sentinel : InheritableAttr { - let Spellings = ["sentinel"]; + let Spellings = [GNU<"sentinel">]; let Args = [DefaultIntArgument<"Sentinel", 0>, DefaultIntArgument<"NullPos", 0>]; } def StdCall : InheritableAttr { - let Spellings = ["stdcall", "__stdcall"]; + let Spellings = [GNU<"stdcall">, GNU<"__stdcall">]; } def ThisCall : InheritableAttr { - let Spellings = ["thiscall", "__thiscall"]; + let Spellings = [GNU<"thiscall">, GNU<"__thiscall">]; } def Pascal : InheritableAttr { - let Spellings = ["pascal", "__pascal"]; + let Spellings = [GNU<"pascal">]; } def TransparentUnion : InheritableAttr { - let Spellings = ["transparent_union"]; + let Spellings = [GNU<"transparent_union">]; } def Unavailable : InheritableAttr { - let Spellings = ["unavailable"]; + let Spellings = [GNU<"unavailable">]; let Args = [StringArgument<"Message">]; } def ArcWeakrefUnavailable : InheritableAttr { - let Spellings = ["objc_arc_weak_reference_unavailable"]; + let Spellings = [GNU<"objc_arc_weak_reference_unavailable">]; let Subjects = [ObjCInterface]; } +def ObjCGC : Attr { + let Spellings = [GNU<"objc_gc">]; + let Args = [IdentifierArgument<"Kind">]; + let ASTNode = 0; +} + +def ObjCOwnership : Attr { + let Spellings = [GNU<"objc_ownership">]; + let Args = [IdentifierArgument<"Kind">]; + let ASTNode = 0; +} + def ObjCRequiresPropertyDefs : InheritableAttr { - let Spellings = ["objc_requires_property_definitions"]; + let Spellings = [GNU<"objc_requires_property_definitions">]; let Subjects = [ObjCInterface]; } def Unused : InheritableAttr { - let Spellings = ["unused"]; + let Spellings = [GNU<"unused">]; } def Used : InheritableAttr { - let Spellings = ["used"]; + let Spellings = [GNU<"used">]; } def Uuid : InheritableAttr { - let Spellings = ["uuid"]; + let Spellings = [GNU<"uuid">]; let Args = [StringArgument<"Guid">]; let Subjects = [CXXRecord]; } +def VectorSize : Attr { + let Spellings = [GNU<"vector_size">]; + let Args = [ExprArgument<"NumBytes">]; + let ASTNode = 0; +} + +def VecTypeHint : Attr { + let Spellings = [GNU<"vec_type_hint">]; + let ASTNode = 0; + let SemaHandler = 0; + let Ignored = 1; +} + def Visibility : InheritableAttr { - let Spellings = ["visibility"]; + let Clone = 0; + let Spellings = [GNU<"visibility">]; let Args = [EnumArgument<"Visibility", "VisibilityType", ["default", "hidden", "internal", "protected"], ["Default", "Hidden", "Hidden", "Protected"]>]; } def VecReturn : InheritableAttr { - let Spellings = ["vecreturn"]; + let Spellings = [GNU<"vecreturn">]; let Subjects = [CXXRecord]; } def WarnUnusedResult : InheritableAttr { - let Spellings = ["warn_unused_result"]; + let Spellings = [GNU<"warn_unused_result">]; } def Weak : InheritableAttr { - let Spellings = ["weak"]; + let Spellings = [GNU<"weak">]; } def WeakImport : InheritableAttr { - let Spellings = ["weak_import"]; + let Spellings = [GNU<"weak_import">]; } def WeakRef : InheritableAttr { - let Spellings = ["weakref"]; + let Spellings = [GNU<"weakref">]; } def X86ForceAlignArgPointer : InheritableAttr { @@ -595,68 +706,68 @@ def X86ForceAlignArgPointer : InheritableAttr { // AddressSafety attribute (e.g. for AddressSanitizer) def NoAddressSafetyAnalysis : InheritableAttr { - let Spellings = ["no_address_safety_analysis"]; + let Spellings = [GNU<"no_address_safety_analysis">]; } // C/C++ Thread safety attributes (e.g. for deadlock, data race checking) def GuardedVar : InheritableAttr { - let Spellings = ["guarded_var"]; + let Spellings = [GNU<"guarded_var">]; } def PtGuardedVar : InheritableAttr { - let Spellings = ["pt_guarded_var"]; + let Spellings = [GNU<"pt_guarded_var">]; } def Lockable : InheritableAttr { - let Spellings = ["lockable"]; + let Spellings = [GNU<"lockable">]; } def ScopedLockable : InheritableAttr { - let Spellings = ["scoped_lockable"]; + let Spellings = [GNU<"scoped_lockable">]; } def NoThreadSafetyAnalysis : InheritableAttr { - let Spellings = ["no_thread_safety_analysis"]; + let Spellings = [GNU<"no_thread_safety_analysis">]; } def GuardedBy : InheritableAttr { - let Spellings = ["guarded_by"]; + let Spellings = [GNU<"guarded_by">]; let Args = [ExprArgument<"Arg">]; let LateParsed = 1; let TemplateDependent = 1; } def PtGuardedBy : InheritableAttr { - let Spellings = ["pt_guarded_by"]; + let Spellings = [GNU<"pt_guarded_by">]; let Args = [ExprArgument<"Arg">]; let LateParsed = 1; let TemplateDependent = 1; } def AcquiredAfter : InheritableAttr { - let Spellings = ["acquired_after"]; + let Spellings = [GNU<"acquired_after">]; let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; let TemplateDependent = 1; } def AcquiredBefore : InheritableAttr { - let Spellings = ["acquired_before"]; + let Spellings = [GNU<"acquired_before">]; let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; let TemplateDependent = 1; } def ExclusiveLockFunction : InheritableAttr { - let Spellings = ["exclusive_lock_function"]; + let Spellings = [GNU<"exclusive_lock_function">]; let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; let TemplateDependent = 1; } def SharedLockFunction : InheritableAttr { - let Spellings = ["shared_lock_function"]; + let Spellings = [GNU<"shared_lock_function">]; let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; let TemplateDependent = 1; @@ -665,7 +776,7 @@ def SharedLockFunction : InheritableAttr { // The first argument is an integer or boolean value specifying the return value // of a successful lock acquisition. def ExclusiveTrylockFunction : InheritableAttr { - let Spellings = ["exclusive_trylock_function"]; + let Spellings = [GNU<"exclusive_trylock_function">]; let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">]; let LateParsed = 1; let TemplateDependent = 1; @@ -674,43 +785,85 @@ def ExclusiveTrylockFunction : InheritableAttr { // The first argument is an integer or boolean value specifying the return value // of a successful lock acquisition. def SharedTrylockFunction : InheritableAttr { - let Spellings = ["shared_trylock_function"]; + let Spellings = [GNU<"shared_trylock_function">]; let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">]; let LateParsed = 1; let TemplateDependent = 1; } def UnlockFunction : InheritableAttr { - let Spellings = ["unlock_function"]; + let Spellings = [GNU<"unlock_function">]; let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; let TemplateDependent = 1; } def LockReturned : InheritableAttr { - let Spellings = ["lock_returned"]; + let Spellings = [GNU<"lock_returned">]; let Args = [ExprArgument<"Arg">]; let LateParsed = 1; let TemplateDependent = 1; } def LocksExcluded : InheritableAttr { - let Spellings = ["locks_excluded"]; + let Spellings = [GNU<"locks_excluded">]; let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; let TemplateDependent = 1; } def ExclusiveLocksRequired : InheritableAttr { - let Spellings = ["exclusive_locks_required"]; + let Spellings = [GNU<"exclusive_locks_required">]; let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; let TemplateDependent = 1; } def SharedLocksRequired : InheritableAttr { - let Spellings = ["shared_locks_required"]; + let Spellings = [GNU<"shared_locks_required">]; let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; let TemplateDependent = 1; } + +// Microsoft-related attributes + +def MsStruct : InheritableAttr { + let Spellings = [Declspec<"ms_struct">]; +} + +def DLLExport : InheritableAttr { + let Spellings = [Declspec<"dllexport">]; +} + +def DLLImport : InheritableAttr { + let Spellings = [Declspec<"dllimport">]; +} + +def ForceInline : InheritableAttr { + let Spellings = [Declspec<"__forceinline">]; +} + +def Win64 : InheritableAttr { + let Spellings = [Declspec<"w64">]; +} + +def Ptr32 : InheritableAttr { + let Spellings = [Declspec<"__ptr32">]; +} + +def Ptr64 : InheritableAttr { + let Spellings = [Declspec<"__ptr64">]; +} + +def SingleInheritance : InheritableAttr { + let Spellings = [Declspec<"__single_inheritance">]; +} + +def MultipleInheritance : InheritableAttr { + let Spellings = [Declspec<"__multiple_inheritance">]; +} + +def VirtualInheritance : InheritableAttr { + let Spellings = [Declspec<"__virtual_inheritance">]; +} diff --git a/include/clang/Basic/AttrKinds.h b/include/clang/Basic/AttrKinds.h index 9d5ae58..150a30e 100644 --- a/include/clang/Basic/AttrKinds.h +++ b/include/clang/Basic/AttrKinds.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the attr::Kind enum -// +/// +/// \file +/// \brief Defines the clang::attr::Kind enum. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_ATTRKINDS_H @@ -18,7 +19,7 @@ namespace clang { namespace attr { -// Kind - This is a list of all the recognized kinds of attributes. +// \brief A list of all the recognized kinds of attributes. enum Kind { #define ATTR(X) X, #define LAST_INHERITABLE_ATTR(X) X, LAST_INHERITABLE = X, diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index d1af218..1b060a5 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -33,7 +33,8 @@ // H -> SEL // a -> __builtin_va_list // A -> "reference" to __builtin_va_list -// V -> Vector, following num elements and a base type. +// V -> Vector, followed by the number of elements and the base type. +// E -> ext_vector, followed by the number of elements and the base type. // X -> _Complex, followed by the base type. // Y -> ptrdiff_t // P -> FILE @@ -475,6 +476,7 @@ BUILTIN(__builtin___vprintf_chk, "iicC*a", "FP:1:") BUILTIN(__builtin_expect, "LiLiLi" , "nc") BUILTIN(__builtin_prefetch, "vvC*.", "nc") +BUILTIN(__builtin_readcyclecounter, "ULLi", "n") BUILTIN(__builtin_trap, "v", "nr") BUILTIN(__builtin_unreachable, "v", "nr") BUILTIN(__builtin_shufflevector, "v." , "nc") @@ -725,6 +727,10 @@ LIBBUILTIN(strndup, "c*cC*z", "f", "string.h", ALL_LANGUAGES) LIBBUILTIN(index, "c*cC*i", "f", "strings.h", ALL_LANGUAGES) LIBBUILTIN(rindex, "c*cC*i", "f", "strings.h", ALL_LANGUAGES) LIBBUILTIN(bzero, "vv*z", "f", "strings.h", ALL_LANGUAGES) +// In some systems str[n]casejmp is a macro that expands to _str[n]icmp. +// We undefine then here to avoid wrong name. +#undef strcasecmp +#undef strncasecmp LIBBUILTIN(strcasecmp, "icC*cC*", "f", "strings.h", ALL_LANGUAGES) LIBBUILTIN(strncasecmp, "icC*cC*z", "f", "strings.h", ALL_LANGUAGES) // POSIX unistd.h @@ -804,33 +810,85 @@ LIBBUILTIN(NSLog, "vG.", "fp:0:", "Foundation/NSObjCRuntime.h", OBJC_LANG) LIBBUILTIN(NSLogv, "vGa", "fP:0:", "Foundation/NSObjCRuntime.h", OBJC_LANG) // Builtin math library functions -LIBBUILTIN(pow, "ddd", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(powl, "LdLdLd", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(powf, "fff", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(acos, "dd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(acosl, "LdLd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(acosf, "ff", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(sqrt, "dd", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(sqrtl, "LdLd", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(sqrtf, "ff", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(asin, "dd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(asinl, "LdLd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(asinf, "ff", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(sin, "dd", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(sinl, "LdLd", "fe", "math.h", ALL_LANGUAGES) -LIBBUILTIN(sinf, "ff", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(atan, "dd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(atanl, "LdLd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(atanf, "ff", "fe", "math.h", ALL_LANGUAGES) + +LIBBUILTIN(atan2, "ddd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(atan2l, "LdLdLd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(atan2f, "fff", "fe", "math.h", ALL_LANGUAGES) + +LIBBUILTIN(ceil, "dd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(ceill, "LdLd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(ceilf, "ff", "fe", "math.h", ALL_LANGUAGES) LIBBUILTIN(cos, "dd", "fe", "math.h", ALL_LANGUAGES) LIBBUILTIN(cosl, "LdLd", "fe", "math.h", ALL_LANGUAGES) LIBBUILTIN(cosf, "ff", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(exp, "dd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(expl, "LdLd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(expf, "ff", "fe", "math.h", ALL_LANGUAGES) + +LIBBUILTIN(fabs, "dd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(fabsl, "LdLd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(fabsf, "ff", "fe", "math.h", ALL_LANGUAGES) + +LIBBUILTIN(floor, "dd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(floorl, "LdLd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(floorf, "ff", "fe", "math.h", ALL_LANGUAGES) + LIBBUILTIN(fma, "dddd", "fc", "math.h", ALL_LANGUAGES) LIBBUILTIN(fmal, "LdLdLdLd", "fc", "math.h", ALL_LANGUAGES) LIBBUILTIN(fmaf, "ffff", "fc", "math.h", ALL_LANGUAGES) +LIBBUILTIN(fmax, "ddd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(fmaxl, "LdLdLd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(fmaxf, "fff", "fe", "math.h", ALL_LANGUAGES) + +LIBBUILTIN(fmin, "ddd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(fminl, "LdLdLd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(fminf, "fff", "fe", "math.h", ALL_LANGUAGES) + +LIBBUILTIN(log, "dd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(logl, "LdLd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(logf, "ff", "fe", "math.h", ALL_LANGUAGES) + +LIBBUILTIN(pow, "ddd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(powl, "LdLdLd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(powf, "fff", "fe", "math.h", ALL_LANGUAGES) + +LIBBUILTIN(round, "dd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(roundl, "LdLd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(roundf, "ff", "fe", "math.h", ALL_LANGUAGES) + +LIBBUILTIN(sin, "dd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(sinl, "LdLd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(sinf, "ff", "fe", "math.h", ALL_LANGUAGES) + +LIBBUILTIN(sqrt, "dd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(sqrtl, "LdLd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(sqrtf, "ff", "fe", "math.h", ALL_LANGUAGES) + +LIBBUILTIN(tan, "dd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(tanl, "LdLd", "fe", "math.h", ALL_LANGUAGES) +LIBBUILTIN(tanf, "ff", "fe", "math.h", ALL_LANGUAGES) + // Blocks runtime Builtin math library functions LIBBUILTIN(_Block_object_assign, "vv*vC*iC", "f", "Blocks.h", ALL_LANGUAGES) LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h", ALL_LANGUAGES) // FIXME: Also declare NSConcreteGlobalBlock and NSConcreteStackBlock. // Annotation function -BUILTIN(__builtin_annotation, "UiUicC*", "nc") +BUILTIN(__builtin_annotation, "v.", "tn") #undef BUILTIN #undef LIBBUILTIN diff --git a/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h index 5afa020..257daf1 100644 --- a/include/clang/Basic/Builtins.h +++ b/include/clang/Basic/Builtins.h @@ -6,10 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines enum values for all the target-independent builtin -// functions. -// +/// +/// \file +/// \brief Defines enum values for all the target-independent builtin +/// functions. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_BUILTINS_H @@ -56,7 +57,7 @@ struct Info { bool operator!=(const Info &RHS) const { return !(*this == RHS); } }; -/// Builtin::Context - This holds information about target-independent and +/// \brief Holds information about both target-independent and /// target-specific builtins, allowing easy queries by clients. class Context { const Info *TSRecords; @@ -67,7 +68,7 @@ public: /// \brief Perform target-specific initialization void InitializeTarget(const TargetInfo &Target); - /// InitializeBuiltins - Mark the identifiers for all the builtins with their + /// \brief Mark the identifiers for all the builtins with their /// appropriate builtin ID # and mark any non-portable builtin identifiers as /// such. void InitializeBuiltins(IdentifierTable &Table, const LangOptions& LangOpts); @@ -76,39 +77,39 @@ public: void GetBuiltinNames(SmallVectorImpl<const char *> &Names, bool NoBuiltins); - /// Builtin::GetName - Return the identifier name for the specified builtin, + /// \brief Return the identifier name for the specified builtin, /// e.g. "__builtin_abs". const char *GetName(unsigned ID) const { return GetRecord(ID).Name; } - /// GetTypeString - Get the type descriptor string for the specified builtin. + /// \brief Get the type descriptor string for the specified builtin. const char *GetTypeString(unsigned ID) const { return GetRecord(ID).Type; } - /// isConst - Return true if this function has no side effects and doesn't + /// \brief Return true if this function has no side effects and doesn't /// read memory. bool isConst(unsigned ID) const { return strchr(GetRecord(ID).Attributes, 'c') != 0; } - /// isNoThrow - Return true if we know this builtin never throws an exception. + /// \brief Return true if we know this builtin never throws an exception. bool isNoThrow(unsigned ID) const { return strchr(GetRecord(ID).Attributes, 'n') != 0; } - /// isNoReturn - Return true if we know this builtin never returns. + /// \brief Return true if we know this builtin never returns. bool isNoReturn(unsigned ID) const { return strchr(GetRecord(ID).Attributes, 'r') != 0; } - /// isReturnsTwice - Return true if we know this builtin can return twice. + /// \brief Return true if we know this builtin can return twice. bool isReturnsTwice(unsigned ID) const { return strchr(GetRecord(ID).Attributes, 'j') != 0; } - /// isLibFunction - Return true if this is a builtin for a libc/libm function, + /// \brief Return true if this is a builtin for a libc/libm function, /// with a "__builtin_" prefix (e.g. __builtin_abs). bool isLibFunction(unsigned ID) const { return strchr(GetRecord(ID).Attributes, 'F') != 0; @@ -146,10 +147,10 @@ public: /// argument and whether this function as a va_list argument. bool isScanfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg); - /// isConstWithoutErrno - Return true if this function has no side - /// effects and doesn't read memory, except for possibly errno. Such - /// functions can be const when the MathErrno lang option is - /// disabled. + /// \brief Return true if this function has no side effects and doesn't + /// read memory, except for possibly errno. + /// + /// Such functions can be const when the MathErrno lang option is disabled. bool isConstWithoutErrno(unsigned ID) const { return strchr(GetRecord(ID).Attributes, 'e') != 0; } diff --git a/include/clang/Basic/BuiltinsHexagon.def b/include/clang/Basic/BuiltinsHexagon.def index 334224f..c071a46 100644 --- a/include/clang/Basic/BuiltinsHexagon.def +++ b/include/clang/Basic/BuiltinsHexagon.def @@ -1,4 +1,4 @@ -//==--- BuiltinsHexagon.def - Hexagon Builtin function database --*- C++ -*-==// +//===-- BuiltinsHexagon.def - Hexagon Builtin function database --*- C++ -*-==// // // The LLVM Compiler Infrastructure // @@ -7,683 +7,872 @@ // //===----------------------------------------------------------------------===// // -// This file defines the X86-specific builtin function database. Users of +// This file defines the Hexagon-specific builtin function database. Users of // this file must define the BUILTIN macro to make use of this information. // //===----------------------------------------------------------------------===// -BUILTIN(__builtin_HEXAGON_C2_cmpeq, "bii", "") -BUILTIN(__builtin_HEXAGON_C2_cmpgt, "bii", "") -BUILTIN(__builtin_HEXAGON_C2_cmpgtu, "bii", "") -BUILTIN(__builtin_HEXAGON_C2_cmpeqp, "bLLiLLi", "") -BUILTIN(__builtin_HEXAGON_C2_cmpgtp, "bLLiLLi", "") -BUILTIN(__builtin_HEXAGON_C2_cmpgtup, "bLLiLLi", "") -BUILTIN(__builtin_HEXAGON_C2_bitsset, "bii", "") -BUILTIN(__builtin_HEXAGON_C2_bitsclr, "bii", "") -BUILTIN(__builtin_HEXAGON_C2_cmpeqi, "bii", "") -BUILTIN(__builtin_HEXAGON_C2_cmpgti, "bii", "") -BUILTIN(__builtin_HEXAGON_C2_cmpgtui, "bii", "") -BUILTIN(__builtin_HEXAGON_C2_cmpgei, "bii", "") -BUILTIN(__builtin_HEXAGON_C2_cmpgeui, "bii", "") -BUILTIN(__builtin_HEXAGON_C2_cmplt, "bii", "") -BUILTIN(__builtin_HEXAGON_C2_cmpltu, "bii", "") -BUILTIN(__builtin_HEXAGON_C2_bitsclri, "bii", "") -BUILTIN(__builtin_HEXAGON_C2_and, "bii", "") -BUILTIN(__builtin_HEXAGON_C2_or, "bii", "") -BUILTIN(__builtin_HEXAGON_C2_xor, "bii", "") -BUILTIN(__builtin_HEXAGON_C2_andn, "bii", "") -BUILTIN(__builtin_HEXAGON_C2_not, "bi", "") -BUILTIN(__builtin_HEXAGON_C2_orn, "bii", "") -BUILTIN(__builtin_HEXAGON_C2_pxfer_map, "bi", "") -BUILTIN(__builtin_HEXAGON_C2_any8, "bi", "") -BUILTIN(__builtin_HEXAGON_C2_all8, "bi", "") -BUILTIN(__builtin_HEXAGON_C2_vitpack, "iii", "") -BUILTIN(__builtin_HEXAGON_C2_mux, "iiii", "") -BUILTIN(__builtin_HEXAGON_C2_muxii, "iiii", "") -BUILTIN(__builtin_HEXAGON_C2_muxir, "iiii", "") -BUILTIN(__builtin_HEXAGON_C2_muxri, "iiii", "") -BUILTIN(__builtin_HEXAGON_C2_vmux, "LLiiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_C2_mask, "LLii", "") -BUILTIN(__builtin_HEXAGON_A2_vcmpbeq, "bLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vcmpbgtu, "bLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vcmpheq, "bLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vcmphgt, "bLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vcmphgtu, "bLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vcmpweq, "bLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vcmpwgt, "bLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vcmpwgtu, "bLLiLLi", "") -BUILTIN(__builtin_HEXAGON_C2_tfrpr, "ii", "") -BUILTIN(__builtin_HEXAGON_C2_tfrrp, "bi", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hh_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hh_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hl_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hl_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_acc_lh_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_acc_lh_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_acc_ll_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_acc_ll_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hh_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hh_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hl_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hl_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_nac_lh_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_nac_lh_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_nac_ll_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_nac_ll_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hh_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hh_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hl_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hl_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_lh_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_lh_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_ll_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_ll_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hh_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hh_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hl_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hl_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_lh_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_lh_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_ll_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_ll_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_hh_s0, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_hh_s1, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_hl_s0, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_hl_s1, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_lh_s0, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_lh_s1, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_ll_s0, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_ll_s1, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hh_s0, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hh_s1, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hl_s0, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hl_s1, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_sat_lh_s0, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_sat_lh_s1, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_sat_ll_s0, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_sat_ll_s1, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hh_s0, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hh_s1, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hl_s0, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hl_s1, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_lh_s0, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_lh_s1, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_ll_s0, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_ll_s1, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hh_s0, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hh_s1, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hl_s0, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hl_s1, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_lh_s0, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_lh_s1, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_ll_s0, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_ll_s1, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hh_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hh_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hl_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hl_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_lh_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_lh_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_ll_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_ll_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hh_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hh_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hl_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hl_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_lh_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_lh_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_ll_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_ll_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_hh_s0, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_hh_s1, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_hl_s0, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_hl_s1, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_lh_s0, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_lh_s1, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_ll_s0, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_ll_s1, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hh_s0, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hh_s1, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hl_s0, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hl_s1, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_lh_s0, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_lh_s1, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_ll_s0, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_ll_s1, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hh_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hh_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hl_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hl_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_lh_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_lh_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_ll_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_ll_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hh_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hh_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hl_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hl_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_lh_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_lh_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_ll_s0, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_ll_s1, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_hh_s0, "Uiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_hh_s1, "Uiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_hl_s0, "Uiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_hl_s1, "Uiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_lh_s0, "Uiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_lh_s1, "Uiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_ll_s0, "Uiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_ll_s1, "Uiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hh_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hh_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hl_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hl_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_lh_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_lh_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_ll_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_ll_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hh_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hh_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hl_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hl_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_lh_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_lh_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_ll_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_ll_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_hh_s0, "ULLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_hh_s1, "ULLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_hl_s0, "ULLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_hl_s1, "ULLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_lh_s0, "ULLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_lh_s1, "ULLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_ll_s0, "ULLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyud_ll_s1, "ULLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpysmi, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_macsip, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_macsin, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_dpmpyss_s0, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_dpmpyss_acc_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_dpmpyss_nac_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_s0, "ULLiii", "") -BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_acc_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_nac_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_mpy_up, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyu_up, "Uiii", "") -BUILTIN(__builtin_HEXAGON_M2_dpmpyss_rnd_s0, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyi, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mpyui, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_maci, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_acci, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_accii, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_nacci, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_naccii, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_subacc, "iiii", "") -BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s0, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s1, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_vmac2s_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_vmac2s_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s0pack, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s1pack, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_vmac2, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_vmpy2es_s0, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vmpy2es_s1, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vmac2es_s0, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vmac2es_s1, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vmac2es, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vrmac_s0, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vrmpy_s0, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vdmpyrs_s0, "iLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vdmpyrs_s1, "iLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vdmacs_s0, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vdmacs_s1, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vdmpys_s0, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vdmpys_s1, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_cmpyrs_s0, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_cmpyrs_s1, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_cmpyrsc_s0, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_cmpyrsc_s1, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_cmacs_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_cmacs_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_cmacsc_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_cmacsc_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_cmpys_s0, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_cmpys_s1, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_cmpysc_s0, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_cmpysc_s1, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_cnacs_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_cnacs_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_cnacsc_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_cnacsc_s1, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_vrcmpys_s1, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_M2_vrcmpys_acc_s1, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_M2_vrcmpys_s1rp, "iLLii", "") -BUILTIN(__builtin_HEXAGON_M2_mmacls_s0, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmacls_s1, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmachs_s0, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmachs_s1, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmpyl_s0, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmpyl_s1, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmpyh_s0, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmpyh_s1, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmacls_rs0, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmacls_rs1, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmachs_rs0, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmachs_rs1, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmpyl_rs0, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmpyl_rs1, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmpyh_rs0, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmpyh_rs1, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_hmmpyl_rs1, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_hmmpyh_rs1, "iii", "") -BUILTIN(__builtin_HEXAGON_M2_mmaculs_s0, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmaculs_s1, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmacuhs_s0, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmacuhs_s1, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmpyul_s0, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmpyul_s1, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmpyuh_s0, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmpyuh_s1, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmaculs_rs0, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmaculs_rs1, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmacuhs_rs0, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmacuhs_rs1, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmpyul_rs0, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmpyul_rs1, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmpyuh_rs0, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_mmpyuh_rs1, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vrcmaci_s0, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vrcmacr_s0, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vrcmaci_s0c, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vrcmacr_s0c, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_cmaci_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_cmacr_s0, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_M2_vrcmpyi_s0, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vrcmpyr_s0, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vrcmpyi_s0c, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vrcmpyr_s0c, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_cmpyi_s0, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_cmpyr_s0, "LLiii", "") -BUILTIN(__builtin_HEXAGON_M2_vcmpy_s0_sat_i, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vcmpy_s0_sat_r, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vcmpy_s1_sat_i, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vcmpy_s1_sat_r, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vcmac_s0_sat_i, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vcmac_s0_sat_r, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_S2_vcrotate, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_A2_add, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_sub, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_addsat, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_subsat, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_addi, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_addh_l16_ll, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_addh_l16_hl, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_addh_l16_sat_ll, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_addh_l16_sat_hl, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_subh_l16_ll, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_subh_l16_hl, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_subh_l16_sat_ll, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_subh_l16_sat_hl, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_addh_h16_ll, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_addh_h16_lh, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_addh_h16_hl, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_addh_h16_hh, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_ll, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_lh, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_hl, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_hh, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_subh_h16_ll, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_subh_h16_lh, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_subh_h16_hl, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_subh_h16_hh, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_ll, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_lh, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_hl, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_hh, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_aslh, "ii", "") -BUILTIN(__builtin_HEXAGON_A2_asrh, "ii", "") -BUILTIN(__builtin_HEXAGON_A2_addp, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_addpsat, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_addsp, "LLiiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_subp, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_neg, "ii", "") -BUILTIN(__builtin_HEXAGON_A2_negsat, "ii", "") -BUILTIN(__builtin_HEXAGON_A2_abs, "ii", "") -BUILTIN(__builtin_HEXAGON_A2_abssat, "ii", "") -BUILTIN(__builtin_HEXAGON_A2_vconj, "LLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_negp, "LLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_absp, "LLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_max, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_maxu, "Uiii", "") -BUILTIN(__builtin_HEXAGON_A2_min, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_minu, "Uiii", "") -BUILTIN(__builtin_HEXAGON_A2_maxp, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_maxup, "ULLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_minp, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_minup, "ULLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_tfr, "ii", "") -BUILTIN(__builtin_HEXAGON_A2_tfrsi, "ii", "") -BUILTIN(__builtin_HEXAGON_A2_tfrp, "LLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_tfrpi, "LLii", "") -BUILTIN(__builtin_HEXAGON_A2_zxtb, "ii", "") -BUILTIN(__builtin_HEXAGON_A2_sxtb, "ii", "") -BUILTIN(__builtin_HEXAGON_A2_zxth, "ii", "") -BUILTIN(__builtin_HEXAGON_A2_sxth, "ii", "") -BUILTIN(__builtin_HEXAGON_A2_combinew, "LLiii", "") -BUILTIN(__builtin_HEXAGON_A2_combineii, "LLiii", "") -BUILTIN(__builtin_HEXAGON_A2_combine_hh, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_combine_hl, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_combine_lh, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_combine_ll, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_tfril, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_tfrih, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_and, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_or, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_xor, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_not, "ii", "") -BUILTIN(__builtin_HEXAGON_M2_xor_xacc, "iiii", "") -BUILTIN(__builtin_HEXAGON_A2_subri, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_andir, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_orir, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_andp, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_orp, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_xorp, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_notp, "LLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_sxtw, "LLii", "") -BUILTIN(__builtin_HEXAGON_A2_sat, "iLLi", "") -BUILTIN(__builtin_HEXAGON_A2_sath, "ii", "") -BUILTIN(__builtin_HEXAGON_A2_satuh, "ii", "") -BUILTIN(__builtin_HEXAGON_A2_satub, "ii", "") -BUILTIN(__builtin_HEXAGON_A2_satb, "ii", "") -BUILTIN(__builtin_HEXAGON_A2_vaddub, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vaddubs, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vaddh, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vaddhs, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vadduhs, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vaddw, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vaddws, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_svavgh, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_svavghs, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_svnavgh, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_svaddh, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_svaddhs, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_svadduhs, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_svsubh, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_svsubhs, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_svsubuhs, "iii", "") -BUILTIN(__builtin_HEXAGON_A2_vraddub, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vraddub_acc, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vradduh, "iLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vsubub, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vsububs, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vsubh, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vsubhs, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vsubuhs, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vsubw, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vsubws, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vabsh, "LLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vabshsat, "LLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vabsw, "LLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vabswsat, "LLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vabsdiffw, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_M2_vabsdiffh, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vrsadub, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vrsadub_acc, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vavgub, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vavguh, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vavgh, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vnavgh, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vavgw, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vnavgw, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vavgwr, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vnavgwr, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vavgwcr, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vnavgwcr, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vavghcr, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vnavghcr, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vavguw, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vavguwr, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vavgubr, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vavguhr, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vavghr, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vnavghr, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vminh, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vmaxh, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vminub, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vmaxub, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vminuh, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vmaxuh, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vminw, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vmaxw, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vminuw, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A2_vmaxuw, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_S2_asr_r_r, "iii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_r_r, "iii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_r_r, "iii", "") -BUILTIN(__builtin_HEXAGON_S2_lsl_r_r, "iii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_r_p, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_r_p, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_r_p, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsl_r_p, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_r_r_acc, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_r_r_acc, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_acc, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_acc, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_r_p_acc, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_r_p_acc, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_acc, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_acc, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_r_r_nac, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_r_r_nac, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_nac, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_nac, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_r_p_nac, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_r_p_nac, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_nac, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_nac, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_r_r_and, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_r_r_and, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_and, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_and, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_r_r_or, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_r_r_or, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_or, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_or, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_r_p_and, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_r_p_and, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_and, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_and, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_r_p_or, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_r_p_or, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_or, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_or, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_r_r_sat, "iii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_r_r_sat, "iii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_i_r, "iii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_i_r, "iii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_i_r, "iii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_i_p, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_i_p, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_i_p, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_i_r_acc, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_acc, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_i_r_acc, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_i_p_acc, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_acc, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_i_p_acc, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_i_r_nac, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_nac, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_i_r_nac, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_i_p_nac, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_nac, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_i_p_nac, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_xacc, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_i_r_xacc, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_xacc, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_i_p_xacc, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_i_r_and, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_and, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_i_r_and, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_i_r_or, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_or, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_i_r_or, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_i_p_and, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_and, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_i_p_and, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_i_p_or, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_or, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_i_p_or, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_i_r_sat, "iii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_i_r_rnd, "iii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_i_r_rnd_goodsyntax, "iii", "") -BUILTIN(__builtin_HEXAGON_S2_addasl_rrri, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_valignib, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_valignrb, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_vspliceib, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_vsplicerb, "LLiLLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_vsplatrh, "LLii", "") -BUILTIN(__builtin_HEXAGON_S2_vsplatrb, "ii", "") -BUILTIN(__builtin_HEXAGON_S2_insert, "iiiii", "") -BUILTIN(__builtin_HEXAGON_S2_tableidxb_goodsyntax, "iiiii", "") -BUILTIN(__builtin_HEXAGON_S2_tableidxh_goodsyntax, "iiiii", "") -BUILTIN(__builtin_HEXAGON_S2_tableidxw_goodsyntax, "iiiii", "") -BUILTIN(__builtin_HEXAGON_S2_tableidxd_goodsyntax, "iiiii", "") -BUILTIN(__builtin_HEXAGON_S2_extractu, "iiii", "") -BUILTIN(__builtin_HEXAGON_S2_insertp, "LLiLLiLLiii", "") -BUILTIN(__builtin_HEXAGON_S2_extractup, "LLiLLiii", "") -BUILTIN(__builtin_HEXAGON_S2_insert_rp, "iiiLLi", "") -BUILTIN(__builtin_HEXAGON_S2_extractu_rp, "iiLLi", "") -BUILTIN(__builtin_HEXAGON_S2_insertp_rp, "LLiLLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_S2_extractup_rp, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_S2_tstbit_i, "bii", "") -BUILTIN(__builtin_HEXAGON_S2_setbit_i, "iii", "") -BUILTIN(__builtin_HEXAGON_S2_togglebit_i, "iii", "") -BUILTIN(__builtin_HEXAGON_S2_clrbit_i, "iii", "") -BUILTIN(__builtin_HEXAGON_S2_tstbit_r, "bii", "") -BUILTIN(__builtin_HEXAGON_S2_setbit_r, "iii", "") -BUILTIN(__builtin_HEXAGON_S2_togglebit_r, "iii", "") -BUILTIN(__builtin_HEXAGON_S2_clrbit_r, "iii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_i_vh, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_i_vh, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_i_vh, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_r_vh, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_r_vh, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_r_vh, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsl_r_vh, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_i_vw, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_i_svw_trun, "iLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_r_svw_trun, "iLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_i_vw, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_i_vw, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asr_r_vw, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_asl_r_vw, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsr_r_vw, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_lsl_r_vw, "LLiLLii", "") -BUILTIN(__builtin_HEXAGON_S2_vrndpackwh, "iLLi", "") -BUILTIN(__builtin_HEXAGON_S2_vrndpackwhs, "iLLi", "") -BUILTIN(__builtin_HEXAGON_S2_vsxtbh, "LLii", "") -BUILTIN(__builtin_HEXAGON_S2_vzxtbh, "LLii", "") -BUILTIN(__builtin_HEXAGON_S2_vsathub, "iLLi", "") -BUILTIN(__builtin_HEXAGON_S2_svsathub, "ii", "") -BUILTIN(__builtin_HEXAGON_S2_svsathb, "ii", "") -BUILTIN(__builtin_HEXAGON_S2_vsathb, "iLLi", "") -BUILTIN(__builtin_HEXAGON_S2_vtrunohb, "iLLi", "") -BUILTIN(__builtin_HEXAGON_S2_vtrunewh, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_S2_vtrunowh, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_S2_vtrunehb, "iLLi", "") -BUILTIN(__builtin_HEXAGON_S2_vsxthw, "LLii", "") -BUILTIN(__builtin_HEXAGON_S2_vzxthw, "LLii", "") -BUILTIN(__builtin_HEXAGON_S2_vsatwh, "iLLi", "") -BUILTIN(__builtin_HEXAGON_S2_vsatwuh, "iLLi", "") -BUILTIN(__builtin_HEXAGON_S2_packhl, "LLiii", "") -BUILTIN(__builtin_HEXAGON_A2_swiz, "ii", "") -BUILTIN(__builtin_HEXAGON_S2_vsathub_nopack, "LLiLLi", "") -BUILTIN(__builtin_HEXAGON_S2_vsathb_nopack, "LLiLLi", "") -BUILTIN(__builtin_HEXAGON_S2_vsatwh_nopack, "LLiLLi", "") -BUILTIN(__builtin_HEXAGON_S2_vsatwuh_nopack, "LLiLLi", "") -BUILTIN(__builtin_HEXAGON_S2_shuffob, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_S2_shuffeb, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_S2_shuffoh, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_S2_shuffeh, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_S2_parityp, "iLLiLLi", "") -BUILTIN(__builtin_HEXAGON_S2_lfsp, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_S2_clbnorm, "ii", "") -BUILTIN(__builtin_HEXAGON_S2_clb, "ii", "") -BUILTIN(__builtin_HEXAGON_S2_cl0, "ii", "") -BUILTIN(__builtin_HEXAGON_S2_cl1, "ii", "") -BUILTIN(__builtin_HEXAGON_S2_clbp, "iLLi", "") -BUILTIN(__builtin_HEXAGON_S2_cl0p, "iLLi", "") -BUILTIN(__builtin_HEXAGON_S2_cl1p, "iLLi", "") -BUILTIN(__builtin_HEXAGON_S2_brev, "ii", "") -BUILTIN(__builtin_HEXAGON_S2_ct0, "ii", "") -BUILTIN(__builtin_HEXAGON_S2_ct1, "ii", "") -BUILTIN(__builtin_HEXAGON_S2_interleave, "LLiLLi", "") -BUILTIN(__builtin_HEXAGON_S2_deinterleave, "LLiLLi", "") +// The format of this database matches clang/Basic/Builtins.def. -BUILTIN(__builtin_SI_to_SXTHI_asrh, "ii", "") - -BUILTIN(__builtin_M2_vrcmpys_s1, "LLiLLii", "") -BUILTIN(__builtin_M2_vrcmpys_acc_s1, "LLiLLiLLii", "") -BUILTIN(__builtin_M2_vrcmpys_s1rp, "iLLii", "") - -BUILTIN(__builtin_M2_vradduh, "iLLiLLi", "") -BUILTIN(__builtin_A2_addsp, "LLiiLLi", "") -BUILTIN(__builtin_A2_addpsat, "LLiLLiLLi", "") +// The builtins below are not autogenerated from iset.py. +// Make sure you do not overwrite these. -BUILTIN(__builtin_A2_maxp, "LLiLLiLLi", "") -BUILTIN(__builtin_A2_maxup, "LLiLLiLLi", "") - -BUILTIN(__builtin_HEXAGON_A4_orn, "iii", "") -BUILTIN(__builtin_HEXAGON_A4_andn, "iii", "") -BUILTIN(__builtin_HEXAGON_A4_ornp, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A4_andnp, "LLiLLiLLi", "") -BUILTIN(__builtin_HEXAGON_A4_combineir, "LLiii", "") -BUILTIN(__builtin_HEXAGON_A4_combineri, "LLiii", "") -BUILTIN(__builtin_HEXAGON_C4_cmpneqi, "bii", "") -BUILTIN(__builtin_HEXAGON_C4_cmpneq, "bii", "") -BUILTIN(__builtin_HEXAGON_C4_cmpltei, "bii", "") -BUILTIN(__builtin_HEXAGON_C4_cmplte, "bii", "") -BUILTIN(__builtin_HEXAGON_C4_cmplteui, "bii", "") -BUILTIN(__builtin_HEXAGON_C4_cmplteu, "bii", "") -BUILTIN(__builtin_HEXAGON_A4_rcmpneq, "iii", "") -BUILTIN(__builtin_HEXAGON_A4_rcmpneqi, "iii", "") -BUILTIN(__builtin_HEXAGON_A4_rcmpeq, "iii", "") -BUILTIN(__builtin_HEXAGON_A4_rcmpeqi, "iii", "") -BUILTIN(__builtin_HEXAGON_C4_fastcorner9, "bii", "") -BUILTIN(__builtin_HEXAGON_C4_fastcorner9_not, "bii", "") -BUILTIN(__builtin_HEXAGON_C4_and_andn, "biii", "") -BUILTIN(__builtin_HEXAGON_C4_and_and, "biii", "") -BUILTIN(__builtin_HEXAGON_C4_and_orn, "biii", "") -BUILTIN(__builtin_HEXAGON_C4_and_or, "biii", "") -BUILTIN(__builtin_HEXAGON_C4_or_andn, "biii", "") -BUILTIN(__builtin_HEXAGON_C4_or_and, "biii", "") -BUILTIN(__builtin_HEXAGON_C4_or_orn, "biii", "") -BUILTIN(__builtin_HEXAGON_C4_or_or, "biii", "") -BUILTIN(__builtin_HEXAGON_S4_addaddi, "iiii", "") -BUILTIN(__builtin_HEXAGON_S4_subaddi, "iiii", "") -BUILTIN(__builtin_HEXAGON_M4_xor_xacc, "LLiLLiLLiLLi", "") - -BUILTIN(__builtin_HEXAGON_M4_and_and, "iiii", "") -BUILTIN(__builtin_HEXAGON_M4_and_or, "iiii", "") -BUILTIN(__builtin_HEXAGON_M4_and_xor, "iiii", "") -BUILTIN(__builtin_HEXAGON_M4_and_andn, "iiii", "") -BUILTIN(__builtin_HEXAGON_M4_xor_and, "iiii", "") -BUILTIN(__builtin_HEXAGON_M4_xor_or, "iiii", "") -BUILTIN(__builtin_HEXAGON_M4_xor_andn, "iiii", "") -BUILTIN(__builtin_HEXAGON_M4_or_and, "iiii", "") -BUILTIN(__builtin_HEXAGON_M4_or_or, "iiii", "") -BUILTIN(__builtin_HEXAGON_M4_or_xor, "iiii", "") -BUILTIN(__builtin_HEXAGON_M4_or_andn, "iiii", "") -BUILTIN(__builtin_HEXAGON_S4_or_andix, "iiii", "") -BUILTIN(__builtin_HEXAGON_S4_or_andi, "iiii", "") -BUILTIN(__builtin_HEXAGON_S4_or_ori, "iiii", "") +BUILTIN(__builtin_SI_to_SXTHI_asrh, "ii", "") +BUILTIN(__builtin_circ_ldd, "LLi*LLi*LLi*ii", "") -BUILTIN(__builtin_HEXAGON_A4_modwrapu, "iii", "") +// The builtins above are not autogenerated from iset.py. +// Make sure you do not overwrite these. -BUILTIN(__builtin_HEXAGON_A4_cround_ri, "iii", "") -BUILTIN(__builtin_HEXAGON_A4_cround_rr, "iii", "") -BUILTIN(__builtin_HEXAGON_A4_round_ri, "iii", "") -BUILTIN(__builtin_HEXAGON_A4_round_rr, "iii", "") -BUILTIN(__builtin_HEXAGON_A4_round_ri_sat, "iii", "") -BUILTIN(__builtin_HEXAGON_A4_round_rr_sat, "iii", "") +BUILTIN(__builtin_HEXAGON_C2_cmpeq,"bii","") +BUILTIN(__builtin_HEXAGON_C2_cmpgt,"bii","") +BUILTIN(__builtin_HEXAGON_C2_cmpgtu,"bii","") +BUILTIN(__builtin_HEXAGON_C2_cmpeqp,"bLLiLLi","") +BUILTIN(__builtin_HEXAGON_C2_cmpgtp,"bLLiLLi","") +BUILTIN(__builtin_HEXAGON_C2_cmpgtup,"bLLiLLi","") +BUILTIN(__builtin_HEXAGON_A4_rcmpeqi,"iii","") +BUILTIN(__builtin_HEXAGON_A4_rcmpneqi,"iii","") +BUILTIN(__builtin_HEXAGON_A4_rcmpeq,"iii","") +BUILTIN(__builtin_HEXAGON_A4_rcmpneq,"iii","") +BUILTIN(__builtin_HEXAGON_C2_bitsset,"bii","") +BUILTIN(__builtin_HEXAGON_C2_bitsclr,"bii","") +BUILTIN(__builtin_HEXAGON_C4_nbitsset,"bii","") +BUILTIN(__builtin_HEXAGON_C4_nbitsclr,"bii","") +BUILTIN(__builtin_HEXAGON_C2_cmpeqi,"bii","") +BUILTIN(__builtin_HEXAGON_C2_cmpgti,"bii","") +BUILTIN(__builtin_HEXAGON_C2_cmpgtui,"bii","") +BUILTIN(__builtin_HEXAGON_C2_cmpgei,"bii","") +BUILTIN(__builtin_HEXAGON_C2_cmpgeui,"bii","") +BUILTIN(__builtin_HEXAGON_C2_cmplt,"bii","") +BUILTIN(__builtin_HEXAGON_C2_cmpltu,"bii","") +BUILTIN(__builtin_HEXAGON_C2_bitsclri,"bii","") +BUILTIN(__builtin_HEXAGON_C4_nbitsclri,"bii","") +BUILTIN(__builtin_HEXAGON_C4_cmpneqi,"bii","") +BUILTIN(__builtin_HEXAGON_C4_cmpltei,"bii","") +BUILTIN(__builtin_HEXAGON_C4_cmplteui,"bii","") +BUILTIN(__builtin_HEXAGON_C4_cmpneq,"bii","") +BUILTIN(__builtin_HEXAGON_C4_cmplte,"bii","") +BUILTIN(__builtin_HEXAGON_C4_cmplteu,"bii","") +BUILTIN(__builtin_HEXAGON_C2_and,"bii","") +BUILTIN(__builtin_HEXAGON_C2_or,"bii","") +BUILTIN(__builtin_HEXAGON_C2_xor,"bii","") +BUILTIN(__builtin_HEXAGON_C2_andn,"bii","") +BUILTIN(__builtin_HEXAGON_C2_not,"bi","") +BUILTIN(__builtin_HEXAGON_C2_orn,"bii","") +BUILTIN(__builtin_HEXAGON_C4_and_and,"biii","") +BUILTIN(__builtin_HEXAGON_C4_and_or,"biii","") +BUILTIN(__builtin_HEXAGON_C4_or_and,"biii","") +BUILTIN(__builtin_HEXAGON_C4_or_or,"biii","") +BUILTIN(__builtin_HEXAGON_C4_and_andn,"biii","") +BUILTIN(__builtin_HEXAGON_C4_and_orn,"biii","") +BUILTIN(__builtin_HEXAGON_C4_or_andn,"biii","") +BUILTIN(__builtin_HEXAGON_C4_or_orn,"biii","") +BUILTIN(__builtin_HEXAGON_C2_pxfer_map,"bi","") +BUILTIN(__builtin_HEXAGON_C2_any8,"bi","") +BUILTIN(__builtin_HEXAGON_C2_all8,"bi","") +BUILTIN(__builtin_HEXAGON_C2_vitpack,"iii","") +BUILTIN(__builtin_HEXAGON_C2_mux,"iiii","") +BUILTIN(__builtin_HEXAGON_C2_muxii,"iiii","") +BUILTIN(__builtin_HEXAGON_C2_muxir,"iiii","") +BUILTIN(__builtin_HEXAGON_C2_muxri,"iiii","") +BUILTIN(__builtin_HEXAGON_C2_vmux,"LLiiLLiLLi","") +BUILTIN(__builtin_HEXAGON_C2_mask,"LLii","") +BUILTIN(__builtin_HEXAGON_A2_vcmpbeq,"bLLiLLi","") +BUILTIN(__builtin_HEXAGON_A4_vcmpbeqi,"bLLii","") +BUILTIN(__builtin_HEXAGON_A4_vcmpbeq_any,"bLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vcmpbgtu,"bLLiLLi","") +BUILTIN(__builtin_HEXAGON_A4_vcmpbgtui,"bLLii","") +BUILTIN(__builtin_HEXAGON_A4_vcmpbgt,"bLLiLLi","") +BUILTIN(__builtin_HEXAGON_A4_vcmpbgti,"bLLii","") +BUILTIN(__builtin_HEXAGON_A4_cmpbeq,"bii","") +BUILTIN(__builtin_HEXAGON_A4_cmpbeqi,"bii","") +BUILTIN(__builtin_HEXAGON_A4_cmpbgtu,"bii","") +BUILTIN(__builtin_HEXAGON_A4_cmpbgtui,"bii","") +BUILTIN(__builtin_HEXAGON_A4_cmpbgt,"bii","") +BUILTIN(__builtin_HEXAGON_A4_cmpbgti,"bii","") +BUILTIN(__builtin_HEXAGON_A2_vcmpheq,"bLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vcmphgt,"bLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vcmphgtu,"bLLiLLi","") +BUILTIN(__builtin_HEXAGON_A4_vcmpheqi,"bLLii","") +BUILTIN(__builtin_HEXAGON_A4_vcmphgti,"bLLii","") +BUILTIN(__builtin_HEXAGON_A4_vcmphgtui,"bLLii","") +BUILTIN(__builtin_HEXAGON_A4_cmpheq,"bii","") +BUILTIN(__builtin_HEXAGON_A4_cmphgt,"bii","") +BUILTIN(__builtin_HEXAGON_A4_cmphgtu,"bii","") +BUILTIN(__builtin_HEXAGON_A4_cmpheqi,"bii","") +BUILTIN(__builtin_HEXAGON_A4_cmphgti,"bii","") +BUILTIN(__builtin_HEXAGON_A4_cmphgtui,"bii","") +BUILTIN(__builtin_HEXAGON_A2_vcmpweq,"bLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vcmpwgt,"bLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vcmpwgtu,"bLLiLLi","") +BUILTIN(__builtin_HEXAGON_A4_vcmpweqi,"bLLii","") +BUILTIN(__builtin_HEXAGON_A4_vcmpwgti,"bLLii","") +BUILTIN(__builtin_HEXAGON_A4_vcmpwgtui,"bLLii","") +BUILTIN(__builtin_HEXAGON_A4_boundscheck,"biLLi","") +BUILTIN(__builtin_HEXAGON_A4_tlbmatch,"bLLii","") +BUILTIN(__builtin_HEXAGON_C2_tfrpr,"ii","") +BUILTIN(__builtin_HEXAGON_C2_tfrrp,"bi","") +BUILTIN(__builtin_HEXAGON_C4_fastcorner9,"bii","") +BUILTIN(__builtin_HEXAGON_C4_fastcorner9_not,"bii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hh_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hh_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hl_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hl_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_lh_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_lh_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_ll_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_ll_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hh_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hh_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hl_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hl_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_lh_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_lh_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_ll_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_ll_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hh_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hh_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hl_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hl_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_lh_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_lh_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_ll_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_ll_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hh_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hh_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hl_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hl_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_lh_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_lh_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_ll_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_ll_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_hh_s0,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_hh_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_hl_s0,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_hl_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_lh_s0,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_lh_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_ll_s0,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_ll_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hh_s0,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hh_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hl_s0,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hl_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_lh_s0,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_lh_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_ll_s0,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_ll_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hh_s0,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hh_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hl_s0,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hl_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_lh_s0,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_lh_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_ll_s0,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_ll_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hh_s0,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hh_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hl_s0,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hl_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_lh_s0,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_lh_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_ll_s0,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_ll_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hh_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hh_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hl_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hl_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_lh_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_lh_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_ll_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_ll_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hh_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hh_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hl_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hl_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_lh_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_lh_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_ll_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_ll_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_hh_s0,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_hh_s1,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_hl_s0,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_hl_s1,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_lh_s0,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_lh_s1,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_ll_s0,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_ll_s1,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hh_s0,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hh_s1,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hl_s0,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hl_s1,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_lh_s0,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_lh_s1,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_ll_s0,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_ll_s1,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hh_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hh_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hl_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hl_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_lh_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_lh_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_ll_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_ll_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hh_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hh_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hl_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hl_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_lh_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_lh_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_ll_s0,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_ll_s1,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_hh_s0,"Uiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_hh_s1,"Uiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_hl_s0,"Uiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_hl_s1,"Uiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_lh_s0,"Uiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_lh_s1,"Uiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_ll_s0,"Uiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_ll_s1,"Uiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hh_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hh_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hl_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hl_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_lh_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_lh_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_ll_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_ll_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hh_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hh_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hl_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hl_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_lh_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_lh_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_ll_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_ll_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_hh_s0,"ULLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_hh_s1,"ULLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_hl_s0,"ULLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_hl_s1,"ULLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_lh_s0,"ULLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_lh_s1,"ULLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_ll_s0,"ULLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyud_ll_s1,"ULLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpysmi,"iii","") +BUILTIN(__builtin_HEXAGON_M2_macsip,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_macsin,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_dpmpyss_s0,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_dpmpyss_acc_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_dpmpyss_nac_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_s0,"ULLiii","") +BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_acc_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_nac_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_up,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_up_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpy_up_s1_sat,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpyu_up,"Uiii","") +BUILTIN(__builtin_HEXAGON_M2_mpysu_up,"iii","") +BUILTIN(__builtin_HEXAGON_M2_dpmpyss_rnd_s0,"iii","") +BUILTIN(__builtin_HEXAGON_M4_mac_up_s1_sat,"iiii","") +BUILTIN(__builtin_HEXAGON_M4_nac_up_s1_sat,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_mpyi,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mpyui,"iii","") +BUILTIN(__builtin_HEXAGON_M2_maci,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_acci,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_accii,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_nacci,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_naccii,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_subacc,"iiii","") +BUILTIN(__builtin_HEXAGON_M4_mpyrr_addr,"iiii","") +BUILTIN(__builtin_HEXAGON_M4_mpyri_addr_u2,"iiii","") +BUILTIN(__builtin_HEXAGON_M4_mpyri_addr,"iiii","") +BUILTIN(__builtin_HEXAGON_M4_mpyri_addi,"iiii","") +BUILTIN(__builtin_HEXAGON_M4_mpyrr_addi,"iiii","") +BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s0,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s1,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_vmac2s_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_vmac2s_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_vmpy2su_s0,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_vmpy2su_s1,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_vmac2su_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_vmac2su_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s0pack,"iii","") +BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s1pack,"iii","") +BUILTIN(__builtin_HEXAGON_M2_vmac2,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_vmpy2es_s0,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vmpy2es_s1,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vmac2es_s0,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vmac2es_s1,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vmac2es,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vrmac_s0,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vrmpy_s0,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vdmpyrs_s0,"iLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vdmpyrs_s1,"iLLiLLi","") +BUILTIN(__builtin_HEXAGON_M5_vrmpybuu,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M5_vrmacbuu,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M5_vrmpybsu,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M5_vrmacbsu,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M5_vmpybuu,"LLiii","") +BUILTIN(__builtin_HEXAGON_M5_vmpybsu,"LLiii","") +BUILTIN(__builtin_HEXAGON_M5_vmacbuu,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M5_vmacbsu,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M5_vdmpybsu,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M5_vdmacbsu,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vdmacs_s0,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vdmacs_s1,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vdmpys_s0,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vdmpys_s1,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_cmpyrs_s0,"iii","") +BUILTIN(__builtin_HEXAGON_M2_cmpyrs_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_cmpyrsc_s0,"iii","") +BUILTIN(__builtin_HEXAGON_M2_cmpyrsc_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_cmacs_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_cmacs_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_cmacsc_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_cmacsc_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_cmpys_s0,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_cmpys_s1,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_cmpysc_s0,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_cmpysc_s1,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_cnacs_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_cnacs_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_cnacsc_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_cnacsc_s1,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_vrcmpys_s1,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_M2_vrcmpys_acc_s1,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_M2_vrcmpys_s1rp,"iLLii","") +BUILTIN(__builtin_HEXAGON_M2_mmacls_s0,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmacls_s1,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmachs_s0,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmachs_s1,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmpyl_s0,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmpyl_s1,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmpyh_s0,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmpyh_s1,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmacls_rs0,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmacls_rs1,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmachs_rs0,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmachs_rs1,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmpyl_rs0,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmpyl_rs1,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmpyh_rs0,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmpyh_rs1,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M4_vrmpyeh_s0,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M4_vrmpyeh_s1,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M4_vrmpyeh_acc_s0,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M4_vrmpyeh_acc_s1,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M4_vrmpyoh_s0,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M4_vrmpyoh_s1,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M4_vrmpyoh_acc_s0,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M4_vrmpyoh_acc_s1,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_hmmpyl_rs1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_hmmpyh_rs1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_hmmpyl_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_hmmpyh_s1,"iii","") +BUILTIN(__builtin_HEXAGON_M2_mmaculs_s0,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmaculs_s1,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmacuhs_s0,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmacuhs_s1,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmpyul_s0,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmpyul_s1,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmpyuh_s0,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmpyuh_s1,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmaculs_rs0,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmaculs_rs1,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmacuhs_rs0,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmacuhs_rs1,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmpyul_rs0,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmpyul_rs1,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmpyuh_rs0,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_mmpyuh_rs1,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vrcmaci_s0,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vrcmacr_s0,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vrcmaci_s0c,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vrcmacr_s0c,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_cmaci_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_cmacr_s0,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M2_vrcmpyi_s0,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vrcmpyr_s0,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vrcmpyi_s0c,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vrcmpyr_s0c,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_cmpyi_s0,"LLiii","") +BUILTIN(__builtin_HEXAGON_M2_cmpyr_s0,"LLiii","") +BUILTIN(__builtin_HEXAGON_M4_cmpyi_wh,"iLLii","") +BUILTIN(__builtin_HEXAGON_M4_cmpyr_wh,"iLLii","") +BUILTIN(__builtin_HEXAGON_M4_cmpyi_whc,"iLLii","") +BUILTIN(__builtin_HEXAGON_M4_cmpyr_whc,"iLLii","") +BUILTIN(__builtin_HEXAGON_M2_vcmpy_s0_sat_i,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vcmpy_s0_sat_r,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vcmpy_s1_sat_i,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vcmpy_s1_sat_r,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vcmac_s0_sat_i,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vcmac_s0_sat_r,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_S2_vcrotate,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S4_vrcrotate_acc,"LLiLLiLLiii","") +BUILTIN(__builtin_HEXAGON_S4_vrcrotate,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_S2_vcnegh,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_vrcnegh,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_M4_pmpyw,"LLiii","") +BUILTIN(__builtin_HEXAGON_M4_vpmpyh,"LLiii","") +BUILTIN(__builtin_HEXAGON_M4_pmpyw_acc,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_M4_vpmpyh_acc,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_A2_add,"iii","") +BUILTIN(__builtin_HEXAGON_A2_sub,"iii","") +BUILTIN(__builtin_HEXAGON_A2_addsat,"iii","") +BUILTIN(__builtin_HEXAGON_A2_subsat,"iii","") +BUILTIN(__builtin_HEXAGON_A2_addi,"iii","") +BUILTIN(__builtin_HEXAGON_A2_addh_l16_ll,"iii","") +BUILTIN(__builtin_HEXAGON_A2_addh_l16_hl,"iii","") +BUILTIN(__builtin_HEXAGON_A2_addh_l16_sat_ll,"iii","") +BUILTIN(__builtin_HEXAGON_A2_addh_l16_sat_hl,"iii","") +BUILTIN(__builtin_HEXAGON_A2_subh_l16_ll,"iii","") +BUILTIN(__builtin_HEXAGON_A2_subh_l16_hl,"iii","") +BUILTIN(__builtin_HEXAGON_A2_subh_l16_sat_ll,"iii","") +BUILTIN(__builtin_HEXAGON_A2_subh_l16_sat_hl,"iii","") +BUILTIN(__builtin_HEXAGON_A2_addh_h16_ll,"iii","") +BUILTIN(__builtin_HEXAGON_A2_addh_h16_lh,"iii","") +BUILTIN(__builtin_HEXAGON_A2_addh_h16_hl,"iii","") +BUILTIN(__builtin_HEXAGON_A2_addh_h16_hh,"iii","") +BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_ll,"iii","") +BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_lh,"iii","") +BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_hl,"iii","") +BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_hh,"iii","") +BUILTIN(__builtin_HEXAGON_A2_subh_h16_ll,"iii","") +BUILTIN(__builtin_HEXAGON_A2_subh_h16_lh,"iii","") +BUILTIN(__builtin_HEXAGON_A2_subh_h16_hl,"iii","") +BUILTIN(__builtin_HEXAGON_A2_subh_h16_hh,"iii","") +BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_ll,"iii","") +BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_lh,"iii","") +BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_hl,"iii","") +BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_hh,"iii","") +BUILTIN(__builtin_HEXAGON_A2_aslh,"ii","") +BUILTIN(__builtin_HEXAGON_A2_asrh,"ii","") +BUILTIN(__builtin_HEXAGON_A2_addp,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_addpsat,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_addsp,"LLiiLLi","") +BUILTIN(__builtin_HEXAGON_A2_subp,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_neg,"ii","") +BUILTIN(__builtin_HEXAGON_A2_negsat,"ii","") +BUILTIN(__builtin_HEXAGON_A2_abs,"ii","") +BUILTIN(__builtin_HEXAGON_A2_abssat,"ii","") +BUILTIN(__builtin_HEXAGON_A2_vconj,"LLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_negp,"LLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_absp,"LLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_max,"iii","") +BUILTIN(__builtin_HEXAGON_A2_maxu,"Uiii","") +BUILTIN(__builtin_HEXAGON_A2_min,"iii","") +BUILTIN(__builtin_HEXAGON_A2_minu,"Uiii","") +BUILTIN(__builtin_HEXAGON_A2_maxp,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_maxup,"ULLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_minp,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_minup,"ULLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_tfr,"ii","") +BUILTIN(__builtin_HEXAGON_A2_tfrsi,"ii","") +BUILTIN(__builtin_HEXAGON_A2_tfrp,"LLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_tfrpi,"LLii","") +BUILTIN(__builtin_HEXAGON_A2_zxtb,"ii","") +BUILTIN(__builtin_HEXAGON_A2_sxtb,"ii","") +BUILTIN(__builtin_HEXAGON_A2_zxth,"ii","") +BUILTIN(__builtin_HEXAGON_A2_sxth,"ii","") +BUILTIN(__builtin_HEXAGON_A2_combinew,"LLiii","") +BUILTIN(__builtin_HEXAGON_A4_combineri,"LLiii","") +BUILTIN(__builtin_HEXAGON_A4_combineir,"LLiii","") +BUILTIN(__builtin_HEXAGON_A2_combineii,"LLiii","") +BUILTIN(__builtin_HEXAGON_A2_combine_hh,"iii","") +BUILTIN(__builtin_HEXAGON_A2_combine_hl,"iii","") +BUILTIN(__builtin_HEXAGON_A2_combine_lh,"iii","") +BUILTIN(__builtin_HEXAGON_A2_combine_ll,"iii","") +BUILTIN(__builtin_HEXAGON_A2_tfril,"iii","") +BUILTIN(__builtin_HEXAGON_A2_tfrih,"iii","") +BUILTIN(__builtin_HEXAGON_A2_and,"iii","") +BUILTIN(__builtin_HEXAGON_A2_or,"iii","") +BUILTIN(__builtin_HEXAGON_A2_xor,"iii","") +BUILTIN(__builtin_HEXAGON_A2_not,"ii","") +BUILTIN(__builtin_HEXAGON_M2_xor_xacc,"iiii","") +BUILTIN(__builtin_HEXAGON_M4_xor_xacc,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A4_andn,"iii","") +BUILTIN(__builtin_HEXAGON_A4_orn,"iii","") +BUILTIN(__builtin_HEXAGON_A4_andnp,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A4_ornp,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_S4_addaddi,"iiii","") +BUILTIN(__builtin_HEXAGON_S4_subaddi,"iiii","") +BUILTIN(__builtin_HEXAGON_M4_and_and,"iiii","") +BUILTIN(__builtin_HEXAGON_M4_and_andn,"iiii","") +BUILTIN(__builtin_HEXAGON_M4_and_or,"iiii","") +BUILTIN(__builtin_HEXAGON_M4_and_xor,"iiii","") +BUILTIN(__builtin_HEXAGON_M4_or_and,"iiii","") +BUILTIN(__builtin_HEXAGON_M4_or_andn,"iiii","") +BUILTIN(__builtin_HEXAGON_M4_or_or,"iiii","") +BUILTIN(__builtin_HEXAGON_M4_or_xor,"iiii","") +BUILTIN(__builtin_HEXAGON_S4_or_andix,"iiii","") +BUILTIN(__builtin_HEXAGON_S4_or_andi,"iiii","") +BUILTIN(__builtin_HEXAGON_S4_or_ori,"iiii","") +BUILTIN(__builtin_HEXAGON_M4_xor_and,"iiii","") +BUILTIN(__builtin_HEXAGON_M4_xor_or,"iiii","") +BUILTIN(__builtin_HEXAGON_M4_xor_andn,"iiii","") +BUILTIN(__builtin_HEXAGON_A2_subri,"iii","") +BUILTIN(__builtin_HEXAGON_A2_andir,"iii","") +BUILTIN(__builtin_HEXAGON_A2_orir,"iii","") +BUILTIN(__builtin_HEXAGON_A2_andp,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_orp,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_xorp,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_notp,"LLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_sxtw,"LLii","") +BUILTIN(__builtin_HEXAGON_A2_sat,"iLLi","") +BUILTIN(__builtin_HEXAGON_A2_roundsat,"iLLi","") +BUILTIN(__builtin_HEXAGON_A2_sath,"ii","") +BUILTIN(__builtin_HEXAGON_A2_satuh,"ii","") +BUILTIN(__builtin_HEXAGON_A2_satub,"ii","") +BUILTIN(__builtin_HEXAGON_A2_satb,"ii","") +BUILTIN(__builtin_HEXAGON_A2_vaddub,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vaddb_map,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vaddubs,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vaddh,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vaddhs,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vadduhs,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A5_vaddhubs,"iLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vaddw,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vaddws,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_S4_vxaddsubw,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_S4_vxsubaddw,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_S4_vxaddsubh,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_S4_vxsubaddh,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_S4_vxaddsubhr,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_S4_vxsubaddhr,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_svavgh,"iii","") +BUILTIN(__builtin_HEXAGON_A2_svavghs,"iii","") +BUILTIN(__builtin_HEXAGON_A2_svnavgh,"iii","") +BUILTIN(__builtin_HEXAGON_A2_svaddh,"iii","") +BUILTIN(__builtin_HEXAGON_A2_svaddhs,"iii","") +BUILTIN(__builtin_HEXAGON_A2_svadduhs,"iii","") +BUILTIN(__builtin_HEXAGON_A2_svsubh,"iii","") +BUILTIN(__builtin_HEXAGON_A2_svsubhs,"iii","") +BUILTIN(__builtin_HEXAGON_A2_svsubuhs,"iii","") +BUILTIN(__builtin_HEXAGON_A2_vraddub,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vraddub_acc,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vraddh,"iLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vradduh,"iLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vsubub,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vsubb_map,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vsububs,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vsubh,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vsubhs,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vsubuhs,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vsubw,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vsubws,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vabsh,"LLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vabshsat,"LLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vabsw,"LLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vabswsat,"LLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vabsdiffw,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_M2_vabsdiffh,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vrsadub,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vrsadub_acc,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vavgub,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vavguh,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vavgh,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vnavgh,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vavgw,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vnavgw,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vavgwr,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vnavgwr,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vavgwcr,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vnavgwcr,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vavghcr,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vnavghcr,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vavguw,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vavguwr,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vavgubr,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vavguhr,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vavghr,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vnavghr,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A4_round_ri,"iii","") +BUILTIN(__builtin_HEXAGON_A4_round_rr,"iii","") +BUILTIN(__builtin_HEXAGON_A4_round_ri_sat,"iii","") +BUILTIN(__builtin_HEXAGON_A4_round_rr_sat,"iii","") +BUILTIN(__builtin_HEXAGON_A4_cround_ri,"iii","") +BUILTIN(__builtin_HEXAGON_A4_cround_rr,"iii","") +BUILTIN(__builtin_HEXAGON_A4_vrminh,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_A4_vrmaxh,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_A4_vrminuh,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_A4_vrmaxuh,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_A4_vrminw,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_A4_vrmaxw,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_A4_vrminuw,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_A4_vrmaxuw,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_A2_vminb,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vmaxb,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vminub,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vmaxub,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vminh,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vmaxh,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vminuh,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vmaxuh,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vminw,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vmaxw,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vminuw,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A2_vmaxuw,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_A4_modwrapu,"iii","") +BUILTIN(__builtin_HEXAGON_F2_sfadd,"fff","") +BUILTIN(__builtin_HEXAGON_F2_sfsub,"fff","") +BUILTIN(__builtin_HEXAGON_F2_sfmpy,"fff","") +BUILTIN(__builtin_HEXAGON_F2_sffma,"ffff","") +BUILTIN(__builtin_HEXAGON_F2_sffma_sc,"ffffi","") +BUILTIN(__builtin_HEXAGON_F2_sffms,"ffff","") +BUILTIN(__builtin_HEXAGON_F2_sffma_lib,"ffff","") +BUILTIN(__builtin_HEXAGON_F2_sffms_lib,"ffff","") +BUILTIN(__builtin_HEXAGON_F2_sfcmpeq,"bff","") +BUILTIN(__builtin_HEXAGON_F2_sfcmpgt,"bff","") +BUILTIN(__builtin_HEXAGON_F2_sfcmpge,"bff","") +BUILTIN(__builtin_HEXAGON_F2_sfcmpuo,"bff","") +BUILTIN(__builtin_HEXAGON_F2_sfmax,"fff","") +BUILTIN(__builtin_HEXAGON_F2_sfmin,"fff","") +BUILTIN(__builtin_HEXAGON_F2_sfclass,"bfi","") +BUILTIN(__builtin_HEXAGON_F2_sfimm_p,"fi","") +BUILTIN(__builtin_HEXAGON_F2_sfimm_n,"fi","") +BUILTIN(__builtin_HEXAGON_F2_sffixupn,"fff","") +BUILTIN(__builtin_HEXAGON_F2_sffixupd,"fff","") +BUILTIN(__builtin_HEXAGON_F2_sffixupr,"ff","") +BUILTIN(__builtin_HEXAGON_F2_dfadd,"ddd","") +BUILTIN(__builtin_HEXAGON_F2_dfsub,"ddd","") +BUILTIN(__builtin_HEXAGON_F2_dfmpy,"ddd","") +BUILTIN(__builtin_HEXAGON_F2_dffma,"dddd","") +BUILTIN(__builtin_HEXAGON_F2_dffms,"dddd","") +BUILTIN(__builtin_HEXAGON_F2_dffma_lib,"dddd","") +BUILTIN(__builtin_HEXAGON_F2_dffms_lib,"dddd","") +BUILTIN(__builtin_HEXAGON_F2_dffma_sc,"ddddi","") +BUILTIN(__builtin_HEXAGON_F2_dfmax,"ddd","") +BUILTIN(__builtin_HEXAGON_F2_dfmin,"ddd","") +BUILTIN(__builtin_HEXAGON_F2_dfcmpeq,"bdd","") +BUILTIN(__builtin_HEXAGON_F2_dfcmpgt,"bdd","") +BUILTIN(__builtin_HEXAGON_F2_dfcmpge,"bdd","") +BUILTIN(__builtin_HEXAGON_F2_dfcmpuo,"bdd","") +BUILTIN(__builtin_HEXAGON_F2_dfclass,"bdi","") +BUILTIN(__builtin_HEXAGON_F2_dfimm_p,"di","") +BUILTIN(__builtin_HEXAGON_F2_dfimm_n,"di","") +BUILTIN(__builtin_HEXAGON_F2_dffixupn,"ddd","") +BUILTIN(__builtin_HEXAGON_F2_dffixupd,"ddd","") +BUILTIN(__builtin_HEXAGON_F2_dffixupr,"dd","") +BUILTIN(__builtin_HEXAGON_F2_conv_sf2df,"df","") +BUILTIN(__builtin_HEXAGON_F2_conv_df2sf,"fd","") +BUILTIN(__builtin_HEXAGON_F2_conv_uw2sf,"fi","") +BUILTIN(__builtin_HEXAGON_F2_conv_uw2df,"di","") +BUILTIN(__builtin_HEXAGON_F2_conv_w2sf,"fi","") +BUILTIN(__builtin_HEXAGON_F2_conv_w2df,"di","") +BUILTIN(__builtin_HEXAGON_F2_conv_ud2sf,"fLLi","") +BUILTIN(__builtin_HEXAGON_F2_conv_ud2df,"dLLi","") +BUILTIN(__builtin_HEXAGON_F2_conv_d2sf,"fLLi","") +BUILTIN(__builtin_HEXAGON_F2_conv_d2df,"dLLi","") +BUILTIN(__builtin_HEXAGON_F2_conv_sf2uw,"if","") +BUILTIN(__builtin_HEXAGON_F2_conv_sf2w,"if","") +BUILTIN(__builtin_HEXAGON_F2_conv_sf2ud,"LLif","") +BUILTIN(__builtin_HEXAGON_F2_conv_sf2d,"LLif","") +BUILTIN(__builtin_HEXAGON_F2_conv_df2uw,"id","") +BUILTIN(__builtin_HEXAGON_F2_conv_df2w,"id","") +BUILTIN(__builtin_HEXAGON_F2_conv_df2ud,"LLid","") +BUILTIN(__builtin_HEXAGON_F2_conv_df2d,"LLid","") +BUILTIN(__builtin_HEXAGON_F2_conv_sf2uw_chop,"if","") +BUILTIN(__builtin_HEXAGON_F2_conv_sf2w_chop,"if","") +BUILTIN(__builtin_HEXAGON_F2_conv_sf2ud_chop,"LLif","") +BUILTIN(__builtin_HEXAGON_F2_conv_sf2d_chop,"LLif","") +BUILTIN(__builtin_HEXAGON_F2_conv_df2uw_chop,"id","") +BUILTIN(__builtin_HEXAGON_F2_conv_df2w_chop,"id","") +BUILTIN(__builtin_HEXAGON_F2_conv_df2ud_chop,"LLid","") +BUILTIN(__builtin_HEXAGON_F2_conv_df2d_chop,"LLid","") +BUILTIN(__builtin_HEXAGON_S2_asr_r_r,"iii","") +BUILTIN(__builtin_HEXAGON_S2_asl_r_r,"iii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_r,"iii","") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_r,"iii","") +BUILTIN(__builtin_HEXAGON_S2_asr_r_p,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asl_r_p,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_p,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_p,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asr_r_r_acc,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_asl_r_r_acc,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_acc,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_acc,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_asr_r_p_acc,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asl_r_p_acc,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_acc,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_acc,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asr_r_r_nac,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_asl_r_r_nac,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_nac,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_nac,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_asr_r_p_nac,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asl_r_p_nac,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_nac,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_nac,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asr_r_r_and,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_asl_r_r_and,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_and,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_and,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_asr_r_r_or,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_asl_r_r_or,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_or,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_or,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_asr_r_p_and,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asl_r_p_and,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_and,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_and,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asr_r_p_or,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asl_r_p_or,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_or,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_or,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asr_r_p_xor,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asl_r_p_xor,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_xor,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_xor,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asr_r_r_sat,"iii","") +BUILTIN(__builtin_HEXAGON_S2_asl_r_r_sat,"iii","") +BUILTIN(__builtin_HEXAGON_S2_asr_i_r,"iii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_r,"iii","") +BUILTIN(__builtin_HEXAGON_S2_asl_i_r,"iii","") +BUILTIN(__builtin_HEXAGON_S2_asr_i_p,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_p,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asl_i_p,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asr_i_r_acc,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_acc,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_asl_i_r_acc,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_asr_i_p_acc,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_acc,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asl_i_p_acc,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asr_i_r_nac,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_nac,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_asl_i_r_nac,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_asr_i_p_nac,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_nac,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asl_i_p_nac,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_xacc,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_asl_i_r_xacc,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_xacc,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asl_i_p_xacc,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asr_i_r_and,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_and,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_asl_i_r_and,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_asr_i_r_or,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_or,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_asl_i_r_or,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_asr_i_p_and,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_and,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asl_i_p_and,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asr_i_p_or,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_or,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asl_i_p_or,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asl_i_r_sat,"iii","") +BUILTIN(__builtin_HEXAGON_S2_asr_i_r_rnd,"iii","") +BUILTIN(__builtin_HEXAGON_S2_asr_i_r_rnd_goodsyntax,"iii","") +BUILTIN(__builtin_HEXAGON_S2_asr_i_p_rnd,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asr_i_p_rnd_goodsyntax,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S4_lsli,"iii","") +BUILTIN(__builtin_HEXAGON_S2_addasl_rrri,"iiii","") +BUILTIN(__builtin_HEXAGON_S4_andi_asl_ri,"iiii","") +BUILTIN(__builtin_HEXAGON_S4_ori_asl_ri,"iiii","") +BUILTIN(__builtin_HEXAGON_S4_addi_asl_ri,"iiii","") +BUILTIN(__builtin_HEXAGON_S4_subi_asl_ri,"iiii","") +BUILTIN(__builtin_HEXAGON_S4_andi_lsr_ri,"iiii","") +BUILTIN(__builtin_HEXAGON_S4_ori_lsr_ri,"iiii","") +BUILTIN(__builtin_HEXAGON_S4_addi_lsr_ri,"iiii","") +BUILTIN(__builtin_HEXAGON_S4_subi_lsr_ri,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_valignib,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_valignrb,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_vspliceib,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_vsplicerb,"LLiLLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_vsplatrh,"LLii","") +BUILTIN(__builtin_HEXAGON_S2_vsplatrb,"ii","") +BUILTIN(__builtin_HEXAGON_S2_insert,"iiiii","") +BUILTIN(__builtin_HEXAGON_S2_tableidxb_goodsyntax,"iiiii","") +BUILTIN(__builtin_HEXAGON_S2_tableidxh_goodsyntax,"iiiii","") +BUILTIN(__builtin_HEXAGON_S2_tableidxw_goodsyntax,"iiiii","") +BUILTIN(__builtin_HEXAGON_S2_tableidxd_goodsyntax,"iiiii","") +BUILTIN(__builtin_HEXAGON_A4_bitspliti,"LLiii","") +BUILTIN(__builtin_HEXAGON_A4_bitsplit,"LLiii","") +BUILTIN(__builtin_HEXAGON_S4_extract,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_extractu,"iiii","") +BUILTIN(__builtin_HEXAGON_S2_insertp,"LLiLLiLLiii","") +BUILTIN(__builtin_HEXAGON_S4_extractp,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_S2_extractup,"LLiLLiii","") +BUILTIN(__builtin_HEXAGON_S2_insert_rp,"iiiLLi","") +BUILTIN(__builtin_HEXAGON_S4_extract_rp,"iiLLi","") +BUILTIN(__builtin_HEXAGON_S2_extractu_rp,"iiLLi","") +BUILTIN(__builtin_HEXAGON_S2_insertp_rp,"LLiLLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_S4_extractp_rp,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_S2_extractup_rp,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_S2_tstbit_i,"bii","") +BUILTIN(__builtin_HEXAGON_S4_ntstbit_i,"bii","") +BUILTIN(__builtin_HEXAGON_S2_setbit_i,"iii","") +BUILTIN(__builtin_HEXAGON_S2_togglebit_i,"iii","") +BUILTIN(__builtin_HEXAGON_S2_clrbit_i,"iii","") +BUILTIN(__builtin_HEXAGON_S2_tstbit_r,"bii","") +BUILTIN(__builtin_HEXAGON_S4_ntstbit_r,"bii","") +BUILTIN(__builtin_HEXAGON_S2_setbit_r,"iii","") +BUILTIN(__builtin_HEXAGON_S2_togglebit_r,"iii","") +BUILTIN(__builtin_HEXAGON_S2_clrbit_r,"iii","") +BUILTIN(__builtin_HEXAGON_S2_asr_i_vh,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_vh,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asl_i_vh,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asr_r_vh,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S5_asrhub_rnd_sat_goodsyntax,"iLLii","") +BUILTIN(__builtin_HEXAGON_S5_asrhub_sat,"iLLii","") +BUILTIN(__builtin_HEXAGON_S5_vasrhrnd_goodsyntax,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asl_r_vh,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_vh,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_vh,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asr_i_vw,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asr_i_svw_trun,"iLLii","") +BUILTIN(__builtin_HEXAGON_S2_asr_r_svw_trun,"iLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_i_vw,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asl_i_vw,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asr_r_vw,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_asl_r_vw,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsr_r_vw,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_lsl_r_vw,"LLiLLii","") +BUILTIN(__builtin_HEXAGON_S2_vrndpackwh,"iLLi","") +BUILTIN(__builtin_HEXAGON_S2_vrndpackwhs,"iLLi","") +BUILTIN(__builtin_HEXAGON_S2_vsxtbh,"LLii","") +BUILTIN(__builtin_HEXAGON_S2_vzxtbh,"LLii","") +BUILTIN(__builtin_HEXAGON_S2_vsathub,"iLLi","") +BUILTIN(__builtin_HEXAGON_S2_svsathub,"ii","") +BUILTIN(__builtin_HEXAGON_S2_svsathb,"ii","") +BUILTIN(__builtin_HEXAGON_S2_vsathb,"iLLi","") +BUILTIN(__builtin_HEXAGON_S2_vtrunohb,"iLLi","") +BUILTIN(__builtin_HEXAGON_S2_vtrunewh,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_S2_vtrunowh,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_S2_vtrunehb,"iLLi","") +BUILTIN(__builtin_HEXAGON_S2_vsxthw,"LLii","") +BUILTIN(__builtin_HEXAGON_S2_vzxthw,"LLii","") +BUILTIN(__builtin_HEXAGON_S2_vsatwh,"iLLi","") +BUILTIN(__builtin_HEXAGON_S2_vsatwuh,"iLLi","") +BUILTIN(__builtin_HEXAGON_S2_packhl,"LLiii","") +BUILTIN(__builtin_HEXAGON_A2_swiz,"ii","") +BUILTIN(__builtin_HEXAGON_S2_vsathub_nopack,"LLiLLi","") +BUILTIN(__builtin_HEXAGON_S2_vsathb_nopack,"LLiLLi","") +BUILTIN(__builtin_HEXAGON_S2_vsatwh_nopack,"LLiLLi","") +BUILTIN(__builtin_HEXAGON_S2_vsatwuh_nopack,"LLiLLi","") +BUILTIN(__builtin_HEXAGON_S2_shuffob,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_S2_shuffeb,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_S2_shuffoh,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_S2_shuffeh,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_S5_popcountp,"iLLi","") +BUILTIN(__builtin_HEXAGON_S4_parity,"iii","") +BUILTIN(__builtin_HEXAGON_S2_parityp,"iLLiLLi","") +BUILTIN(__builtin_HEXAGON_S2_lfsp,"LLiLLiLLi","") +BUILTIN(__builtin_HEXAGON_S2_clbnorm,"ii","") +BUILTIN(__builtin_HEXAGON_S4_clbaddi,"iii","") +BUILTIN(__builtin_HEXAGON_S4_clbpnorm,"iLLi","") +BUILTIN(__builtin_HEXAGON_S4_clbpaddi,"iLLii","") +BUILTIN(__builtin_HEXAGON_S2_clb,"ii","") +BUILTIN(__builtin_HEXAGON_S2_cl0,"ii","") +BUILTIN(__builtin_HEXAGON_S2_cl1,"ii","") +BUILTIN(__builtin_HEXAGON_S2_clbp,"iLLi","") +BUILTIN(__builtin_HEXAGON_S2_cl0p,"iLLi","") +BUILTIN(__builtin_HEXAGON_S2_cl1p,"iLLi","") +BUILTIN(__builtin_HEXAGON_S2_brev,"ii","") +BUILTIN(__builtin_HEXAGON_S2_brevp,"LLiLLi","") +BUILTIN(__builtin_HEXAGON_S2_ct0,"ii","") +BUILTIN(__builtin_HEXAGON_S2_ct1,"ii","") +BUILTIN(__builtin_HEXAGON_S2_ct0p,"iLLi","") +BUILTIN(__builtin_HEXAGON_S2_ct1p,"iLLi","") +BUILTIN(__builtin_HEXAGON_S2_interleave,"LLiLLi","") +BUILTIN(__builtin_HEXAGON_S2_deinterleave,"LLiLLi","") #undef BUILTIN diff --git a/include/clang/Basic/BuiltinsMips.def b/include/clang/Basic/BuiltinsMips.def new file mode 100644 index 0000000..d013715 --- /dev/null +++ b/include/clang/Basic/BuiltinsMips.def @@ -0,0 +1,125 @@ +//===-- BuiltinsMips.def - Mips Builtin function database --------*- 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 MIPS-specific builtin function database. Users of +// this file must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +// The format of this database matches clang/Basic/Builtins.def. + +// Add/subtract with optional saturation +BUILTIN(__builtin_mips_addu_qb, "V4ScV4ScV4Sc", "n") +BUILTIN(__builtin_mips_addu_s_qb, "V4ScV4ScV4Sc", "n") +BUILTIN(__builtin_mips_subu_qb, "V4ScV4ScV4Sc", "n") +BUILTIN(__builtin_mips_subu_s_qb, "V4ScV4ScV4Sc", "n") + +BUILTIN(__builtin_mips_addq_ph, "V2sV2sV2s", "n") +BUILTIN(__builtin_mips_addq_s_ph, "V2sV2sV2s", "n") +BUILTIN(__builtin_mips_subq_ph, "V2sV2sV2s", "n") +BUILTIN(__builtin_mips_subq_s_ph, "V2sV2sV2s", "n") + +BUILTIN(__builtin_mips_madd, "LLiLLiii", "nc") +BUILTIN(__builtin_mips_maddu, "LLiLLiUiUi", "nc") +BUILTIN(__builtin_mips_msub, "LLiLLiii", "nc") +BUILTIN(__builtin_mips_msubu, "LLiLLiUiUi", "nc") + +BUILTIN(__builtin_mips_addq_s_w, "iii", "n") +BUILTIN(__builtin_mips_subq_s_w, "iii", "n") + +BUILTIN(__builtin_mips_addsc, "iii", "n") +BUILTIN(__builtin_mips_addwc, "iii", "n") + +BUILTIN(__builtin_mips_modsub, "iii", "nc") + +BUILTIN(__builtin_mips_raddu_w_qb, "iV4Sc", "nc") + +BUILTIN(__builtin_mips_absq_s_ph, "V2sV2s", "n") +BUILTIN(__builtin_mips_absq_s_w, "ii", "n") + +BUILTIN(__builtin_mips_precrq_qb_ph, "V4ScV2sV2s", "nc") +BUILTIN(__builtin_mips_precrqu_s_qb_ph, "V4ScV2sV2s", "n") +BUILTIN(__builtin_mips_precrq_ph_w, "V2sii", "nc") +BUILTIN(__builtin_mips_precrq_rs_ph_w, "V2sii", "n") +BUILTIN(__builtin_mips_preceq_w_phl, "iV2s", "nc") +BUILTIN(__builtin_mips_preceq_w_phr, "iV2s", "nc") +BUILTIN(__builtin_mips_precequ_ph_qbl, "V2sV4Sc", "nc") +BUILTIN(__builtin_mips_precequ_ph_qbr, "V2sV4Sc", "nc") +BUILTIN(__builtin_mips_precequ_ph_qbla, "V2sV4Sc", "nc") +BUILTIN(__builtin_mips_precequ_ph_qbra, "V2sV4Sc", "nc") +BUILTIN(__builtin_mips_preceu_ph_qbl, "V2sV4Sc", "nc") +BUILTIN(__builtin_mips_preceu_ph_qbr, "V2sV4Sc", "nc") +BUILTIN(__builtin_mips_preceu_ph_qbla, "V2sV4Sc", "nc") +BUILTIN(__builtin_mips_preceu_ph_qbra, "V2sV4Sc", "nc") + +BUILTIN(__builtin_mips_shll_qb, "V4ScV4Sci", "n") +BUILTIN(__builtin_mips_shrl_qb, "V4ScV4Sci", "nc") +BUILTIN(__builtin_mips_shll_ph, "V2sV2si", "n") +BUILTIN(__builtin_mips_shll_s_ph, "V2sV2si", "n") +BUILTIN(__builtin_mips_shra_ph, "V2sV2si", "nc") +BUILTIN(__builtin_mips_shra_r_ph, "V2sV2si", "nc") +BUILTIN(__builtin_mips_shll_s_w, "iii", "n") +BUILTIN(__builtin_mips_shra_r_w, "iii", "nc") +BUILTIN(__builtin_mips_shilo, "LLiLLii", "nc") + +BUILTIN(__builtin_mips_muleu_s_ph_qbl, "V2sV4ScV2s", "n") +BUILTIN(__builtin_mips_muleu_s_ph_qbr, "V2sV4ScV2s", "n") +BUILTIN(__builtin_mips_mulq_rs_ph, "V2sV2sV2s", "n") +BUILTIN(__builtin_mips_muleq_s_w_phl, "iV2sV2s", "n") +BUILTIN(__builtin_mips_muleq_s_w_phr, "iV2sV2s", "n") +BUILTIN(__builtin_mips_mulsaq_s_w_ph, "LLiLLiV2sV2s", "n") +BUILTIN(__builtin_mips_maq_s_w_phl, "LLiLLiV2sV2s", "n") +BUILTIN(__builtin_mips_maq_s_w_phr, "LLiLLiV2sV2s", "n") +BUILTIN(__builtin_mips_maq_sa_w_phl, "LLiLLiV2sV2s", "n") +BUILTIN(__builtin_mips_maq_sa_w_phr, "LLiLLiV2sV2s", "n") +BUILTIN(__builtin_mips_mult, "LLiii", "nc") +BUILTIN(__builtin_mips_multu, "LLiUiUi", "nc") + +BUILTIN(__builtin_mips_dpau_h_qbl, "LLiLLiV4ScV4Sc", "nc") +BUILTIN(__builtin_mips_dpau_h_qbr, "LLiLLiV4ScV4Sc", "nc") +BUILTIN(__builtin_mips_dpsu_h_qbl, "LLiLLiV4ScV4Sc", "nc") +BUILTIN(__builtin_mips_dpsu_h_qbr, "LLiLLiV4ScV4Sc", "nc") +BUILTIN(__builtin_mips_dpaq_s_w_ph, "LLiLLiV2sV2s", "n") +BUILTIN(__builtin_mips_dpsq_s_w_ph, "LLiLLiV2sV2s", "n") +BUILTIN(__builtin_mips_dpaq_sa_l_w, "LLiLLiii", "n") +BUILTIN(__builtin_mips_dpsq_sa_l_w, "LLiLLiii", "n") + +BUILTIN(__builtin_mips_cmpu_eq_qb, "vV4ScV4Sc", "n") +BUILTIN(__builtin_mips_cmpu_lt_qb, "vV4ScV4Sc", "n") +BUILTIN(__builtin_mips_cmpu_le_qb, "vV4ScV4Sc", "n") +BUILTIN(__builtin_mips_cmpgu_eq_qb, "iV4ScV4Sc", "n") +BUILTIN(__builtin_mips_cmpgu_lt_qb, "iV4ScV4Sc", "n") +BUILTIN(__builtin_mips_cmpgu_le_qb, "iV4ScV4Sc", "n") +BUILTIN(__builtin_mips_cmp_eq_ph, "vV2sV2s", "n") +BUILTIN(__builtin_mips_cmp_lt_ph, "vV2sV2s", "n") +BUILTIN(__builtin_mips_cmp_le_ph, "vV2sV2s", "n") + +BUILTIN(__builtin_mips_extr_s_h, "iLLii", "n") +BUILTIN(__builtin_mips_extr_w, "iLLii", "n") +BUILTIN(__builtin_mips_extr_rs_w, "iLLii", "n") +BUILTIN(__builtin_mips_extr_r_w, "iLLii", "n") +BUILTIN(__builtin_mips_extp, "iLLii", "n") +BUILTIN(__builtin_mips_extpdp, "iLLii", "n") + +BUILTIN(__builtin_mips_wrdsp, "viIi", "n") +BUILTIN(__builtin_mips_rddsp, "iIi", "n") +BUILTIN(__builtin_mips_insv, "iii", "n") +BUILTIN(__builtin_mips_bitrev, "ii", "nc") +BUILTIN(__builtin_mips_packrl_ph, "V2sV2sV2s", "nc") +BUILTIN(__builtin_mips_repl_qb, "V4Sci", "nc") +BUILTIN(__builtin_mips_repl_ph, "V2si", "nc") +BUILTIN(__builtin_mips_pick_qb, "V4ScV4ScV4Sc", "n") +BUILTIN(__builtin_mips_pick_ph, "V2sV2sV2s", "n") +BUILTIN(__builtin_mips_mthlip, "LLiLLii", "n") +BUILTIN(__builtin_mips_bposge32, "i", "n") +BUILTIN(__builtin_mips_lbux, "iv*i", "n") +BUILTIN(__builtin_mips_lhx, "iv*i", "n") +BUILTIN(__builtin_mips_lwx, "iv*i", "n") + +#undef BUILTIN diff --git a/include/clang/Basic/BuiltinsPTX.def b/include/clang/Basic/BuiltinsNVPTX.def index f90a43f..f90a43f 100644 --- a/include/clang/Basic/BuiltinsPTX.def +++ b/include/clang/Basic/BuiltinsNVPTX.def diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 4aea980..75e6074 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -303,8 +303,6 @@ BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "") BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cIc", "") BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "") -BUILTIN(__builtin_ia32_storelv4si, "vV2i*V2LLi", "") - BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "") BUILTIN(__builtin_ia32_pblendw128, "V8sV8sV8sIi", "") BUILTIN(__builtin_ia32_blendpd, "V2dV2dV2dIi", "") @@ -354,23 +352,30 @@ BUILTIN(__builtin_ia32_pcmpistri128, "iV16cV16cIc", "") BUILTIN(__builtin_ia32_pcmpestrm128, "V16cV16ciV16ciIc", "") BUILTIN(__builtin_ia32_pcmpestri128, "iV16ciV16ciIc","") -// FIXME: These builtins are horribly broken; reenable when PR11305 is fixed. -//BUILTIN(__builtin_ia32_pcmpistria128, "iV16cV16cIc","") -//BUILTIN(__builtin_ia32_pcmpistric128, "iV16cV16cIc","") -//BUILTIN(__builtin_ia32_pcmpistrio128, "iV16cV16cIc","") -//BUILTIN(__builtin_ia32_pcmpistris128, "iV16cV16cIc","") -//BUILTIN(__builtin_ia32_pcmpistriz128, "iV16cV16cIc","") -//BUILTIN(__builtin_ia32_pcmpestria128, "iV16ciV16ciIc","") -//BUILTIN(__builtin_ia32_pcmpestric128, "iV16ciV16ciIc","") -//BUILTIN(__builtin_ia32_pcmpestrio128, "iV16ciV16ciic","") -//BUILTIN(__builtin_ia32_pcmpestris128, "iV16ciV16ciIc","") -//BUILTIN(__builtin_ia32_pcmpestriz128, "iV16ciV16ciIc","") +BUILTIN(__builtin_ia32_pcmpistria128, "iV16cV16cIc","") +BUILTIN(__builtin_ia32_pcmpistric128, "iV16cV16cIc","") +BUILTIN(__builtin_ia32_pcmpistrio128, "iV16cV16cIc","") +BUILTIN(__builtin_ia32_pcmpistris128, "iV16cV16cIc","") +BUILTIN(__builtin_ia32_pcmpistriz128, "iV16cV16cIc","") +BUILTIN(__builtin_ia32_pcmpestria128, "iV16ciV16ciIc","") +BUILTIN(__builtin_ia32_pcmpestric128, "iV16ciV16ciIc","") +BUILTIN(__builtin_ia32_pcmpestrio128, "iV16ciV16ciIc","") +BUILTIN(__builtin_ia32_pcmpestris128, "iV16ciV16ciIc","") +BUILTIN(__builtin_ia32_pcmpestriz128, "iV16ciV16ciIc","") BUILTIN(__builtin_ia32_crc32qi, "UiUiUc", "") BUILTIN(__builtin_ia32_crc32hi, "UiUiUs", "") BUILTIN(__builtin_ia32_crc32si, "UiUiUi", "") BUILTIN(__builtin_ia32_crc32di, "ULLiULLiULLi", "") +// SSE4a +BUILTIN(__builtin_ia32_extrqi, "V2LLiV2LLiIcIc", "") +BUILTIN(__builtin_ia32_extrq, "V2LLiV2LLiV16c", "") +BUILTIN(__builtin_ia32_insertqi, "V2LLiV2LLiV2LLiIcIc", "") +BUILTIN(__builtin_ia32_insertq, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_movntsd, "vd*V2d", "") +BUILTIN(__builtin_ia32_movntss, "vf*V4f", "") + // AES BUILTIN(__builtin_ia32_aesenc128, "V2LLiV2LLiV2LLi", "") BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "") @@ -379,6 +384,9 @@ BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "") BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "") BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLiIc", "") +// CLMUL +BUILTIN(__builtin_ia32_pclmulqdq128, "V2LLiV2LLiV2LLiIc", "") + // AVX BUILTIN(__builtin_ia32_addsubpd256, "V4dV4dV4d", "") BUILTIN(__builtin_ia32_addsubps256, "V8fV8fV8f", "") @@ -586,6 +594,30 @@ BUILTIN(__builtin_ia32_psrlv4si, "V4iV4iV4i", "") BUILTIN(__builtin_ia32_psrlv4di, "V4LLiV4LLiV4LLi", "") BUILTIN(__builtin_ia32_psrlv2di, "V2LLiV2LLiV2LLi", "") +// GATHER +BUILTIN(__builtin_ia32_gatherd_pd, "V2dV2dV2dC*V4iV2dIc", "") +BUILTIN(__builtin_ia32_gatherd_pd256, "V4dV4dV4dC*V4iV4dIc", "") +BUILTIN(__builtin_ia32_gatherq_pd, "V2dV2dV2dC*V2LLiV2dIc", "") +BUILTIN(__builtin_ia32_gatherq_pd256, "V4dV4dV4dC*V4LLiV4dIc", "") +BUILTIN(__builtin_ia32_gatherd_ps, "V4fV4fV4fC*V4iV4fIc", "") +BUILTIN(__builtin_ia32_gatherd_ps256, "V8fV8fV8fC*V8iV8fIc", "") +BUILTIN(__builtin_ia32_gatherq_ps, "V4fV4fV4fC*V2LLiV4fIc", "") +BUILTIN(__builtin_ia32_gatherq_ps256, "V4fV4fV4fC*V4LLiV4fIc", "") + +BUILTIN(__builtin_ia32_gatherd_q, "V2LLiV2LLiV2LLiC*V4iV2LLiIc", "") +BUILTIN(__builtin_ia32_gatherd_q256, "V4LLiV4LLiV4LLiC*V4iV4LLiIc", "") +BUILTIN(__builtin_ia32_gatherq_q, "V2LLiV2LLiV2LLiC*V2LLiV2LLiIc", "") +BUILTIN(__builtin_ia32_gatherq_q256, "V4LLiV4LLiV4LLiC*V4LLiV4LLiIc", "") +BUILTIN(__builtin_ia32_gatherd_d, "V4iV4iV4iC*V4iV4iIc", "") +BUILTIN(__builtin_ia32_gatherd_d256, "V8iV8iV8iC*V8iV8iIc", "") +BUILTIN(__builtin_ia32_gatherq_d, "V4iV4iV4iC*V2LLiV4iIc", "") +BUILTIN(__builtin_ia32_gatherq_d256, "V4iV4iV4iC*V4LLiV4iIc", "") + +// RDRAND +BUILTIN(__builtin_ia32_rdrand16_step, "UiUs*", "") +BUILTIN(__builtin_ia32_rdrand32_step, "UiUi*", "") +BUILTIN(__builtin_ia32_rdrand64_step, "UiULLi*", "") + // BMI BUILTIN(__builtin_ia32_bextr_u32, "UiUiUi", "") BUILTIN(__builtin_ia32_bextr_u64, "ULLiULLiULLi", "") @@ -632,4 +664,71 @@ BUILTIN(__builtin_ia32_vfmaddsubpd256, "V4dV4dV4dV4d", "") BUILTIN(__builtin_ia32_vfmsubaddps256, "V8fV8fV8fV8f", "") BUILTIN(__builtin_ia32_vfmsubaddpd256, "V4dV4dV4dV4d", "") +// XOP +BUILTIN(__builtin_ia32_vpmacssww, "V8sV8sV8sV8s", "") +BUILTIN(__builtin_ia32_vpmacsww, "V8sV8sV8sV8s", "") +BUILTIN(__builtin_ia32_vpmacsswd, "V4iV8sV8sV4i", "") +BUILTIN(__builtin_ia32_vpmacswd, "V4iV8sV8sV4i", "") +BUILTIN(__builtin_ia32_vpmacssdd, "V4iV4iV4iV4i", "") +BUILTIN(__builtin_ia32_vpmacsdd, "V4iV4iV4iV4i", "") +BUILTIN(__builtin_ia32_vpmacssdql, "V2LLiV4iV4iV2LLi", "") +BUILTIN(__builtin_ia32_vpmacsdql, "V2LLiV4iV4iV2LLi", "") +BUILTIN(__builtin_ia32_vpmacssdqh, "V2LLiV4iV4iV2LLi", "") +BUILTIN(__builtin_ia32_vpmacsdqh, "V2LLiV4iV4iV2LLi", "") +BUILTIN(__builtin_ia32_vpmadcsswd, "V4iV8sV8sV4i", "") +BUILTIN(__builtin_ia32_vpmadcswd, "V4iV8sV8sV4i", "") + +BUILTIN(__builtin_ia32_vphaddbw, "V8sV16c", "") +BUILTIN(__builtin_ia32_vphaddbd, "V4iV16c", "") +BUILTIN(__builtin_ia32_vphaddbq, "V2LLiV16c", "") +BUILTIN(__builtin_ia32_vphaddwd, "V4iV8s", "") +BUILTIN(__builtin_ia32_vphaddwq, "V2LLiV8s", "") +BUILTIN(__builtin_ia32_vphadddq, "V2LLiV4i", "") +BUILTIN(__builtin_ia32_vphaddubw, "V8sV16c", "") +BUILTIN(__builtin_ia32_vphaddubd, "V4iV16c", "") +BUILTIN(__builtin_ia32_vphaddubq, "V2LLiV16c", "") +BUILTIN(__builtin_ia32_vphadduwd, "V4iV8s", "") +BUILTIN(__builtin_ia32_vphadduwq, "V2LLiV8s", "") +BUILTIN(__builtin_ia32_vphaddudq, "V2LLiV4i", "") +BUILTIN(__builtin_ia32_vphsubbw, "V8sV16c", "") +BUILTIN(__builtin_ia32_vphsubwd, "V4iV8s", "") +BUILTIN(__builtin_ia32_vphsubdq, "V2LLiV4i", "") +BUILTIN(__builtin_ia32_vpcmov, "V2LLiV2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_vpcmov_256, "V4LLiV4LLiV4LLiV4LLi", "") +BUILTIN(__builtin_ia32_vpperm, "V16cV16cV16cV16c", "") +BUILTIN(__builtin_ia32_vprotb, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_vprotw, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_vprotd, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_vprotq, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_vprotbi, "V16cV16cIc", "") +BUILTIN(__builtin_ia32_vprotwi, "V8sV8sIc", "") +BUILTIN(__builtin_ia32_vprotdi, "V4iV4iIc", "") +BUILTIN(__builtin_ia32_vprotqi, "V2LLiV2LLiIc", "") +BUILTIN(__builtin_ia32_vpshlb, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_vpshlw, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_vpshld, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_vpshlq, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_vpshab, "V16cV16cV16c", "") +BUILTIN(__builtin_ia32_vpshaw, "V8sV8sV8s", "") +BUILTIN(__builtin_ia32_vpshad, "V4iV4iV4i", "") +BUILTIN(__builtin_ia32_vpshaq, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_vpcomub, "V16cV16cV16cIc", "") +BUILTIN(__builtin_ia32_vpcomuw, "V8sV8sV8sIc", "") +BUILTIN(__builtin_ia32_vpcomud, "V4iV4iV4iIc", "") +BUILTIN(__builtin_ia32_vpcomuq, "V2LLiV2LLiV2LLiIc", "") +BUILTIN(__builtin_ia32_vpcomb, "V16cV16cV16cIc", "") +BUILTIN(__builtin_ia32_vpcomw, "V8sV8sV8sIc", "") +BUILTIN(__builtin_ia32_vpcomd, "V4iV4iV4iIc", "") +BUILTIN(__builtin_ia32_vpcomq, "V2LLiV2LLiV2LLiIc", "") +BUILTIN(__builtin_ia32_vpermil2pd, "V2dV2dV2dV2LLiIc", "") +BUILTIN(__builtin_ia32_vpermil2pd256, "V4dV4dV4dV4LLiIc", "") +BUILTIN(__builtin_ia32_vpermil2ps, "V4fV4fV4fV4iIc", "") +BUILTIN(__builtin_ia32_vpermil2ps256, "V8fV8fV8fV8iIc", "") +BUILTIN(__builtin_ia32_vfrczss, "V4fV4f", "") +BUILTIN(__builtin_ia32_vfrczsd, "V2dV2d", "") +BUILTIN(__builtin_ia32_vfrczps, "V4fV4f", "") +BUILTIN(__builtin_ia32_vfrczpd, "V2dV2d", "") +BUILTIN(__builtin_ia32_vfrczps256, "V8fV8f", "") +BUILTIN(__builtin_ia32_vfrczpd256, "V4dV4d", "") + #undef BUILTIN diff --git a/include/clang/Basic/CMakeLists.txt b/include/clang/Basic/CMakeLists.txt index 3df88c7..274b94d 100644 --- a/include/clang/Basic/CMakeLists.txt +++ b/include/clang/Basic/CMakeLists.txt @@ -7,6 +7,7 @@ endmacro(clang_diag_gen) clang_diag_gen(Analysis) clang_diag_gen(AST) +clang_diag_gen(Comment) clang_diag_gen(Common) clang_diag_gen(Driver) clang_diag_gen(Frontend) diff --git a/include/clang/Basic/CommentNodes.td b/include/clang/Basic/CommentNodes.td new file mode 100644 index 0000000..7bf32b7 --- /dev/null +++ b/include/clang/Basic/CommentNodes.td @@ -0,0 +1,27 @@ +class Comment<bit abstract = 0> { + bit Abstract = abstract; +} + +class DComment<Comment base, bit abstract = 0> : Comment<abstract> { + Comment Base = base; +} + +def InlineContentComment : Comment<1>; + def TextComment : DComment<InlineContentComment>; + def InlineCommandComment : DComment<InlineContentComment>; + def HTMLTagComment : DComment<InlineContentComment, 1>; + def HTMLStartTagComment : DComment<HTMLTagComment>; + def HTMLEndTagComment : DComment<HTMLTagComment>; + +def BlockContentComment : Comment<1>; + def ParagraphComment : DComment<BlockContentComment>; + def BlockCommandComment : DComment<BlockContentComment>; + def ParamCommandComment : DComment<BlockCommandComment>; + def TParamCommandComment : DComment<BlockCommandComment>; + def VerbatimBlockComment : DComment<BlockCommandComment>; + def VerbatimLineComment : DComment<BlockCommandComment>; + +def VerbatimBlockLineComment : Comment; + +def FullComment : Comment; + diff --git a/include/clang/Basic/ConvertUTF.h b/include/clang/Basic/ConvertUTF.h index 7fb5874..e7cfa8a 100644 --- a/include/clang/Basic/ConvertUTF.h +++ b/include/clang/Basic/ConvertUTF.h @@ -110,6 +110,8 @@ typedef unsigned char Boolean; /* 0 or 1 */ #define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF #define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF +#define UNI_MAX_UTF8_BYTES_PER_CODE_POINT 4 + typedef enum { conversionOK, /* conversion successful */ sourceExhausted, /* partial character in source, but hit end */ @@ -139,11 +141,13 @@ ConversionResult ConvertUTF8toUTF32 ( ConversionResult ConvertUTF16toUTF8 ( const UTF16** sourceStart, const UTF16* sourceEnd, UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); +#endif ConversionResult ConvertUTF32toUTF8 ( const UTF32** sourceStart, const UTF32* sourceEnd, UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); +#ifdef CLANG_NEEDS_THESE_ONE_DAY ConversionResult ConvertUTF16toUTF32 ( const UTF16** sourceStart, const UTF16* sourceEnd, UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); @@ -159,6 +163,37 @@ Boolean isLegalUTF8String(const UTF8 *source, const UTF8 *sourceEnd); #ifdef __cplusplus } + +/*************************************************************************/ +/* Below are LLVM-specific wrappers of the functions above. */ + +#include "llvm/ADT/StringRef.h" + +namespace clang { + +/** + * Convert an UTF8 StringRef to UTF8, UTF16, or UTF32 depending on + * WideCharWidth. The converted data is written to ResultPtr, which needs to + * point to at least WideCharWidth * (Source.Size() + 1) bytes. On success, + * ResultPtr will point one after the end of the copied string. + * \return true on success. + */ +bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source, + char *&ResultPtr); + +/** + * Convert an Unicode code point to UTF8 sequence. + * + * \param Source a Unicode code point. + * \param [in,out] ResultPtr pointer to the output buffer, needs to be at least + * \c UNI_MAX_UTF8_BYTES_PER_CODE_POINT bytes. On success \c ResultPtr is + * updated one past end of the converted sequence. + * + * \returns true on success. + */ +bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr); + +} #endif #endif diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index e157178..3997fb8 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the Diagnostic-related interfaces. -// +/// +/// \file +/// \brief Defines the Diagnostic-related interfaces. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_DIAGNOSTIC_H @@ -82,7 +83,7 @@ public: } /// \brief Create a code modification hint that inserts the given - /// code from \arg FromRange at a specific location. + /// code from \p FromRange at a specific location. static FixItHint CreateInsertionFromRange(SourceLocation InsertionLoc, CharSourceRange FromRange, bool BeforePreviousInsertions = false) { @@ -121,14 +122,15 @@ public: } }; -/// DiagnosticsEngine - This concrete class is used by the front-end to report -/// problems and issues. It massages the diagnostics (e.g. handling things like -/// "report warnings as errors" and passes them off to the DiagnosticConsumer -/// for reporting to the user. DiagnosticsEngine is tied to one translation unit -/// and one SourceManager. +/// \brief Concrete class used by the front-end to report problems and issues. +/// +/// This massages the diagnostics (e.g. handling things like "report warnings +/// as errors" and passes them off to the DiagnosticConsumer for reporting to +/// the user. DiagnosticsEngine is tied to one translation unit and one +/// SourceManager. class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> { public: - /// Level - The level of the diagnostic, after it has been through mapping. + /// \brief The level of the diagnostic, after it has been through mapping. enum Level { Ignored = DiagnosticIDs::Ignored, Note = DiagnosticIDs::Note, @@ -137,34 +139,36 @@ public: Fatal = DiagnosticIDs::Fatal }; - /// ExtensionHandling - How do we handle otherwise-unmapped extension? This - /// is controlled by -pedantic and -pedantic-errors. + /// \brief How do we handle otherwise-unmapped extension? + /// + /// This is controlled by -pedantic and -pedantic-errors. enum ExtensionHandling { Ext_Ignore, Ext_Warn, Ext_Error }; enum ArgumentKind { - ak_std_string, // std::string - ak_c_string, // const char * - ak_sint, // int - ak_uint, // unsigned - ak_identifierinfo, // IdentifierInfo - ak_qualtype, // QualType - ak_declarationname, // DeclarationName - ak_nameddecl, // NamedDecl * - ak_nestednamespec, // NestedNameSpecifier * - ak_declcontext // DeclContext * + ak_std_string, ///< std::string + ak_c_string, ///< const char * + ak_sint, ///< int + ak_uint, ///< unsigned + ak_identifierinfo, ///< IdentifierInfo + ak_qualtype, ///< QualType + ak_declarationname, ///< DeclarationName + ak_nameddecl, ///< NamedDecl * + ak_nestednamespec, ///< NestedNameSpecifier * + ak_declcontext, ///< DeclContext * + ak_qualtype_pair ///< pair<QualType, QualType> }; - /// Specifies which overload candidates to display when overload resolution - /// fails. + /// \brief Specifies which overload candidates to display when overload + /// resolution fails. enum OverloadsShown { Ovl_All, ///< Show all overloads. Ovl_Best ///< Show just the "best" overload candidates. }; - /// ArgumentValue - This typedef represents on argument value, which is a - /// union discriminated by ArgumentKind, with a value. + /// \brief Represents on argument value, which is a union discriminated + /// by ArgumentKind, with a value. typedef std::pair<ArgumentKind, intptr_t> ArgumentValue; private: @@ -175,6 +179,9 @@ private: bool ErrorsAsFatal; // Treat errors like fatal errors. bool SuppressSystemWarnings; // Suppress warnings in system headers. bool SuppressAllDiagnostics; // Suppress all diagnostics. + bool ElideType; // Elide common types of templates. + bool PrintTemplateTree; // Print a tree when comparing templates. + bool ShowColors; // Color printing is enabled. OverloadsShown ShowOverloads; // Which overload candidates to show. unsigned ErrorLimit; // Cap of # errors emitted, 0 -> no limit. unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack, @@ -187,12 +194,13 @@ private: bool OwnsDiagClient; SourceManager *SourceMgr; - /// \brief Mapping information for diagnostics. Mapping info is - /// packed into four bits per diagnostic. The low three bits are the mapping - /// (an instance of diag::Mapping), or zero if unset. The high bit is set - /// when the mapping was established as a user mapping. If the high bit is - /// clear, then the low bits are set to the default value, and should be - /// mapped with -pedantic, -Werror, etc. + /// \brief Mapping information for diagnostics. + /// + /// Mapping info is packed into four bits per diagnostic. The low three + /// bits are the mapping (an instance of diag::Mapping), or zero if unset. + /// The high bit is set when the mapping was established as a user mapping. + /// If the high bit is clear, then the low bits are set to the default + /// value, and should be mapped with -pedantic, -Werror, etc. /// /// A new DiagState is created and kept around when diagnostic pragmas modify /// the state so that we know what is the diagnostic state at any given @@ -220,8 +228,10 @@ private: std::list<DiagState> DiagStates; /// \brief Represents a point in source where the diagnostic state was - /// modified because of a pragma. 'Loc' can be null if the point represents - /// the diagnostic state modifications done through the command-line. + /// modified because of a pragma. + /// + /// 'Loc' can be null if the point represents the diagnostic state + /// modifications done through the command-line. struct DiagStatePoint { DiagState *State; FullSourceLoc Loc; @@ -239,9 +249,11 @@ private: } }; - /// \brief A vector of all DiagStatePoints representing changes in diagnostic - /// state due to diagnostic pragmas. The vector is always sorted according to - /// the SourceLocation of the DiagStatePoint. + /// \brief A sorted vector of all DiagStatePoints representing changes in + /// diagnostic state due to diagnostic pragmas. + /// + /// The vector is always sorted according to the SourceLocation of the + /// DiagStatePoint. typedef std::vector<DiagStatePoint> DiagStatePointsTy; mutable DiagStatePointsTy DiagStatePoints; @@ -255,25 +267,24 @@ private: } void PushDiagStatePoint(DiagState *State, SourceLocation L) { - FullSourceLoc Loc(L, *SourceMgr); + FullSourceLoc Loc(L, getSourceManager()); // Make sure that DiagStatePoints is always sorted according to Loc. - assert((Loc.isValid() || DiagStatePoints.empty()) && - "Adding invalid loc point after another point"); - assert((Loc.isInvalid() || DiagStatePoints.empty() || - DiagStatePoints.back().Loc.isInvalid() || + assert(Loc.isValid() && "Adding invalid loc point"); + assert(!DiagStatePoints.empty() && + (DiagStatePoints.back().Loc.isInvalid() || DiagStatePoints.back().Loc.isBeforeInTranslationUnitThan(Loc)) && "Previous point loc comes after or is the same as new one"); - DiagStatePoints.push_back(DiagStatePoint(State, - FullSourceLoc(Loc, *SourceMgr))); + DiagStatePoints.push_back(DiagStatePoint(State, Loc)); } /// \brief Finds the DiagStatePoint that contains the diagnostic state of /// the given source location. DiagStatePointsTy::iterator GetDiagStatePointForLoc(SourceLocation Loc) const; - /// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or - /// fatal error is emitted, and is sticky. + /// \brief Sticky flag set to \c true when an error is emitted. bool ErrorOccurred; + + /// \brief Sticky flag set to \c true when a fatal error is emitted. bool FatalErrorOccurred; /// \brief Indicates that an unrecoverable error has occurred. @@ -284,18 +295,20 @@ private: unsigned TrapNumErrorsOccurred; unsigned TrapNumUnrecoverableErrorsOccurred; - /// LastDiagLevel - This is the level of the last diagnostic emitted. This is - /// used to emit continuation diagnostics with the same level as the + /// \brief The level of the last diagnostic emitted. + /// + /// This is used to emit continuation diagnostics with the same level as the /// diagnostic that they follow. DiagnosticIDs::Level LastDiagLevel; - unsigned NumWarnings; // Number of warnings reported - unsigned NumErrors; // Number of errors reported - unsigned NumErrorsSuppressed; // Number of errors suppressed + unsigned NumWarnings; ///< Number of warnings reported + unsigned NumErrors; ///< Number of errors reported + unsigned NumErrorsSuppressed; ///< Number of errors suppressed - /// ArgToStringFn - A function pointer that converts an opaque diagnostic - /// argument to a strings. This takes the modifiers and argument that was - /// present in the diagnostic. + /// \brief A function pointer that converts an opaque diagnostic + /// argument to a strings. + /// + /// This takes the modifiers and argument that was present in the diagnostic. /// /// The PrevArgs array (whose length is NumPrevArgs) indicates the previous /// arguments formatted for this diagnostic. Implementations of this function @@ -361,14 +374,15 @@ public: // how diagnostics are emitted. // - /// pushMappings - Copies the current DiagMappings and pushes the new copy + /// \brief Copies the current DiagMappings and pushes the new copy /// onto the top of the stack. void pushMappings(SourceLocation Loc); - /// popMappings - Pops the current DiagMappings off the top of the stack - /// causing the new top of the stack to be the active mappings. Returns - /// true if the pop happens, false if there is only one DiagMapping on the - /// stack. + /// \brief Pops the current DiagMappings off the top of the stack, + /// causing the new top of the stack to be the active mappings. + /// + /// \returns \c true if the pop happens, \c false if there is only one + /// DiagMapping on the stack. bool popMappings(SourceLocation Loc); /// \brief Set the diagnostic client associated with this diagnostic object. @@ -377,8 +391,10 @@ public: /// ownership of \c client. void setClient(DiagnosticConsumer *client, bool ShouldOwnClient = true); - /// setErrorLimit - Specify a limit for the number of errors we should - /// emit before giving up. Zero disables the limit. + /// \brief Specify a limit for the number of errors we should + /// emit before giving up. + /// + /// Zero disables the limit. void setErrorLimit(unsigned Limit) { ErrorLimit = Limit; } /// \brief Specify the maximum number of template instantiation @@ -405,29 +421,28 @@ public: return ConstexprBacktraceLimit; } - /// setIgnoreAllWarnings - When set to true, any unmapped warnings are - /// ignored. If this and WarningsAsErrors are both set, then this one wins. + /// \brief When set to true, any unmapped warnings are ignored. + /// + /// If this and WarningsAsErrors are both set, then this one wins. void setIgnoreAllWarnings(bool Val) { IgnoreAllWarnings = Val; } bool getIgnoreAllWarnings() const { return IgnoreAllWarnings; } - /// setEnableAllWarnings - When set to true, any unmapped ignored warnings - /// are no longer ignored. If this and IgnoreAllWarnings are both set, - /// then that one wins. + /// \brief When set to true, any unmapped ignored warnings are no longer + /// ignored. + /// + /// If this and IgnoreAllWarnings are both set, then that one wins. void setEnableAllWarnings(bool Val) { EnableAllWarnings = Val; } bool getEnableAllWarnngs() const { return EnableAllWarnings; } - /// setWarningsAsErrors - When set to true, any warnings reported are issued - /// as errors. + /// \brief When set to true, any warnings reported are issued as errors. void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; } bool getWarningsAsErrors() const { return WarningsAsErrors; } - /// setErrorsAsFatal - When set to true, any error reported is made a - /// fatal error. + /// \brief When set to true, any error reported is made a fatal error. void setErrorsAsFatal(bool Val) { ErrorsAsFatal = Val; } bool getErrorsAsFatal() const { return ErrorsAsFatal; } - /// setSuppressSystemWarnings - When set to true mask warnings that - /// come from system headers. + /// \brief When set to true mask warnings that come from system headers. void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; } bool getSuppressSystemWarnings() const { return SuppressSystemWarnings; } @@ -438,76 +453,105 @@ public: SuppressAllDiagnostics = Val; } bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; } - + + /// \brief Set type eliding, to skip outputting same types occurring in + /// template types. + void setElideType(bool Val = true) { ElideType = Val; } + bool getElideType() { return ElideType; } + + /// \brief Set tree printing, to outputting the template difference in a + /// tree format. + void setPrintTemplateTree(bool Val = false) { PrintTemplateTree = Val; } + bool getPrintTemplateTree() { return PrintTemplateTree; } + + /// \brief Set color printing, so the type diffing will inject color markers + /// into the output. + void setShowColors(bool Val = false) { ShowColors = Val; } + bool getShowColors() { return ShowColors; } + /// \brief Specify which overload candidates to show when overload resolution - /// fails. By default, we show all candidates. + /// fails. + /// + /// By default, we show all candidates. void setShowOverloads(OverloadsShown Val) { ShowOverloads = Val; } OverloadsShown getShowOverloads() const { return ShowOverloads; } - /// \brief Pretend that the last diagnostic issued was ignored. This can - /// be used by clients who suppress diagnostics themselves. + /// \brief Pretend that the last diagnostic issued was ignored. + /// + /// This can be used by clients who suppress diagnostics themselves. void setLastDiagnosticIgnored() { LastDiagLevel = DiagnosticIDs::Ignored; } - /// setExtensionHandlingBehavior - This controls whether otherwise-unmapped - /// extension diagnostics are mapped onto ignore/warning/error. This - /// corresponds to the GCC -pedantic and -pedantic-errors option. + /// \brief Controls whether otherwise-unmapped extension diagnostics are + /// mapped onto ignore/warning/error. + /// + /// This corresponds to the GCC -pedantic and -pedantic-errors option. void setExtensionHandlingBehavior(ExtensionHandling H) { ExtBehavior = H; } ExtensionHandling getExtensionHandlingBehavior() const { return ExtBehavior; } - /// AllExtensionsSilenced - This is a counter bumped when an __extension__ - /// block is encountered. When non-zero, all extension diagnostics are - /// entirely silenced, no matter how they are mapped. + /// \brief Counter bumped when an __extension__ block is/ encountered. + /// + /// When non-zero, all extension diagnostics are entirely silenced, no + /// matter how they are mapped. void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; } void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; } bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; } - /// \brief This allows the client to specify that certain - /// warnings are ignored. Notes can never be mapped, errors can only be - /// mapped to fatal, and WARNINGs and EXTENSIONs can be mapped arbitrarily. + /// \brief This allows the client to specify that certain warnings are + /// ignored. + /// + /// Notes can never be mapped, errors can only be mapped to fatal, and + /// WARNINGs and EXTENSIONs can be mapped arbitrarily. /// /// \param Loc The source location that this change of diagnostic state should /// take affect. It can be null if we are setting the latest state. void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map, SourceLocation Loc); - /// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g. - /// "unknown-pragmas" to have the specified mapping. This returns true and - /// ignores the request if "Group" was unknown, false otherwise. + /// \brief Change an entire diagnostic group (e.g. "unknown-pragmas") to + /// have the specified mapping. /// - /// 'Loc' is the source location that this change of diagnostic state should + /// \returns true (and ignores the request) if "Group" was unknown, false + /// otherwise. + /// + /// \param Loc The source location that this change of diagnostic state should /// take affect. It can be null if we are setting the state from command-line. bool setDiagnosticGroupMapping(StringRef Group, diag::Mapping Map, SourceLocation Loc = SourceLocation()); - /// \brief Set the warning-as-error flag for the given diagnostic. This - /// function always only operates on the current diagnostic state. + /// \brief Set the warning-as-error flag for the given diagnostic. + /// + /// This function always only operates on the current diagnostic state. void setDiagnosticWarningAsError(diag::kind Diag, bool Enabled); - /// \brief Set the warning-as-error flag for the given diagnostic group. This - /// function always only operates on the current diagnostic state. + /// \brief Set the warning-as-error flag for the given diagnostic group. + /// + /// This function always only operates on the current diagnostic state. /// /// \returns True if the given group is unknown, false otherwise. bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled); - /// \brief Set the error-as-fatal flag for the given diagnostic. This function - /// always only operates on the current diagnostic state. + /// \brief Set the error-as-fatal flag for the given diagnostic. + /// + /// This function always only operates on the current diagnostic state. void setDiagnosticErrorAsFatal(diag::kind Diag, bool Enabled); - /// \brief Set the error-as-fatal flag for the given diagnostic group. This - /// function always only operates on the current diagnostic state. + /// \brief Set the error-as-fatal flag for the given diagnostic group. + /// + /// This function always only operates on the current diagnostic state. /// /// \returns True if the given group is unknown, false otherwise. bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled); - /// \brief Add the specified mapping to all diagnostics. Mainly to be used - /// by -Wno-everything to disable all warnings but allow subsequent -W options - /// to enable specific warnings. + /// \brief Add the specified mapping to all diagnostics. + /// + /// Mainly to be used by -Wno-everything to disable all warnings but allow + /// subsequent -W options to enable specific warnings. void setMappingToAllDiagnostics(diag::Mapping Map, SourceLocation Loc = SourceLocation()); @@ -525,15 +569,16 @@ public: this->NumWarnings = NumWarnings; } - /// getCustomDiagID - Return an ID for a diagnostic with the specified message - /// and level. If this is the first request for this diagnosic, it is - /// registered and created, otherwise the existing ID is returned. + /// \brief Return an ID for a diagnostic with the specified message and level. + /// + /// If this is the first request for this diagnosic, it is registered and + /// created, otherwise the existing ID is returned. unsigned getCustomDiagID(Level L, StringRef Message) { return Diags->getCustomDiagID((DiagnosticIDs::Level)L, Message); } - /// ConvertArgToString - This method converts a diagnostic argument (as an - /// intptr_t) into the string that represents it. + /// \brief Converts a diagnostic argument (as an intptr_t) into the string + /// that represents it. void ConvertArgToString(ArgumentKind Kind, intptr_t Val, const char *Modifier, unsigned ModLen, const char *Argument, unsigned ArgLen, @@ -568,12 +613,15 @@ public: return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this); } - /// Report - Issue the message to the client. @c DiagID is a member of the - /// @c diag::kind enum. This actually returns aninstance of DiagnosticBuilder - /// which emits the diagnostics (through @c ProcessDiag) when it is destroyed. - /// @c Pos represents the source location associated with the diagnostic, + /// \brief Issue the message to the client. + /// + /// This actually returns an instance of DiagnosticBuilder which emits the + /// diagnostics (through @c ProcessDiag) when it is destroyed. + /// + /// \param DiagID A member of the @c diag::kind enum. + /// \param Loc Represents the source location associated with the diagnostic, /// which can be an invalid location if no position information is available. - inline DiagnosticBuilder Report(SourceLocation Pos, unsigned DiagID); + inline DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID); inline DiagnosticBuilder Report(unsigned DiagID); void Report(const StoredDiagnostic &storedDiag); @@ -624,55 +672,60 @@ private: friend class PartialDiagnostic; friend class DiagnosticErrorTrap; - /// CurDiagLoc - This is the location of the current diagnostic that is in - /// flight. + /// \brief The location of the current diagnostic that is in flight. SourceLocation CurDiagLoc; - /// CurDiagID - This is the ID of the current diagnostic that is in flight. + /// \brief The ID of the current diagnostic that is in flight. + /// /// This is set to ~0U when there is no diagnostic in flight. unsigned CurDiagID; enum { - /// MaxArguments - The maximum number of arguments we can hold. We currently - /// only support up to 10 arguments (%0-%9). A single diagnostic with more - /// than that almost certainly has to be simplified anyway. + /// \brief The maximum number of arguments we can hold. + /// + /// We currently only support up to 10 arguments (%0-%9). A single + /// diagnostic with more than that almost certainly has to be simplified + /// anyway. MaxArguments = 10, - /// MaxRanges - The maximum number of ranges we can hold. + /// \brief The maximum number of ranges we can hold. MaxRanges = 10, - /// MaxFixItHints - The maximum number of ranges we can hold. + /// \brief The maximum number of ranges we can hold. MaxFixItHints = 10 }; - /// NumDiagArgs - This contains the number of entries in Arguments. + /// \brief The number of entries in Arguments. signed char NumDiagArgs; - /// NumDiagRanges - This is the number of ranges in the DiagRanges array. + /// \brief The number of ranges in the DiagRanges array. unsigned char NumDiagRanges; - /// NumDiagFixItHints - This is the number of hints in the DiagFixItHints - /// array. + /// \brief The number of hints in the DiagFixItHints array. unsigned char NumDiagFixItHints; - /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum - /// values, with one for each argument. This specifies whether the argument - /// is in DiagArgumentsStr or in DiagArguments. + /// \brief Specifies whether an argument is in DiagArgumentsStr or + /// in DiagArguments. + /// + /// This is an array of ArgumentKind::ArgumentKind enum values, one for each + /// argument. unsigned char DiagArgumentsKind[MaxArguments]; - /// DiagArgumentsStr - This holds the values of each string argument for the - /// current diagnostic. This value is only used when the corresponding - /// ArgumentKind is ak_std_string. + /// \brief Holds the values of each string argument for the current + /// diagnostic. + /// + /// This is only used when the corresponding ArgumentKind is ak_std_string. std::string DiagArgumentsStr[MaxArguments]; - /// DiagArgumentsVal - The values for the various substitution positions. This - /// is used when the argument is not an std::string. The specific value is - /// mangled into an intptr_t and the interpretation depends on exactly what - /// sort of argument kind it is. + /// \brief The values for the various substitution positions. + /// + /// This is used when the argument is not an std::string. The specific + /// value is mangled into an intptr_t and the interpretation depends on + /// exactly what sort of argument kind it is. intptr_t DiagArgumentsVal[MaxArguments]; - /// DiagRanges - The list of ranges added to this diagnostic. + /// \brief The list of ranges added to this diagnostic. CharSourceRange DiagRanges[MaxRanges]; - /// FixItHints - If valid, provides a hint with some code to insert, remove, + /// \brief If valid, provides a hint with some code to insert, remove, /// or modify at a particular position. FixItHint DiagFixItHints[MaxFixItHints]; @@ -691,11 +744,9 @@ private: return MappingInfo; } - /// ProcessDiag - This is the method used to report a diagnostic that is - /// finally fully formed. + /// \brief Used to report a diagnostic that is finally fully formed. /// - /// \returns true if the diagnostic was emitted, false if it was - /// suppressed. + /// \returns true if the diagnostic was emitted, false if it was suppressed. bool ProcessDiag() { return Diags->ProcessDiag(*this); } @@ -710,7 +761,9 @@ protected: friend class Sema; /// \brief Emit the current diagnostic and clear the diagnostic state. - bool EmitCurrentDiagnostic(); + /// + /// \param Force Emit the diagnostic regardless of suppression settings. + bool EmitCurrentDiagnostic(bool Force = false); unsigned getCurrentDiagID() const { return CurDiagID; } @@ -746,7 +799,7 @@ public: return Diag.TrapNumUnrecoverableErrorsOccurred > NumUnrecoverableErrors; } - // Set to initial state of "no errors occurred". + /// \brief Set to initial state of "no errors occurred". void reset() { NumErrors = Diag.TrapNumErrorsOccurred; NumUnrecoverableErrors = Diag.TrapNumUnrecoverableErrorsOccurred; @@ -757,11 +810,12 @@ public: // DiagnosticBuilder //===----------------------------------------------------------------------===// -/// DiagnosticBuilder - This is a little helper class used to produce -/// diagnostics. This is constructed by the DiagnosticsEngine::Report method, -/// and allows insertion of extra information (arguments and source ranges) into -/// the currently "in flight" diagnostic. When the temporary for the builder is -/// destroyed, the diagnostic is issued. +/// \brief A little helper class used to produce diagnostics. +/// +/// This is constructed by the DiagnosticsEngine::Report method, and +/// allows insertion of extra information (arguments and source ranges) into +/// the currently "in flight" diagnostic. When the temporary for the builder +/// is destroyed, the diagnostic is issued. /// /// Note that many of these will be created as temporary objects (many call /// sites), so we want them to be small and we never want their address taken. @@ -779,15 +833,25 @@ class DiagnosticBuilder { // Emit() would end up with if we used that as our status variable. mutable bool IsActive; + /// \brief Flag indicating that this diagnostic is being emitted via a + /// call to ForceEmit. + mutable bool IsForceEmit; + void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT friend class DiagnosticsEngine; + + DiagnosticBuilder() + : DiagObj(0), NumArgs(0), NumRanges(0), NumFixits(0), IsActive(false), + IsForceEmit(false) { } + explicit DiagnosticBuilder(DiagnosticsEngine *diagObj) - : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixits(0), IsActive(true) { + : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixits(0), IsActive(true), + IsForceEmit(false) { assert(diagObj && "DiagnosticBuilder requires a valid DiagnosticsEngine!"); } friend class PartialDiagnostic; - + protected: void FlushCounts() { DiagObj->NumDiagArgs = NumArgs; @@ -799,9 +863,10 @@ protected: void Clear() const { DiagObj = 0; IsActive = false; + IsForceEmit = false; } - /// isActive - Determine whether this diagnostic is still active. + /// \brief Determine whether this diagnostic is still active. bool isActive() const { return IsActive; } /// \brief Force the diagnostic builder to emit the diagnostic now. @@ -821,7 +886,7 @@ protected: FlushCounts(); // Process the diagnostic. - bool Result = DiagObj->EmitCurrentDiagnostic(); + bool Result = DiagObj->EmitCurrentDiagnostic(IsForceEmit); // This diagnostic is dead. Clear(); @@ -835,20 +900,36 @@ public: DiagnosticBuilder(const DiagnosticBuilder &D) { DiagObj = D.DiagObj; IsActive = D.IsActive; + IsForceEmit = D.IsForceEmit; D.Clear(); NumArgs = D.NumArgs; NumRanges = D.NumRanges; NumFixits = D.NumFixits; } - /// Destructor - The dtor emits the diagnostic. + /// \brief Retrieve an empty diagnostic builder. + static DiagnosticBuilder getEmpty() { + return DiagnosticBuilder(); + } + + /// \brief Emits the diagnostic. ~DiagnosticBuilder() { Emit(); } - /// Operator bool: conversion of DiagnosticBuilder to bool always returns - /// true. This allows is to be used in boolean error contexts like: + /// \brief Forces the diagnostic to be emitted. + const DiagnosticBuilder &setForceEmit() const { + IsForceEmit = true; + return *this; + } + + /// \brief Conversion of DiagnosticBuilder to bool always returns \c true. + /// + /// This allows is to be used in boolean error contexts (where \c true is + /// used to indicate that an error has occurred), like: + /// \code /// return Diag(...); + /// \endcode operator bool() const { return true; } void AddString(StringRef S) const { @@ -951,9 +1032,6 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, return DB; } -/// Report - Issue the message to the client. DiagID is a member of the -/// diag::kind enum. This actually returns a new instance of DiagnosticBuilder -/// which emits the diagnostics (through ProcessDiag) when it is destroyed. inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc, unsigned DiagID){ assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!"); @@ -969,9 +1047,9 @@ inline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) { // Diagnostic //===----------------------------------------------------------------------===// -/// Diagnostic - This is a little helper class (which is basically a smart -/// pointer that forward info from DiagnosticsEngine) that allows clients to -/// enquire about the currently in-flight diagnostic. +/// A little helper class (which is basically a smart pointer that forwards +/// info from DiagnosticsEngine) that allows clients to enquire about the +/// currently in-flight diagnostic. class Diagnostic { const DiagnosticsEngine *DiagObj; StringRef StoredDiagMessage; @@ -988,62 +1066,71 @@ public: unsigned getNumArgs() const { return DiagObj->NumDiagArgs; } - /// getArgKind - Return the kind of the specified index. Based on the kind - /// of argument, the accessors below can be used to get the value. + /// \brief Return the kind of the specified index. + /// + /// Based on the kind of argument, the accessors below can be used to get + /// the value. + /// + /// \pre Idx < getNumArgs() DiagnosticsEngine::ArgumentKind getArgKind(unsigned Idx) const { assert(Idx < getNumArgs() && "Argument index out of range!"); return (DiagnosticsEngine::ArgumentKind)DiagObj->DiagArgumentsKind[Idx]; } - /// getArgStdStr - Return the provided argument string specified by Idx. + /// \brief Return the provided argument string specified by \p Idx. + /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_std_string const std::string &getArgStdStr(unsigned Idx) const { assert(getArgKind(Idx) == DiagnosticsEngine::ak_std_string && "invalid argument accessor!"); return DiagObj->DiagArgumentsStr[Idx]; } - /// getArgCStr - Return the specified C string argument. + /// \brief Return the specified C string argument. + /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_c_string const char *getArgCStr(unsigned Idx) const { assert(getArgKind(Idx) == DiagnosticsEngine::ak_c_string && "invalid argument accessor!"); return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]); } - /// getArgSInt - Return the specified signed integer argument. + /// \brief Return the specified signed integer argument. + /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_sint int getArgSInt(unsigned Idx) const { assert(getArgKind(Idx) == DiagnosticsEngine::ak_sint && "invalid argument accessor!"); return (int)DiagObj->DiagArgumentsVal[Idx]; } - /// getArgUInt - Return the specified unsigned integer argument. + /// \brief Return the specified unsigned integer argument. + /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_uint unsigned getArgUInt(unsigned Idx) const { assert(getArgKind(Idx) == DiagnosticsEngine::ak_uint && "invalid argument accessor!"); return (unsigned)DiagObj->DiagArgumentsVal[Idx]; } - /// getArgIdentifier - Return the specified IdentifierInfo argument. + /// \brief Return the specified IdentifierInfo argument. + /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo const IdentifierInfo *getArgIdentifier(unsigned Idx) const { assert(getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo && "invalid argument accessor!"); return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]); } - /// getRawArg - Return the specified non-string argument in an opaque form. + /// \brief Return the specified non-string argument in an opaque form. + /// \pre getArgKind(Idx) != DiagnosticsEngine::ak_std_string intptr_t getRawArg(unsigned Idx) const { assert(getArgKind(Idx) != DiagnosticsEngine::ak_std_string && "invalid argument accessor!"); return DiagObj->DiagArgumentsVal[Idx]; } - - /// getNumRanges - Return the number of source ranges associated with this - /// diagnostic. + /// \brief Return the number of source ranges associated with this diagnostic. unsigned getNumRanges() const { return DiagObj->NumDiagRanges; } + /// \pre Idx < getNumRanges() const CharSourceRange &getRange(unsigned Idx) const { assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!"); return DiagObj->DiagRanges[Idx]; @@ -1067,13 +1154,14 @@ public: return getNumFixItHints()? DiagObj->DiagFixItHints : 0; } - /// FormatDiagnostic - Format this diagnostic into a string, substituting the - /// formal arguments into the %0 slots. The result is appended onto the Str - /// array. + /// \brief Format this diagnostic into a string, substituting the + /// formal arguments into the %0 slots. + /// + /// The result is appended onto the \p OutStr array. void FormatDiagnostic(SmallVectorImpl<char> &OutStr) const; - /// FormatDiagnostic - Format the given format-string into the - /// output buffer using the arguments stored in this diagnostic. + /// \brief Format the given format-string into the output buffer using the + /// arguments stored in this diagnostic. void FormatDiagnostic(const char *DiagStr, const char *DiagEnd, SmallVectorImpl<char> &OutStr) const; }; @@ -1131,12 +1219,12 @@ public: } }; -/// DiagnosticConsumer - This is an abstract interface implemented by clients of -/// the front-end, which formats and prints fully processed diagnostics. +/// \brief Abstract interface, implemented by clients of the front-end, which +/// formats and prints fully processed diagnostics. class DiagnosticConsumer { protected: - unsigned NumWarnings; // Number of warnings reported - unsigned NumErrors; // Number of errors reported + unsigned NumWarnings; ///< Number of warnings reported + unsigned NumErrors; ///< Number of errors reported public: DiagnosticConsumer() : NumWarnings(0), NumErrors(0) { } @@ -1147,7 +1235,7 @@ public: virtual ~DiagnosticConsumer(); - /// BeginSourceFile - Callback to inform the diagnostic client that processing + /// \brief Callback to inform the diagnostic client that processing /// of a source file is beginning. /// /// Note that diagnostics may be emitted outside the processing of a source @@ -1155,32 +1243,35 @@ public: /// diagnostics with source range information are required to only be emitted /// in between BeginSourceFile() and EndSourceFile(). /// - /// \arg LO - The language options for the source file being processed. - /// \arg PP - The preprocessor object being used for the source; this optional - /// and may not be present, for example when processing AST source files. + /// \param LangOpts The language options for the source file being processed. + /// \param PP The preprocessor object being used for the source; this is + /// optional, e.g., it may not be present when processing AST source files. virtual void BeginSourceFile(const LangOptions &LangOpts, const Preprocessor *PP = 0) {} - /// EndSourceFile - Callback to inform the diagnostic client that processing - /// of a source file has ended. The diagnostic client should assume that any - /// objects made available via \see BeginSourceFile() are inaccessible. + /// \brief Callback to inform the diagnostic client that processing + /// of a source file has ended. + /// + /// The diagnostic client should assume that any objects made available via + /// BeginSourceFile() are inaccessible. virtual void EndSourceFile() {} /// \brief Callback to inform the diagnostic client that processing of all /// source files has ended. virtual void finish() {} - /// IncludeInDiagnosticCounts - This method (whose default implementation - /// returns true) indicates whether the diagnostics handled by this + /// \brief Indicates whether the diagnostics handled by this /// DiagnosticConsumer should be included in the number of diagnostics /// reported by DiagnosticsEngine. + /// + /// The default implementation returns true. virtual bool IncludeInDiagnosticCounts() const; - /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or + /// \brief Handle this diagnostic, reporting it to the user or /// capturing it to a log as needed. /// - /// Default implementation just keeps track of the total number of warnings - /// and errors. + /// The default implementation just keeps track of the total number of + /// warnings and errors. virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info); @@ -1189,8 +1280,7 @@ public: virtual DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const = 0; }; -/// IgnoringDiagConsumer - This is a diagnostic client that just ignores all -/// diags. +/// \brief A diagnostic client that ignores all diagnostics. class IgnoringDiagConsumer : public DiagnosticConsumer { virtual void anchor(); void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, @@ -1202,6 +1292,22 @@ class IgnoringDiagConsumer : public DiagnosticConsumer { } }; +// Struct used for sending info about how a type should be printed. +struct TemplateDiffTypes { + intptr_t FromType; + intptr_t ToType; + unsigned PrintTree : 1; + unsigned PrintFromType : 1; + unsigned ElideType : 1; + unsigned ShowColors : 1; + // The printer sets this variable to true if the template diff was used. + unsigned TemplateDiffUsed : 1; +}; + +/// Special character that the diagnostic printer will use to toggle the bold +/// attribute. The character itself will be not be printed. +const char ToggleHighlight = 127; + } // end namespace clang #endif diff --git a/include/clang/Basic/Diagnostic.td b/include/clang/Basic/Diagnostic.td index 109cd08..6dfecdc 100644 --- a/include/clang/Basic/Diagnostic.td +++ b/include/clang/Basic/Diagnostic.td @@ -88,6 +88,7 @@ class AccessControl { bit AccessControl = 1; } // Definitions for Diagnostics. include "DiagnosticASTKinds.td" include "DiagnosticAnalysisKinds.td" +include "DiagnosticCommentKinds.td" include "DiagnosticCommonKinds.td" include "DiagnosticDriverKinds.td" include "DiagnosticFrontendKinds.td" diff --git a/include/clang/Basic/DiagnosticCommentKinds.td b/include/clang/Basic/DiagnosticCommentKinds.td new file mode 100644 index 0000000..235ca79 --- /dev/null +++ b/include/clang/Basic/DiagnosticCommentKinds.td @@ -0,0 +1,125 @@ +//==--- DiagnosticCommentKinds.td - diagnostics related to comments -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +let Component = "Comment" in { +let CategoryName = "Documentation Issue" in { + +// HTML parsing errors. These are under -Wdocumentation to make sure the user +// knows that we didn't parse something as he might expect. + +def warn_doc_html_start_tag_expected_quoted_string : Warning< + "expected quoted string after equals sign">, + InGroup<Documentation>, DefaultIgnore; + +def warn_doc_html_start_tag_expected_ident_or_greater : Warning< + "HTML start tag prematurely ended, expected attribute name or '>'">, + InGroup<Documentation>, DefaultIgnore; + +def note_doc_html_tag_started_here : Note< + "HTML tag started here">; + +// HTML semantic errors + +def warn_doc_html_end_forbidden : Warning< + "HTML end tag '%0' is forbidden">, + InGroup<DocumentationHTML>, DefaultIgnore; + +def warn_doc_html_end_unbalanced : Warning< + "HTML end tag does not match any start tag">, + InGroup<DocumentationHTML>, DefaultIgnore; + +def warn_doc_html_start_end_mismatch : Warning< + "HTML start tag '%0' closed by '%1'">, + InGroup<DocumentationHTML>, DefaultIgnore; + +def note_doc_html_end_tag : Note< + "end tag">; + +// Commands + +def warn_doc_block_command_empty_paragraph : Warning< + "empty paragraph passed to '\\%0' command">, + InGroup<Documentation>, DefaultIgnore; + +def warn_doc_block_command_duplicate : Warning< + "duplicated command '\\%0'">, + InGroup<Documentation>, DefaultIgnore; + +def note_doc_block_command_previous : Note< + "previous command '\\%0' here">; + +def note_doc_block_command_previous_alias : Note< + "previous command '\\%0' (an alias of '\\%1') here">; + +// \param command + +def warn_doc_param_invalid_direction : Warning< + "unrecognized parameter passing direction, " + "valid directions are '[in]', '[out]' and '[in,out]'">, + InGroup<Documentation>, DefaultIgnore; + +def warn_doc_param_spaces_in_direction : Warning< + "whitespace is not allowed in parameter passing direction">, + InGroup<DocumentationPedantic>, DefaultIgnore; + +def warn_doc_param_not_attached_to_a_function_decl : Warning< + "'\\param' command used in a comment that is not attached to " + "a function declaration">, + InGroup<Documentation>, DefaultIgnore; + +def warn_doc_param_duplicate : Warning< + "parameter '%0' is already documented">, + InGroup<Documentation>, DefaultIgnore; + +def note_doc_param_previous : Note< + "previous documentation">; + +def warn_doc_param_not_found : Warning< + "parameter '%0' not found in the function declaration">, + InGroup<Documentation>, DefaultIgnore; + +def note_doc_param_name_suggestion : Note< + "did you mean '%0'?">; + +// \tparam command + +def warn_doc_tparam_not_attached_to_a_template_decl : Warning< + "'\\tparam' command used in a comment that is not attached to " + "a template declaration">, + InGroup<Documentation>, DefaultIgnore; + +def warn_doc_tparam_duplicate : Warning< + "template parameter '%0' is already documented">, + InGroup<Documentation>, DefaultIgnore; + +def note_doc_tparam_previous : Note< + "previous documentation">; + +def warn_doc_tparam_not_found : Warning< + "template parameter '%0' not found in the template declaration">, + InGroup<Documentation>, DefaultIgnore; + +def note_doc_tparam_name_suggestion : Note< + "did you mean '%0'?">; + +// \returns command + +def warn_doc_returns_not_attached_to_a_function_decl : Warning< + "'\\%0' command used in a comment that is not attached to " + "a function or method declaration">, + InGroup<Documentation>, DefaultIgnore; + +def warn_doc_returns_attached_to_a_void_function : Warning< + "'\\%0' command used in a comment that is attached to a " + "%select{function returning void|constructor|destructor|" + "method returning void}1">, + InGroup<Documentation>, DefaultIgnore; + +} // end of documentation issue category +} // end of AST component diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index 103fc00..f859287 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -74,6 +74,8 @@ def err_module_cycle : Error<"cyclic dependency in module '%0': %1">, def warn_module_build : Warning<"building module '%0' from source">, InGroup<ModuleBuild>, DefaultIgnore; def note_pragma_entered_here : Note<"#pragma entered here">; +def note_decl_hiding_tag_type : Note< + "%1 %0 is hidden by a non-type declaration of %0 here">; // Sema && Lex def ext_longlong : Extension< @@ -106,4 +108,8 @@ def err_file_modified : Error< "file '%0' modified since it was first processed">, DefaultFatal; def err_unsupported_bom : Error<"%0 byte order mark detected in '%1', but " "encoding is not supported">, DefaultFatal; +def err_unable_to_rename_temp : Error< + "unable to rename temporary '%0' to output file '%1': '%2'">; +def err_unable_to_make_temp : Error< + "unable to make temporary file: %0">; } diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index b443159..583b234 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -33,8 +33,6 @@ def err_drv_use_of_Z_option : Error< "unsupported use of internal gcc -Z option '%0'">; def err_drv_output_argument_with_multiple_files : Error< "cannot specify -o when generating multiple output files">; -def err_drv_unable_to_make_temp : Error< - "unable to make temporary file: %0">; def err_drv_unable_to_remove_file : Error< "unable to remove file: %0">; def err_drv_command_failure : Error< @@ -94,23 +92,32 @@ def err_drv_invalid_arch_for_deployment_target : Error< def err_drv_objc_gc_arr : Error< "cannot specify both '-fobjc-arc' and '%0'">; def err_arc_nonfragile_abi : Error< - "-fobjc-arc is not supported with fragile abi">; + "-fobjc-arc is not supported with legacy abi">; def err_arc_unsupported : Error< "-fobjc-arc is not supported on current deployment target">; def err_drv_mg_requires_m_or_mm : Error< "option '-MG' requires '-M' or '-MM'">; +def err_drv_asan_android_requires_pie : Error< + "AddressSanitizer on Android requires '-pie'">; +def err_drv_unknown_objc_runtime : Error< + "unknown or ill-formed Objective-C runtime '%0'">; def warn_c_kext : Warning< - "ignoring -fapple-kext which is valid for c++ and objective-c++ only">; + "ignoring -fapple-kext which is valid for C++ and Objective-C++ only">; def warn_drv_input_file_unused : Warning< - "%0: '%1' input unused when '%2' is present">; + "%0: '%1' input unused%select{ when '%3' is present|}2">, + InGroup<DiagGroup<"unused-command-line-argument">>; +def warn_drv_input_file_unused_by_cpp : Warning< + "%0: '%1' input unused in cpp mode">, + InGroup<DiagGroup<"unused-command-line-argument">>; def warn_drv_preprocessed_input_file_unused : Warning< - "%0: previously preprocessed input unused when '%1' is present">; + "%0: previously preprocessed input%select{ unused when '%2' is present|}1">, + InGroup<DiagGroup<"unused-command-line-argument">>; def warn_drv_unused_argument : Warning< "argument unused during compilation: '%0'">, InGroup<DiagGroup<"unused-command-line-argument">>; def warn_drv_empty_joined_argument : Warning< - "joined argument expects addition arg: '%0'">, + "joined argument expects additional value: '%0'">, InGroup<DiagGroup<"unused-command-line-argument">>; def warn_drv_not_using_clang_cpp : Warning< "not using the clang preprocessor due to user override">; diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 5d6b887..417a22c 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -48,14 +48,12 @@ def err_fe_unable_to_interface_with_target : Error< "unable to interface with target machine">; def err_fe_unable_to_open_output : Error< "unable to open output file '%0': '%1'">; -def err_fe_unable_to_rename_temp : Error< - "unable to rename temporary '%0' to output file '%1': '%2'">; def err_fe_unable_to_open_logfile : Error< "unable to open logfile file '%0': '%1'">; def err_fe_pth_file_has_no_source_header : Error< "PTH file '%0' does not designate an original source header file for -include-pth">; def warn_fe_macro_contains_embedded_newline : Warning< - "macro '%0' contains embedded newline, text after the newline is ignored.">; + "macro '%0' contains embedded newline; text after the newline is ignored">; def warn_fe_cc_print_header_failure : Warning< "unable to open CC_PRINT_HEADERS file: %0 (using stderr)">; def warn_fe_cc_log_diagnostics_failure : Warning< @@ -65,6 +63,10 @@ def warn_fe_serialized_diag_failure : Warning< "unable to open file %0 for serializing diagnostics (%1)">, InGroup<DiagGroup<"serialized-diagnostics">>; +def err_verify_missing_line : Error< + "missing or invalid line number following '@' in expected %0">; +def err_verify_invalid_range : Error< + "invalid range following '-' in expected %0">; def err_verify_missing_start : Error< "cannot find start ('{{') of expected %0">; def err_verify_missing_end : Error< @@ -93,19 +95,19 @@ def warn_unknown_warning_option : Warning< "unknown warning option '%0'">, InGroup<DiagGroup<"unknown-warning-option"> >; def warn_unknown_negative_warning_option : Warning< - "unknown warning option '%0'?">, - InGroup<DiagGroup<"unknown-warning-option"> >, DefaultIgnore; + "unknown warning option '%0'">, + InGroup<DiagGroup<"unknown-warning-option"> >; def warn_unknown_warning_option_suggest : Warning< "unknown warning option '%0'; did you mean '%1'?">, InGroup<DiagGroup<"unknown-warning-option"> >; def warn_unknown_negative_warning_option_suggest : Warning< "unknown warning option '%0'; did you mean '%1'?">, - InGroup<DiagGroup<"unknown-warning-option"> >, DefaultIgnore; + InGroup<DiagGroup<"unknown-warning-option"> >; def warn_unknown_warning_specifier : Warning< "unknown %0 warning specifier: '%1'">, InGroup<DiagGroup<"unknown-warning-option"> >; -def warn_unknown_analyzer_checker : Warning< +def err_unknown_analyzer_checker : Error< "no analyzer checkers are associated with '%0'">; def warn_incompatible_analyzer_plugin_api : Warning< "checker plugin '%0' is not compatible with this version of the analyzer">, diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index c839853..b95a90b 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -25,6 +25,7 @@ def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">; def : DiagGroup<"attributes">; def : DiagGroup<"bad-function-cast">; def Availability : DiagGroup<"availability">; +def Section : DiagGroup<"section">; def AutoImport : DiagGroup<"auto-import">; def ConstantConversion : DiagGroup<"constant-conversion">; def LiteralConversion : DiagGroup<"literal-conversion">; @@ -32,6 +33,7 @@ def StringConversion : DiagGroup<"string-conversion">; def SignConversion : DiagGroup<"sign-conversion">; def BoolConversion : DiagGroup<"bool-conversion">; def IntConversion : DiagGroup<"int-conversion">; +def NonLiteralNullConversion : DiagGroup<"non-literal-null-conversion">; def NullConversion : DiagGroup<"null-conversion">; def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">; def CXXCompat: DiagGroup<"c++-compat">; @@ -56,8 +58,13 @@ def DeprecatedImplementations :DiagGroup<"deprecated-implementations">; def : DiagGroup<"disabled-optimization">; def : DiagGroup<"discard-qual">; def : DiagGroup<"div-by-zero">; +def DocumentationHTML : DiagGroup<"documentation-html">; +def DocumentationPedantic : DiagGroup<"documentation-pedantic">; +def Documentation : DiagGroup<"documentation", [DocumentationHTML]>; def EmptyBody : DiagGroup<"empty-body">; def ExtraTokens : DiagGroup<"extra-tokens">; +def CXX11ExtraSemi : DiagGroup<"c++11-extra-semi">; +def ExtraSemi : DiagGroup<"extra-semi", [CXX11ExtraSemi]>; def FormatExtraArgs : DiagGroup<"format-extra-args">; def FormatZeroLength : DiagGroup<"format-zero-length">; @@ -96,6 +103,7 @@ def CXX11Compat : DiagGroup<"c++11-compat", def : DiagGroup<"c++0x-compat", [CXX11Compat]>; def : DiagGroup<"effc++">; +def DivZero : DiagGroup<"division-by-zero">; def ExitTimeDestructors : DiagGroup<"exit-time-destructors">; def FlexibleArrayExtensions : DiagGroup<"flexible-array-extensions">; def FourByteMultiChar : DiagGroup<"four-char-constants">; @@ -142,9 +150,13 @@ def : DiagGroup<"old-style-cast">; def : DiagGroup<"old-style-definition">; def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">; def : DiagGroup<"overflow">; +def ForwardClassReceiver : DiagGroup<"receiver-forward-class">; +def MethodAccess : DiagGroup<"objc-method-access">; +def ObjCReceiver : DiagGroup<"receiver-expr">; def OverlengthStrings : DiagGroup<"overlength-strings">; def OverloadedVirtual : DiagGroup<"overloaded-virtual">; def ObjCPropertyImpl : DiagGroup<"objc-property-implementation">; +def ObjCPropertyNoAttribute : DiagGroup<"objc-property-no-attribute">; def ObjCMissingSuperCalls : DiagGroup<"objc-missing-super-calls">; def ObjCRetainBlockProperty : DiagGroup<"objc-noncopy-retain-block-property">; def ObjCReadonlyPropertyHasSetter : DiagGroup<"objc-readonly-with-setter-property">; @@ -162,7 +174,8 @@ def ReturnTypeCLinkage : DiagGroup<"return-type-c-linkage">; def ReturnType : DiagGroup<"return-type", [ReturnTypeCLinkage]>; def BindToTemporaryCopy : DiagGroup<"bind-to-temporary-copy", [CXX98CompatBindToTemporaryCopy]>; -def SelfAssignment : DiagGroup<"self-assign">; +def SelfAssignmentField : DiagGroup<"self-assign-field">; +def SelfAssignment : DiagGroup<"self-assign", [SelfAssignmentField]>; def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">; def Sentinel : DiagGroup<"sentinel">; def MissingMethodReturnType : DiagGroup<"missing-method-return-type">; @@ -206,12 +219,18 @@ def MethodDuplicate : DiagGroup<"duplicate-method-match">; def CoveredSwitchDefault : DiagGroup<"covered-switch-default">; def SwitchEnum : DiagGroup<"switch-enum">; def Switch : DiagGroup<"switch">; +def ImplicitFallthroughPerFunction : + DiagGroup<"implicit-fallthrough-per-function">; +def ImplicitFallthrough : DiagGroup<"implicit-fallthrough", + [ImplicitFallthroughPerFunction]>; +def InvalidPPToken : DiagGroup<"invalid-pp-token">; def Trigraphs : DiagGroup<"trigraphs">; def : DiagGroup<"type-limits">; def Unicode : DiagGroup<"unicode">; -def Uninitialized : DiagGroup<"uninitialized">; def UninitializedMaybe : DiagGroup<"conditional-uninitialized">; +def UninitializedSometimes : DiagGroup<"sometimes-uninitialized">; +def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes]>; def UnknownPragmas : DiagGroup<"unknown-pragmas">; def NSobjectAttribute : DiagGroup<"NSObject-attribute">; def UnknownAttributes : DiagGroup<"attributes">; @@ -223,6 +242,7 @@ def UnusedComparison : DiagGroup<"unused-comparison">; def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">; def UnneededInternalDecl : DiagGroup<"unneeded-internal-declaration">; def UnneededMemberFunction : DiagGroup<"unneeded-member-function">; +def UnusedPrivateField : DiagGroup<"unused-private-field">; def UnusedFunction : DiagGroup<"unused-function", [UnneededInternalDecl]>; def UnusedMemberFunction : DiagGroup<"unused-member-function", [UnneededMemberFunction]>; @@ -250,7 +270,6 @@ def AutomaticReferenceCounting : DiagGroup<"arc", ARCRetainCycles, ARCNonPodMemAccess]>; def Selector : DiagGroup<"selector">; -def NonfragileAbi2 : DiagGroup<"nonfragile-abi2">; def Protocol : DiagGroup<"protocol">; def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">; def OverridingMethodMismatch : DiagGroup<"overriding-method-mismatch">; @@ -296,7 +315,8 @@ def Conversion : DiagGroup<"conversion", StringConversion, SignConversion, BoolConversion, - NullConversion, + NullConversion, // NULL->non-pointer + NonLiteralNullConversion, // (1-1)->pointer (etc) IntConversion]>, DiagCategory<"Value Conversion Issue">; @@ -304,6 +324,7 @@ def Unused : DiagGroup<"unused", [UnusedArgument, UnusedFunction, UnusedLabel, // UnusedParameter, (matches GCC's behavior) // UnusedMemberFunction, (clean-up llvm before enabling) + UnusedPrivateField, UnusedValue, UnusedVariable]>, DiagCategory<"Unused Entity Issue">; @@ -354,13 +375,19 @@ def Most : DiagGroup<"most", [ ]>; // Thread Safety warnings -def ThreadSafety : DiagGroup<"thread-safety">; +def ThreadSafetyAttributes : DiagGroup<"thread-safety-attributes">; +def ThreadSafetyAnalysis : DiagGroup<"thread-safety-analysis">; +def ThreadSafety : DiagGroup<"thread-safety", + [ThreadSafetyAttributes, ThreadSafetyAnalysis]>; // Note that putting warnings in -Wall will not disable them by default. If a // warning should be active _only_ when -Wall is passed in, mark it as // DefaultIgnore in addition to putting it here. def : DiagGroup<"all", [Most, Parentheses, Switch]>; +// Warnings enabled by -pedantic. This is magically filled in by TableGen. +def Pedantic : DiagGroup<"pedantic">; + // Aliases. def : DiagGroup<"", [Extra]>; // -W = -Wextra def : DiagGroup<"endif-labels", [ExtraTokens]>; // -Wendif-labels=-Wendif-tokens @@ -381,7 +408,7 @@ def NonGCC : DiagGroup<"non-gcc", // A warning group for warnings about using C++11 features as extensions in // earlier C++ versions. -def CXX11 : DiagGroup<"c++11-extensions">; +def CXX11 : DiagGroup<"c++11-extensions", [CXX11ExtraSemi]>; def : DiagGroup<"c++0x-extensions", [CXX11]>; def DelegatingCtorCycles : DiagGroup<"delegating-ctor-cycles">; @@ -413,3 +440,8 @@ def ObjCRedundantAPIUse : DiagGroup<"objc-redundant-api-use", [ def ObjCCocoaAPI : DiagGroup<"objc-cocoa-api", [ ObjCRedundantAPIUse ]>; + +def ObjCStringComparison : DiagGroup<"objc-string-compare">; +def ObjCLiteralComparison : DiagGroup<"objc-literal-compare", [ + ObjCStringComparison + ]>; diff --git a/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h index a6c22db..11552af 100644 --- a/include/clang/Basic/DiagnosticIDs.h +++ b/include/clang/Basic/DiagnosticIDs.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the Diagnostic IDs-related interfaces. -// +/// +/// \file +/// \brief Defines the Diagnostic IDs-related interfaces. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_DIAGNOSTICIDS_H @@ -37,14 +38,15 @@ namespace clang { DIAG_START_LEX = DIAG_START_SERIALIZATION + 120, DIAG_START_PARSE = DIAG_START_LEX + 300, DIAG_START_AST = DIAG_START_PARSE + 400, - DIAG_START_SEMA = DIAG_START_AST + 100, + DIAG_START_COMMENT = DIAG_START_AST + 100, + DIAG_START_SEMA = DIAG_START_COMMENT + 100, DIAG_START_ANALYSIS = DIAG_START_SEMA + 3000, DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100 }; class CustomDiagInfo; - /// diag::kind - All of the diagnostics that can be emitted by the frontend. + /// \brief All of the diagnostics that can be emitted by the frontend. typedef unsigned kind; // Get typedefs for common diagnostics. @@ -63,10 +65,10 @@ namespace clang { /// one). enum Mapping { // NOTE: 0 means "uncomputed". - MAP_IGNORE = 1, //< Map this diagnostic to nothing, ignore it. - MAP_WARNING = 2, //< Map this diagnostic to a warning. - MAP_ERROR = 3, //< Map this diagnostic to an error. - MAP_FATAL = 4 //< Map this diagnostic to a fatal error. + MAP_IGNORE = 1, ///< Map this diagnostic to nothing, ignore it. + MAP_WARNING = 2, ///< Map this diagnostic to a warning. + MAP_ERROR = 3, ///< Map this diagnostic to an error. + MAP_FATAL = 4 ///< Map this diagnostic to a fatal error. }; } @@ -111,83 +113,84 @@ public: /// by multiple Diagnostics for multiple translation units. class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> { public: - /// Level - The level of the diagnostic, after it has been through mapping. + /// Level The level of the diagnostic, after it has been through mapping. enum Level { Ignored, Note, Warning, Error, Fatal }; private: - /// CustomDiagInfo - Information for uniquing and looking up custom diags. + /// \brief Information for uniquing and looking up custom diags. diag::CustomDiagInfo *CustomDiagInfo; public: DiagnosticIDs(); ~DiagnosticIDs(); - /// getCustomDiagID - Return an ID for a diagnostic with the specified message - /// and level. If this is the first request for this diagnosic, it is - /// registered and created, otherwise the existing ID is returned. + /// \brief Return an ID for a diagnostic with the specified message and level. + /// + /// If this is the first request for this diagnosic, it is registered and + /// created, otherwise the existing ID is returned. unsigned getCustomDiagID(Level L, StringRef Message); //===--------------------------------------------------------------------===// // Diagnostic classification and reporting interfaces. // - /// getDescription - Given a diagnostic ID, return a description of the - /// issue. + /// \brief Given a diagnostic ID, return a description of the issue. StringRef getDescription(unsigned DiagID) const; - /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic level - /// of the specified diagnostic ID is a Warning or Extension. This only works - /// on builtin diagnostics, not custom ones, and is not legal to call on - /// NOTEs. + /// \brief Return true if the unmapped diagnostic levelof the specified + /// diagnostic ID is a Warning or Extension. + /// + /// This only works on builtin diagnostics, not custom ones, and is not + /// legal to call on NOTEs. static bool isBuiltinWarningOrExtension(unsigned DiagID); /// \brief Return true if the specified diagnostic is mapped to errors by /// default. static bool isDefaultMappingAsError(unsigned DiagID); - /// \brief Determine whether the given built-in diagnostic ID is a - /// Note. + /// \brief Determine whether the given built-in diagnostic ID is a Note. static bool isBuiltinNote(unsigned DiagID); - /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic - /// ID is for an extension of some sort. - /// + /// \brief Determine whether the given built-in diagnostic ID is for an + /// extension of some sort. static bool isBuiltinExtensionDiag(unsigned DiagID) { bool ignored; return isBuiltinExtensionDiag(DiagID, ignored); } - /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic - /// ID is for an extension of some sort. This also returns EnabledByDefault, - /// which is set to indicate whether the diagnostic is ignored by default (in - /// which case -pedantic enables it) or treated as a warning/error by default. + /// \brief Determine whether the given built-in diagnostic ID is for an + /// extension of some sort, and whether it is enabled by default. + /// + /// This also returns EnabledByDefault, which is set to indicate whether the + /// diagnostic is ignored by default (in which case -pedantic enables it) or + /// treated as a warning/error by default. /// static bool isBuiltinExtensionDiag(unsigned DiagID, bool &EnabledByDefault); - /// getWarningOptionForDiag - Return the lowest-level warning option that - /// enables the specified diagnostic. If there is no -Wfoo flag that controls - /// the diagnostic, this returns null. + /// \brief Return the lowest-level warning option that enables the specified + /// diagnostic. + /// + /// If there is no -Wfoo flag that controls the diagnostic, this returns null. static StringRef getWarningOptionForDiag(unsigned DiagID); - /// getCategoryNumberForDiag - Return the category number that a specified - /// DiagID belongs to, or 0 if no category. + /// \brief Return the category number that a specified \p DiagID belongs to, + /// or 0 if no category. static unsigned getCategoryNumberForDiag(unsigned DiagID); - /// getNumberOfCategories - Return the number of categories + /// \brief Return the number of diagnostic categories. static unsigned getNumberOfCategories(); - /// getCategoryNameFromID - Given a category ID, return the name of the - /// category. + /// \brief Given a category ID, return the name of the category. static StringRef getCategoryNameFromID(unsigned CategoryID); - /// isARCDiagnostic - Return true if a given diagnostic falls into an - /// ARC diagnostic category; + /// \brief Return true if a given diagnostic falls into an ARC diagnostic + /// category. static bool isARCDiagnostic(unsigned DiagID); - /// \brief Enumeration describing how the the emission of a diagnostic should + /// \brief Enumeration describing how the emission of a diagnostic should /// be treated when it occurs during C++ template argument deduction. enum SFINAEResponse { /// \brief The diagnostic should not be reported, but it should cause @@ -253,20 +256,23 @@ private: DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, const DiagnosticsEngine &Diag) const; - /// getDiagnosticLevel - This is an internal implementation helper used when - /// DiagClass is already known. + /// \brief An internal implementation helper used when \p DiagClass is + /// already known. DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID, unsigned DiagClass, SourceLocation Loc, const DiagnosticsEngine &Diag) const; - /// ProcessDiag - This is the method used to report a diagnostic that is - /// finally fully formed. + /// \brief Used to report a diagnostic that is finally fully formed. /// - /// \returns true if the diagnostic was emitted, false if it was + /// \returns \c true if the diagnostic was emitted, \c false if it was /// suppressed. bool ProcessDiag(DiagnosticsEngine &Diag) const; + /// \brief Used to emit a diagnostic that is finally fully formed, + /// ignoring suppression. + void EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const; + /// \brief Whether the diagnostic may leave the AST in a state where some /// invariants can break. bool isUnrecoverable(unsigned DiagID) const; diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 670283e..cc958db 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -64,9 +64,12 @@ def ext_token_used : Extension<"extension used">, def warn_cxx11_keyword : Warning<"'%0' is a keyword in C++11">, InGroup<CXX11Compat>, DefaultIgnore; -def warn_unterminated_string : ExtWarn<"missing terminating '\"' character">; -def warn_unterminated_char : ExtWarn<"missing terminating ' character">; -def err_empty_character : Error<"empty character constant">; +def ext_unterminated_string : ExtWarn<"missing terminating '\"' character">, + InGroup<InvalidPPToken>; +def ext_unterminated_char : ExtWarn<"missing terminating ' character">, + InGroup<InvalidPPToken>; +def ext_empty_character : ExtWarn<"empty character constant">, + InGroup<InvalidPPToken>; def err_unterminated_block_comment : Error<"unterminated /* comment">; def err_invalid_character_to_charify : Error< "invalid argument to convert to character">; @@ -177,6 +180,7 @@ def err_bad_character_encoding : Error< def warn_bad_character_encoding : ExtWarn< "illegal character encoding in character literal">, InGroup<DiagGroup<"invalid-source-encoding">>; +def err_lexing_string : Error<"failure when lexing a string">; //===----------------------------------------------------------------------===// @@ -251,7 +255,7 @@ def ext_pp_comma_expr : Extension<"comma operator in operand of #if">; def ext_pp_bad_vaargs_use : Extension< "__VA_ARGS__ can only appear in the expansion of a C99 variadic macro">; def ext_pp_macro_redef : ExtWarn<"%0 macro redefined">; -def ext_variadic_macro : Extension<"variadic macros were introduced in C99">, +def ext_variadic_macro : Extension<"variadic macros are a C99 feature">, InGroup<VariadicMacros>; def warn_cxx98_compat_variadic_macro : Warning< "variadic macros are incompatible with C++98">, @@ -264,15 +268,19 @@ def ext_embedded_directive : Extension< "embedding a directive within macro arguments has undefined behavior">, InGroup<DiagGroup<"embedded-directive">>; def ext_missing_varargs_arg : Extension< - "varargs argument missing, but tolerated as an extension">; + "must specify at least one argument for '...' parameter of variadic macro">, + InGroup<GNU>; def ext_empty_fnmacro_arg : Extension< - "empty macro arguments were standardized in C99">; + "empty macro arguments are a C99 feature">, InGroup<C99>; def warn_cxx98_compat_empty_fnmacro_arg : Warning< - "empty macro argument list is incompatible with C++98">, + "empty macro arguments are incompatible with C++98">, InGroup<CXX98CompatPedantic>, DefaultIgnore; +def note_macro_here : Note<"macro %0 defined here">; def err_pp_invalid_directive : Error<"invalid preprocessing directive">; def err_pp_file_not_found : Error<"'%0' file not found">, DefaultFatal; +def err_pp_file_not_found_not_fatal : Error< + "'%0' file not found with <angled> include; use \"quotes\" instead">; def err_pp_error_opening_file : Error< "error opening file '%0': %1">, DefaultFatal; def err_pp_empty_filename : Error<"empty filename">; @@ -324,8 +332,7 @@ def err_feature_check_malformed : Error< "builtin feature check macro requires a parenthesized identifier">; def err_warning_check_malformed : Error< - "builtin warning check macro requires a parenthesized string">, - InGroup<MalformedWarningCheck>; + "builtin warning check macro requires a parenthesized string">; def warn_has_warning_invalid_option : ExtWarn<"__has_warning expected option name (e.g. \"-Wundef\")">, InGroup<MalformedWarningCheck>; @@ -394,7 +401,7 @@ def err_paste_at_start : Error< "'##' cannot appear at start of macro expansion">; def err_paste_at_end : Error<"'##' cannot appear at end of macro expansion">; def ext_paste_comma : Extension< - "Use of comma pasting extension is non-portable">; + "token pasting of ',' and __VA_ARGS__ is a GNU extension">, InGroup<GNU>; def err_unterm_macro_invoc : Error< "unterminated function-like macro invocation">; def err_too_many_args_in_macro_invoc : Error< @@ -412,6 +419,9 @@ def err_pp_illegal_floating_literal : Error< "floating point literal in preprocessor expression">; def err_pp_line_requires_integer : Error< "#line directive requires a positive integer argument">; +def ext_pp_line_zero : Extension< + "#line directive with zero argument is a GNU extension">, + InGroup<GNU>; def err_pp_line_invalid_filename : Error< "invalid filename for #line directive">; def warn_pp_line_decimal : Warning< diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index c183da7..8cb82fd 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -20,23 +20,32 @@ def warn_file_asm_volatile : Warning< let CategoryName = "Parse Issue" in { -def ext_empty_source_file : Extension<"ISO C forbids an empty source file">; -def ext_top_level_semi : Extension< - "extra ';' outside of a function">; +def ext_empty_translation_unit : Extension< + "ISO C requires a translation unit to contain at least one declaration.">, + InGroup<DiagGroup<"empty-translation-unit">>; def warn_cxx98_compat_top_level_semi : Warning< "extra ';' outside of a function is incompatible with C++98">, InGroup<CXX98CompatPedantic>, DefaultIgnore; -def ext_extra_struct_semi : Extension< - "extra ';' inside a %0">; -def ext_extra_ivar_semi : Extension< - "extra ';' inside instance variable list">; +def ext_extra_semi : Extension< + "extra ';' %select{" + "outside of a function|" + "inside a %1|" + "inside instance variable list|" + "after member function definition}0">, + InGroup<ExtraSemi>; +def ext_extra_semi_cxx11 : Extension< + "extra ';' outside of a function is a C++11 extension">, + InGroup<CXX11ExtraSemi>; +def warn_extra_semi_after_mem_fn_def : Warning< + "extra ';' after member function definition">, + InGroup<ExtraSemi>, DefaultIgnore; def ext_duplicate_declspec : Extension<"duplicate '%0' declaration specifier">; def ext_plain_complex : ExtWarn< "plain '_Complex' requires a type specifier; assuming '_Complex double'">; def ext_integer_complex : Extension< "complex integer types are an extension">; -def ext_thread_before : Extension<"'__thread' before 'static'">; +def ext_thread_before : Extension<"'__thread' before '%0'">; def ext_empty_struct_union : Extension< "empty %select{struct|union}0 is a GNU extension">, InGroup<GNU>; @@ -58,9 +67,12 @@ def ext_c99_compound_literal : Extension< "compound literals are a C99-specific feature">, InGroup<C99>; def ext_c99_flexible_array_member : Extension< "Flexible array members are a C99-specific feature">, InGroup<C99>; -def ext_enumerator_list_comma : Extension< - "commas at the end of enumerator lists are a %select{C99|C++11}0-specific " - "feature">; +def ext_enumerator_list_comma_c : Extension< + "commas at the end of enumerator lists are a C99-specific " + "feature">, InGroup<C99>; +def ext_enumerator_list_comma_cxx : Extension< + "commas at the end of enumerator lists are a C++11 extension">, + InGroup<CXX11>; def warn_cxx98_compat_enumerator_list_comma : Warning< "commas at the end of enumerator lists are incompatible with C++98">, InGroup<CXX98CompatPedantic>, DefaultIgnore; @@ -89,8 +101,8 @@ def err_duplicate_default_assoc : Error< def note_previous_default_assoc : Note< "previous default generic association is here">; -def ext_c11_alignas : Extension< - "_Alignas is a C11-specific feature">, InGroup<C11>; +def ext_c11_alignment : Extension< + "%0 is a C11-specific feature">, InGroup<C11>; def ext_gnu_indirect_goto : Extension< "use of GNU indirect-goto extension">, InGroup<GNU>; @@ -311,7 +323,7 @@ def err_templated_using_directive : Error< def err_templated_using_declaration : Error< "cannot template a using declaration">; def err_unexected_colon_in_nested_name_spec : Error< - "unexpected ':' in nested name specifier">; + "unexpected ':' in nested name specifier; did you mean '::'?">; def err_bool_redeclaration : Error< "redeclaration of C++ built-in type 'bool'">; def ext_c11_static_assert : Extension< @@ -336,6 +348,9 @@ def err_illegal_super_cast : Error< "cannot cast 'super' (it isn't an expression)">; def err_nsnumber_nonliteral_unary : Error< "@%0 must be followed by a number to form an NSNumber object">; +def warn_cstyle_param : Warning< + "use of C-style parameters in Objective-C method declarations" + " is deprecated">, InGroup<DeprecatedDeclarations>; let CategoryName = "ARC Parse Issue" in { def err_arc_bridge_retain : Error< @@ -377,6 +392,8 @@ def err_synthesized_property_name : Error< def warn_semicolon_before_method_body : Warning< "semicolon before method body is ignored">, InGroup<DiagGroup<"semicolon-before-method-body">>, DefaultIgnore; +def note_extra_comma_message_arg : Note< + "comma separating Objective-C messaging arguments">; def err_expected_field_designator : Error< "expected a field designator, such as '.field = 4'">; @@ -396,9 +413,8 @@ def err_expected_init_in_condition : Error< "variable declaration in condition must have an initializer">; def err_expected_init_in_condition_lparen : Error< "variable declaration in condition cannot have a parenthesized initializer">; -def warn_parens_disambiguated_as_function_decl : Warning< - "parentheses were disambiguated as a function declarator">, - InGroup<VexingParse>; +def err_extraneous_rparen_in_condition : Error< + "extraneous ')' after condition, expected a statement">; def warn_dangling_else : Warning< "add explicit braces to avoid dangling else">, InGroup<DanglingElse>; @@ -474,6 +490,10 @@ def err_l_square_l_square_not_attribute : Error< "introducing an attribute">; def err_alignas_pack_exp_unsupported : Error< "pack expansions in alignment specifiers are not supported yet">; +def err_ms_declspec_type : Error< + "__declspec attributes must be an identifier or string literal">; +def warn_ms_declspec_unknown : Warning< + "unknown __declspec attribute %0 ignored">, InGroup<UnknownAttributes>; /// C++ Templates def err_expected_template : Error<"expected template">; @@ -491,9 +511,12 @@ def err_id_after_template_in_nested_name_spec : Error< "expected template name after 'template' keyword in nested name specifier">; def err_two_right_angle_brackets_need_space : Error< "a space is required between consecutive right angle brackets (use '> >')">; +def err_right_angle_bracket_equal_needs_space : Error< + "a space is required between a right angle bracket and an equals sign " + "(use '> =')">; def warn_cxx0x_right_shift_in_template_arg : Warning< "use of right-shift operator ('>>') in template argument will require " - "parentheses in C++11">; + "parentheses in C++11">, InGroup<CXX11Compat>; def warn_cxx98_compat_two_right_angle_brackets : Warning< "consecutive right angle brackets are incompatible with C++98 (use '> >')">, InGroup<CXX98Compat>, DefaultIgnore; @@ -648,9 +671,11 @@ def err_availability_unknown_change : Error< "%0 is not an availability stage; use 'introduced', 'deprecated', or " "'obsoleted'">; def err_availability_redundant : Error< - "redundant %0 availability change; only the last specified change will " "be used">; + "redundant %0 availability change; only the last specified change will " + "be used">; def warn_availability_and_unavailable : Warning< - "'unavailable' availability overrides all other availability information">; + "'unavailable' availability overrides all other availability information">, + InGroup<Availability>; // Language specific pragmas // - Generic warnings diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 0614ade..6d7b52e 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -14,6 +14,19 @@ let Component = "Sema" in { let CategoryName = "Semantic Issue" in { +// For loop analysis +def warn_variables_not_in_loop_body : Warning< + "variable%select{s| %1|s %1 and %2|s %1, %2, and %3|s %1, %2, %3, and %4}0 " + "used in loop condition not modified in loop body">, + InGroup<DiagGroup<"loop-analysis">>, DefaultIgnore; + +def warn_identical_enum_values : Warning< + "all elements of %0 are initialized with literals to value %1">, + InGroup<DiagGroup<"unique-enum">>; +def note_identical_enum_values : Note< + "initialize the last element with the previous element to silence " + "this warning">; + // Constant expressions def err_expr_not_ice : Error< "expression is not an %select{integer|integral}0 constant expression">; @@ -145,6 +158,11 @@ def warn_redefinition_in_param_list : Warning< def warn_empty_parens_are_function_decl : Warning< "empty parentheses interpreted as a function declaration">, InGroup<VexingParse>; +def warn_parens_disambiguated_as_function_declaration : Warning< + "parentheses were disambiguated as a function declaration">, + InGroup<VexingParse>; +def note_additional_parens_for_variable_declaration : Note< + "add a pair of parentheses to declare a variable">; def note_empty_parens_function_call : Note< "change this ',' to a ';' to call %0">; def note_empty_parens_default_ctor : Note< @@ -160,9 +178,15 @@ def warn_used_but_marked_unused: Warning<"%0 was marked unused but was used">, def warn_unneeded_internal_decl : Warning< "%select{function|variable}0 %1 is not needed and will not be emitted">, InGroup<UnneededInternalDecl>, DefaultIgnore; +def warn_unneeded_static_internal_decl : Warning< + "'static' function %0 declared in header file " + "should be declared 'static inline'">, + InGroup<UnneededInternalDecl>, DefaultIgnore; def warn_unneeded_member_function : Warning< "member function %0 is not needed and will not be emitted">, InGroup<UnneededMemberFunction>, DefaultIgnore; +def warn_unused_private_field: Warning<"private field %0 is not used">, + InGroup<UnusedPrivateField>, DefaultIgnore; def warn_parameter_size: Warning< "%0 is a large (%1 bytes) pass-by-value argument; " @@ -173,6 +197,9 @@ def warn_return_value_size: Warning< def warn_return_value_udt: Warning< "%0 has C-linkage specified, but returns user-defined type %1 which is " "incompatible with C">, InGroup<ReturnTypeCLinkage>; +def warn_return_value_udt_incomplete: Warning< + "%0 has C-linkage specified, but returns incomplete type %1 which could be " + "incompatible with C">, InGroup<ReturnTypeCLinkage>; def warn_implicit_function_decl : Warning< "implicit declaration of function %0">, InGroup<ImplicitFunctionDeclare>, DefaultIgnore; @@ -325,10 +352,14 @@ def warn_dyn_class_memaccess : Warning< def note_bad_memaccess_silence : Note< "explicitly cast the pointer to silence this warning">; def warn_sizeof_pointer_expr_memaccess : Warning< - "argument to 'sizeof' in %0 call is the same expression as the " - "%select{destination|source}1; did you mean to " - "%select{dereference it|remove the addressof|provide an explicit length}2?">, + "'%0' call operates on objects of type %1 while the size is based on a " + "different type %2">, InGroup<DiagGroup<"sizeof-pointer-memaccess">>; +def warn_sizeof_pointer_expr_memaccess_note : Note< + "did you mean to %select{dereference the argument to 'sizeof' (and multiply " + "it by the number of elements)|remove the addressof in the argument to " + "'sizeof' (and multiply it by the number of elements)|provide an explicit " + "length}0?">; def warn_sizeof_pointer_type_memaccess : Warning< "argument to 'sizeof' in %0 call is the same pointer type %1 as the " "%select{destination|source}2; expected %3 or an explicit length">, @@ -342,9 +373,11 @@ def note_strlcpycat_wrong_size : Note< def warn_strncat_large_size : Warning< "the value of the size argument in 'strncat' is too large, might lead to a " - "buffer overflow">, InGroup<StrncatSize>, DefaultIgnore; + "buffer overflow">, InGroup<StrncatSize>; def warn_strncat_src_size : Warning<"size argument in 'strncat' call appears " - "to be size of the source">, InGroup<StrncatSize>, DefaultIgnore; + "to be size of the source">, InGroup<StrncatSize>; +def warn_strncat_wrong_size : Warning< + "the value of the size argument to 'strncat' is wrong">, InGroup<StrncatSize>; def note_strncat_wrong_size : Note< "change the argument to be the free space in the destination buffer minus " "the terminating null byte">; @@ -442,6 +475,8 @@ def err_class_extension_after_impl : Error< "cannot declare class extension for %0 after class implementation">; def note_implementation_declared : Note< "class implementation is declared here">; +def note_while_in_implementation : Note< + "detected while default synthesizing properties in class implementation">; def note_class_declared : Note< "class is declared here">; def note_receiver_is_id : Note< @@ -452,7 +487,7 @@ def err_objc_root_class_subclass : Error< "objc_root_class attribute may only be specified on a root class declaration">; def warn_objc_root_class_missing : Warning< "class %0 defined without specifying a base class">, - InGroup<ObjCRootClass>, DefaultIgnore; + InGroup<ObjCRootClass>; def note_objc_needs_superclass : Note< "add a super class to fix this problem">; def warn_dup_category_def : Warning< @@ -462,7 +497,7 @@ def err_dup_implementation_class : Error<"reimplementation of class %0">; def err_dup_implementation_category : Error< "reimplementation of category %1 for class %0">; def err_conflicting_ivar_type : Error< - "instance variable %0 has conflicting type: %1 vs %2">; + "instance variable %0 has conflicting type%diff{: $ vs $|}1,2">; def err_duplicate_ivar_declaration : Error< "instance variable is already declared">; def warn_on_superclass_use : Warning< @@ -481,12 +516,12 @@ def note_required_for_protocol_at : def warn_conflicting_overriding_ret_types : Warning< "conflicting return type in " - "declaration of %0: %1 vs %2">, + "declaration of %0%diff{: $ vs $|}1,2">, InGroup<OverridingMethodMismatch>, DefaultIgnore; def warn_conflicting_ret_types : Warning< "conflicting return type in " - "implementation of %0: %1 vs %2">; + "implementation of %0%diff{: $ vs $|}1,2">; def warn_conflicting_overriding_ret_type_modifiers : Warning< "conflicting distributed object modifiers on return type " @@ -510,12 +545,12 @@ def warn_non_covariant_ret_types : Warning< def warn_conflicting_overriding_param_types : Warning< "conflicting parameter types in " - "declaration of %0: %1 vs %2">, + "declaration of %0%diff{: $ vs $|}1,2">, InGroup<OverridingMethodMismatch>, DefaultIgnore; def warn_conflicting_param_types : Warning< "conflicting parameter types in " - "implementation of %0: %1 vs %2">; + "implementation of %0%diff{: $ vs $|}1,2">; def warn_conflicting_param_modifiers : Warning< "conflicting distributed object modifiers on parameter type " "in implementation of %0">, @@ -575,15 +610,17 @@ def err_objc_property_requires_object : Error< "property with '%0' attribute must be of object type">; def warn_objc_property_no_assignment_attribute : Warning< "no 'assign', 'retain', or 'copy' attribute is specified - " - "'assign' is assumed">; + "'assign' is assumed">, + InGroup<ObjCPropertyNoAttribute>; def warn_objc_isa_use : Warning< "direct access to objective-c's isa is deprecated " "in favor of object_setClass() and object_getClass()">, InGroup<DiagGroup<"deprecated-objc-isa-usage">>; def warn_objc_property_default_assign_on_object : Warning< - "default property attribute 'assign' not appropriate for non-gc object">; + "default property attribute 'assign' not appropriate for non-GC object">, + InGroup<ObjCPropertyNoAttribute>; def warn_property_attr_mismatch : Warning< - "property attribute in continuation class does not match the primary class">; + "property attribute in class extension does not match the primary class">; def warn_objc_property_copy_missing_on_block : Warning< "'copy' attribute must be specified for the block property " "when -fobjc-gc-only is specified">; @@ -610,9 +647,19 @@ def warn_auto_synthesizing_protocol_property :Warning< "auto property synthesis will not synthesize property" " declared in a protocol">, InGroup<DiagGroup<"objc-protocol-property-synthesis">>; +def warn_autosynthesis_property_ivar_match :Warning< + "autosynthesized property %0 will use %select{|synthesized}1 instance variable " + "%2, not existing instance variable %3">, + InGroup<DiagGroup<"objc-autosynthesis-property-ivar-name-match">>; +def warn_missing_explicit_synthesis : Warning < + "auto property synthesis is synthesizing property not explicitly synthesized">, + InGroup<DiagGroup<"objc-missing-property-synthesis">>, DefaultIgnore; def warn_property_getter_owning_mismatch : Warning< "property declared as returning non-retained objects" "; getter returning retained objects">; +def error_property_setter_ambiguous_use : Error< + "synthesized properties '%0' and '%1' both claim setter %2 -" + " use of this setter will cause unexpected behavior">; def err_ownin_getter_rule : Error< "property's synthesized getter follows Cocoa naming" " convention for returning 'owned' objects">; @@ -621,16 +668,16 @@ def warn_default_atomic_custom_getter_setter : Warning< "(property should be marked 'atomic' if this is intended)">, InGroup<CustomAtomic>, DefaultIgnore; def err_use_continuation_class : Error< - "illegal redeclaration of property in continuation class %0" + "illegal redeclaration of property in class extension %0" " (attribute must be 'readwrite', while its primary must be 'readonly')">; def err_type_mismatch_continuation_class : Error< - "type of property %0 in continuation class does not match " + "type of property %0 in class extension does not match " "property type in primary class">; def err_use_continuation_class_redeclaration_readwrite : Error< - "illegal redeclaration of 'readwrite' property in continuation class %0" + "illegal redeclaration of 'readwrite' property in class extension %0" " (perhaps you intended this to be a 'readwrite' redeclaration of a " "'readonly' public property?)">; -def err_continuation_class : Error<"continuation class has no primary class">; +def err_continuation_class : Error<"class extension has no primary class">; def err_property_type : Error<"property cannot have array or function type %0">; def error_missing_property_context : Error< "missing context for property implementation declaration">; @@ -664,15 +711,16 @@ def warn_arc_perform_selector_leaks : Warning< def err_gc_weak_property_strong_type : Error< "weak attribute declared on a __strong type property in GC mode">; def warn_receiver_is_weak : Warning < - "weak receiver may be unpredictably null in ARC mode">, + "weak %select{receiver|property|implicit property}0 may be " + "unpredictably null in ARC mode">, InGroup<DiagGroup<"receiver-is-weak">>, DefaultIgnore; - -def error_synthesized_ivar_yet_not_supported : Error< - "instance variable synthesis not yet supported" - " (need to declare %0 explicitly)">; +def err_incomplete_synthesized_property : Error< + "cannot synthesize property %0 with incomplete type %1">; def error_property_ivar_type : Error< "type of property %0 (%1) does not match type of ivar %2 (%3)">; +def error_property_accessor_type : Error< + "type of property %0 (%1) does not match type of accessor %2 (%3)">; def error_ivar_in_superclass_use : Error< "property %0 attempting to use ivar %1 declared in super class %2">; def error_weak_property : Error< @@ -690,6 +738,9 @@ def warn_objc_property_attr_mutually_exclusive : Warning< def warn_objc_missing_super_dealloc : Warning< "method possibly missing a [super dealloc] call">, InGroup<ObjCMissingSuperCalls>; +def error_dealloc_bad_result_type : Error< + "dealloc return type must be correctly specified as 'void' under ARC, " + "instead of %0">; def warn_objc_missing_super_finalize : Warning< "method possibly missing a [super finalize] call">, InGroup<ObjCMissingSuperCalls>; @@ -697,6 +748,12 @@ def warn_undeclared_selector : Warning< "undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore; def warn_implicit_atomic_property : Warning< "property is assumed atomic by default">, InGroup<ImplicitAtomic>, DefaultIgnore; +def note_auto_readonly_iboutlet_fixup_suggest : Note< + "readonly IBOutlet property should be changed to be readwrite">; +def warn_auto_readonly_iboutlet_property : Warning< + "readonly IBOutlet property when auto-synthesized may " + "not work correctly with 'nib' loader">, + InGroup<DiagGroup<"readonly-iboutlet-property">>; def warn_auto_implicit_atomic_property : Warning< "property is assumed atomic when auto-synthesizing the property">, InGroup<ImplicitAtomic>, DefaultIgnore; @@ -823,8 +880,6 @@ def warn_missing_exception_specification : Warning< "%0 is missing exception specification '%1'">; def err_noexcept_needs_constant_expression : Error< "argument to noexcept specifier must be a constant expression">; -def err_exception_spec_unknown : Error< - "exception specification is not available until end of class definition">; // C++ access checking def err_class_redeclared_with_different_access : Error< @@ -854,6 +909,9 @@ def err_access_field_ctor : Error< "field of type %0 has %select{private|protected}2 " "%select{default |copy |move |*ERROR* |*ERROR* |*ERROR* |}1constructor">, AccessControl; +def err_access_friend_function : Error< + "friend function %1 is a %select{private|protected}0 member of %3">, + AccessControl; def err_access_dtor : Error< "calling a %select{private|protected}1 destructor of class %0">, @@ -1015,8 +1073,9 @@ def ext_anonymous_struct_union_qualified : Extension< "anonymous %select{struct|union}0 cannot be '%select{const|volatile|" "restrict}1'">; def err_different_return_type_for_overriding_virtual_function : Error< - "virtual function %0 has a different return type (%1) than the " - "function it overrides (which has return type %2)">; + "virtual function %0 has a different return type " + "%diff{($) than the function it overrides (which has return type $)|" + "than the function it overrides}1,2">; def note_overridden_virtual_function : Note< "overridden virtual function is here">; @@ -1094,36 +1153,43 @@ def err_destructor_template : Error< def err_init_conversion_failed : Error< "cannot initialize %select{a variable|a parameter|return object|an " "exception object|a member subobject|an array element|a new value|a value|a " - "base class|a constructor delegation|a vector element}0 of type %1 with an " - "%select{rvalue|lvalue}2 of type %3" - "%select{|: different classes (%5 vs %6)" + "base class|a constructor delegation|a vector element}0 " + "%diff{of type $ with an %select{rvalue|lvalue}2 of type $|" + "with an %select{rvalue|lvalue}2 of incompatible type}1,3" + "%select{|: different classes%diff{ ($ vs $)|}5,6" "|: different number of parameters (%5 vs %6)" - "|: type mismatch at %ordinal5 parameter (%6 vs %7)" - "|: different return type (%5 vs %6)" + "|: type mismatch at %ordinal5 parameter%diff{ ($ vs $)|}6,7" + "|: different return type%diff{ ($ vs $)|}5,6" "|: different qualifiers (" "%select{none|const|restrict|const and restrict|volatile|const and volatile|" "volatile and restrict|const, volatile, and restrict}5 vs " "%select{none|const|restrict|const and restrict|volatile|const and volatile|" "volatile and restrict|const, volatile, and restrict}6)}4">; -def err_lvalue_to_rvalue_ref : Error<"rvalue reference to type %0 cannot bind " - "to lvalue of type %1">; +def err_lvalue_to_rvalue_ref : Error<"rvalue reference %diff{to type $ cannot " + "bind to lvalue of type $|cannot bind to incompatible lvalue}0,1">; def err_lvalue_reference_bind_to_initlist : Error< "%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to an " "initializer list temporary">; def err_lvalue_reference_bind_to_temporary : Error< - "%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to a " - "temporary of type %2">; + "%select{non-const|volatile}0 lvalue reference %diff{to type $ cannot bind " + "to a temporary of type $|cannot bind to incompatible temporary}1,2">; def err_lvalue_reference_bind_to_unrelated : Error< - "%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to a " - "value of unrelated type %2">; + "%select{non-const|volatile}0 lvalue reference " + "%diff{to type $ cannot bind to a value of unrelated type $|" + "cannot bind to a value of unrelated type}1,2">; def err_reference_bind_drops_quals : Error< - "binding of reference to type %0 to a value of type %1 drops qualifiers">; + "binding of reference %diff{to type $ to a value of type $ drops qualifiers|" + "drops qualifiers}0,1">; def err_reference_bind_failed : Error< - "reference to type %0 could not bind to an %select{rvalue|lvalue}1 of type " - "%2">; + "reference %diff{to type $ could not bind to an %select{rvalue|lvalue}1 of " + "type $|could not bind to %select{rvalue|lvalue}1 of incompatible type}0,2">; def err_reference_bind_init_list : Error< "reference to type %0 cannot bind to an initializer list">; +def warn_temporary_array_to_pointer_decay : Warning< + "pointer is initialized by a temporary array, which will be destroyed at the " + "end of the full-expression">, + InGroup<DiagGroup<"address-of-array-temporary">>; def err_init_list_bad_dest_type : Error< "%select{|non-aggregate }0type %1 cannot be initialized with an initializer " "list">; @@ -1154,19 +1220,21 @@ def warn_uninit_self_reference_in_init : Warning< "variable %0 is uninitialized when used within its own initialization">, InGroup<Uninitialized>; def warn_uninit_var : Warning< - "variable %0 is uninitialized when used here">, - InGroup<Uninitialized>, DefaultIgnore; -def warn_maybe_uninit_var : - Warning<"variable %0 may be uninitialized when used here">, - InGroup<UninitializedMaybe>, DefaultIgnore; -def note_uninit_var_def : Note< - "variable %0 is declared here">; -def warn_uninit_var_captured_by_block : Warning< - "variable %0 is uninitialized when captured by block">, + "variable %0 is uninitialized when %select{used here|captured by block}1">, InGroup<Uninitialized>, DefaultIgnore; -def warn_maybe_uninit_var_captured_by_block : Warning< - "variable %0 may be uninitialized when captured by block">, +def warn_sometimes_uninit_var : Warning< + "variable %0 is %select{used|captured}1 uninitialized whenever " + "%select{'%3' condition is %select{true|false}4|" + "'%3' loop %select{is entered|exits because its condition is false}4|" + "'%3' loop %select{condition is true|exits because its condition is false}4|" + "switch %3 is taken}2">, InGroup<UninitializedSometimes>, DefaultIgnore; +def warn_maybe_uninit_var : Warning< + "variable %0 may be uninitialized when " + "%select{used here|captured by block}1">, InGroup<UninitializedMaybe>, DefaultIgnore; +def note_uninit_var_def : Note<"variable %0 is declared here">; +def note_uninit_var_use : Note< + "%select{uninitialized use occurs|variable is captured by block}0 here">; def warn_uninit_byref_blockvar_captured_by_block : Warning< "block pointer variable %0 is uninitialized when captured by block">, InGroup<Uninitialized>, DefaultIgnore; @@ -1174,6 +1242,9 @@ def note_block_var_fixit_add_initialization : Note< "maybe you meant to use __block %0">; def note_var_fixit_add_initialization : Note< "initialize the variable %0 to silence this warning">; +def note_uninit_fixit_remove_cond : Note< + "remove the %select{'%1' if its condition|condition if it}0 " + "is always %select{false|true}2">; def err_init_incomplete_type : Error<"initialization of incomplete type %0">; def err_temp_copy_no_viable : Error< @@ -1316,10 +1387,8 @@ def err_delegating_initializer_alone : Error< def warn_delegating_ctor_cycle : Warning< "constructor for %0 creates a delegation cycle">, DefaultError, InGroup<DelegatingCtorCycles>; -def note_it_delegates_to : Note< - "it delegates to">, InGroup<DelegatingCtorCycles>; -def note_which_delegates_to : Note< - "which delegates to">, InGroup<DelegatingCtorCycles>; +def note_it_delegates_to : Note<"it delegates to">; +def note_which_delegates_to : Note<"which delegates to">; // C++11 range-based for loop def err_for_range_decl_must_be_var : Error< @@ -1370,6 +1439,8 @@ def err_constexpr_virtual : Error<"virtual function cannot be constexpr">; def err_constexpr_virtual_base : Error< "constexpr %select{member function|constructor}0 not allowed in " "%select{class|struct}1 with virtual base %plural{1:class|:classes}2">; +def note_non_literal_incomplete : Note< + "incomplete type %0 is not a literal type">; def note_non_literal_virtual_base : Note<"%select{class|struct}0 with virtual " "base %plural{1:class|:classes}1 is not a literal type">; def note_constexpr_virtual_base_here : Note<"virtual base class declared here">; @@ -1427,6 +1498,10 @@ def warn_cxx98_compat_unicode_type : Warning< // Objective-C++ def err_objc_decls_may_only_appear_in_global_scope : Error< "Objective-C declarations may only appear in global scope">; +def warn_auto_var_is_id : Warning< + "'auto' deduced as 'id' in declaration of %0">, + InGroup<DiagGroup<"auto-var-id">>; + // Attributes def err_nsobject_attribute : Error< "__attribute ((NSObject)) is for pointer types only">; @@ -1451,6 +1526,8 @@ def err_attribute_bad_neon_vector_size : Error< "Neon vector size must be 64 or 128 bits">; def err_attribute_argument_not_int : Error< "'%0' attribute requires integer constant">; +def err_aligned_attribute_argument_not_int : Error< + "'aligned' attribute requires integer constant">; def err_attribute_argument_not_class : Error< "%0 attribute requires arguments that are class type or point to class type">; def err_attribute_first_argument_not_int_or_bool : Error< @@ -1522,17 +1599,19 @@ def err_undeclared_nsnumber : Error< "NSNumber must be available to use Objective-C literals">; def err_invalid_nsnumber_type : Error< "%0 is not a valid literal type for NSNumber">; +def err_undeclared_nsstring : Error< + "cannot box a string value because NSString has not been declared">; +def err_objc_illegal_boxed_expression_type : Error< + "illegal type %0 used in a boxed expression">; +def err_objc_incomplete_boxed_expression_type : Error< + "incomplete type %0 used in a boxed expression">; def err_undeclared_nsarray : Error< "NSArray must be available to use Objective-C array literals">; def err_undeclared_nsdictionary : Error< "NSDictionary must be available to use Objective-C dictionary " "literals">; -def err_undeclared_arraywithobjects : Error< - "declaration of %0 is missing in NSArray class">; -def err_undeclared_dictwithobjects : Error< - "declaration of %0 is missing in NSDictionary class">; -def err_undeclared_nsnumber_method : Error< - "declaration of %0 is missing in NSNumber class">; +def err_undeclared_boxing_method : Error< + "declaration of %0 is missing in %1 class">; def err_objc_literal_method_sig : Error< "literal construction method %0 has incompatible signature">; def note_objc_literal_method_param : Note< @@ -1545,50 +1624,81 @@ def err_invalid_collection_element : Error< def err_box_literal_collection : Error< "%select{string|character|boolean|numeric}0 literal must be prefixed by '@' " "in a collection">; +def warn_objc_literal_comparison : Warning< + "direct comparison of %select{an array literal|a dictionary literal|" + "a numeric literal|a boxed expression|}0 has undefined behavior">, + InGroup<ObjCLiteralComparison>; +def warn_objc_string_literal_comparison : Warning< + "direct comparison of a string literal has undefined behavior">, + InGroup<ObjCStringComparison>; +def note_objc_literal_comparison_isequal : Note< + "use 'isEqual:' instead">; let CategoryName = "Cocoa API Issue" in { def warn_objc_redundant_literal_use : Warning< "using %0 with a literal is redundant">, InGroup<ObjCRedundantLiteralUse>; } +def err_attr_tlsmodel_arg : Error<"tls_model must be \"global-dynamic\", " + "\"local-dynamic\", \"initial-exec\" or \"local-exec\"">; + def err_only_annotate_after_access_spec : Error< "access specifier can only have annotation attributes">; + def err_attribute_section_invalid_for_target : Error< "argument to 'section' attribute is not valid for this target: %0">; def err_attribute_section_local_variable : Error< "'section' attribute is not valid on local variables">; +def warn_mismatched_section : Warning< + "section does not match previous declaration">, InGroup<Section>; + def err_attribute_aligned_not_power_of_two : Error< "requested alignment is not a power of 2">; +def err_attribute_aligned_greater_than_8192 : Error< + "requested alignment must be 8192 bytes or smaller">; def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning< "'%0' redeclared without %1 attribute: previous %1 ignored">; -def warn_attribute_ignored : Warning<"%0 attribute ignored">; +def warn_attribute_ignored : Warning<"%0 attribute ignored">, + InGroup<IgnoredAttributes>; +def warn_attribute_after_definition_ignored : Warning< + "attribute %0 after definition is ignored">, + InGroup<IgnoredAttributes>; def warn_unknown_attribute_ignored : Warning< "unknown attribute %0 ignored">, InGroup<UnknownAttributes>; +def warn_unhandled_ms_attribute_ignored : Warning< + "__declspec attribute %0 is not supported">, + InGroup<IgnoredAttributes>; def warn_attribute_invalid_on_stmt : Warning< "attribute %0 cannot be specified on a statement">, InGroup<IgnoredAttributes>; def warn_declspec_attribute_ignored : Warning< "attribute %0 is ignored, place it after \"%select{class|struct|union|enum}1\" to apply attribute to type declaration">, InGroup<IgnoredAttributes>; def warn_attribute_precede_definition : Warning< - "attribute declaration must precede definition">; + "attribute declaration must precede definition">, + InGroup<IgnoredAttributes>; def warn_attribute_void_function_method : Warning< "attribute %0 cannot be applied to " - "%select{functions|Objective-C method}1 without return value">; + "%select{functions|Objective-C method}1 without return value">, + InGroup<IgnoredAttributes>; def warn_attribute_weak_on_field : Warning< - "__weak attribute cannot be specified on a field declaration">; + "__weak attribute cannot be specified on a field declaration">, + InGroup<IgnoredAttributes>; def warn_gc_attribute_weak_on_local : Warning< - "Objective-C GC does not allow weak variables on the stack">; + "Objective-C GC does not allow weak variables on the stack">, + InGroup<IgnoredAttributes>; def warn_nsobject_attribute : Warning< "__attribute ((NSObject)) may be put on a typedef only, " "attribute is ignored">, InGroup<NSobjectAttribute>; def warn_attribute_weak_on_local : Warning< - "__weak attribute cannot be specified on an automatic variable">; + "__weak attribute cannot be specified on an automatic variable">, + InGroup<IgnoredAttributes>; def warn_weak_identifier_undeclared : Warning< "weak identifier %0 never declared">; def err_attribute_weak_static : Error< "weak declaration cannot have internal linkage">; def warn_attribute_weak_import_invalid_on_definition : Warning< - "'weak_import' attribute cannot be specified on a definition">; + "'weak_import' attribute cannot be specified on a definition">, + InGroup<IgnoredAttributes>; def err_attribute_weakref_not_static : Error< "weakref declaration must have internal linkage">; def err_attribute_weakref_not_global_context : Error< @@ -1602,22 +1712,31 @@ def warn_attribute_wrong_decl_type : Warning< "variables and functions|functions and methods|parameters|" "functions, methods and blocks|functions, methods, and parameters|" "classes|variables|methods|variables, functions and labels|" - "fields and global variables|structs}1">; + "fields and global variables|structs|" + "variables, functions and tag types|thread-local variables}1">, + InGroup<IgnoredAttributes>; def err_attribute_wrong_decl_type : Error< "%0 attribute only applies to %select{functions|unions|" "variables and functions|functions and methods|parameters|" "functions, methods and blocks|functions, methods, and parameters|" "classes|variables|methods|variables, functions and labels|" - "fields and global variables|structs}1">; + "fields and global variables|structs|thread-local variables}1">; def warn_function_attribute_wrong_type : Warning< - "'%0' only applies to function types; type here is %1">; + "'%0' only applies to function types; type here is %1">, + InGroup<IgnoredAttributes>; def warn_pointer_attribute_wrong_type : Warning< - "'%0' only applies to pointer types; type here is %1">; + "'%0' only applies to pointer types; type here is %1">, + InGroup<IgnoredAttributes>; def warn_objc_object_attribute_wrong_type : Warning< - "'%0' only applies to objective-c object or block pointer types; type here is %1">; + "'%0' only applies to Objective-C object or block pointer types; type here is %1">, + InGroup<IgnoredAttributes>; +def warn_attribute_requires_functions_or_static_globals : Warning< + "%0 only applies to variables with static storage duration and functions">, + InGroup<IgnoredAttributes>; def warn_gnu_inline_attribute_requires_inline : Warning< "'gnu_inline' attribute requires function to be marked 'inline'," - " attribute ignored">; + " attribute ignored">, + InGroup<IgnoredAttributes>; def err_attribute_vecreturn_only_vector_member : Error< "the vecreturn attribute can only be used on a class or structure with one member, which must be a vector">; def err_attribute_vecreturn_only_pod_record : Error< @@ -1649,79 +1768,95 @@ def warn_attribute_not_on_decl : Error< // Availability attribute def warn_availability_unknown_platform : Warning< - "unknown platform %0 in availability macro">; + "unknown platform %0 in availability macro">, InGroup<Availability>; def warn_availability_version_ordering : Warning< "feature cannot be %select{introduced|deprecated|obsoleted}0 in %1 version " "%2 before it was %select{introduced|deprecated|obsoleted}3 in version %4; " - "attribute ignored">; - + "attribute ignored">, InGroup<Availability>; +def warn_mismatched_availability: Warning< + "availability does not match previous declaration">, InGroup<Availability>; + // Thread Safety Attributes -// Errors when parsing the attributes +def warn_thread_attribute_ignored : Warning< + "ignoring %0 attribute because its argument is invalid">, + InGroup<ThreadSafetyAttributes>, DefaultIgnore; +def warn_thread_attribute_argument_not_lockable : Warning< + "%0 attribute requires arguments whose type is annotated " + "with 'lockable' attribute; type here is '%1'">, + InGroup<ThreadSafetyAttributes>, DefaultIgnore; +def warn_thread_attribute_argument_not_class : Warning< + "%0 attribute requires arguments that are class type or point to" + " class type; type here is '%1'">, + InGroup<ThreadSafetyAttributes>, DefaultIgnore; +def warn_thread_attribute_decl_not_lockable : Warning< + "%0 attribute can only be applied in a context annotated " + "with 'lockable' attribute">, + InGroup<ThreadSafetyAttributes>, DefaultIgnore; +def warn_thread_attribute_decl_not_pointer : Warning< + "'%0' only applies to pointer types; type here is %1">, + InGroup<ThreadSafetyAttributes>, DefaultIgnore; +def warn_thread_attribute_wrong_decl_type : Warning< + "%0 attribute only applies to %select{" + "fields and global variables|functions and methods|" + "classes and structs}1">, + InGroup<ThreadSafetyAttributes>, DefaultIgnore; def err_attribute_argument_out_of_range : Error< "%0 attribute parameter %1 is out of bounds: " "%plural{0:no parameters to index into|" "1:can only be 1, since there is one parameter|" ":must be between 1 and %2}2">; -def warn_attribute_argument_not_lockable : Warning< - "%0 attribute requires arguments whose type is annotated " - "with 'lockable' attribute; type here is '%1'">, - InGroup<ThreadSafety>, DefaultIgnore; -def warn_attribute_decl_not_lockable : Warning< - "%0 attribute can only be applied in a context annotated " - "with 'lockable' attribute">, - InGroup<ThreadSafety>, DefaultIgnore; -def warn_attribute_argument_not_class : Warning< - "%0 attribute requires arguments that are class type or point to" - " class type; type here is '%1'">, - InGroup<ThreadSafety>, DefaultIgnore; + +// Thread Safety Analysis def warn_unlock_but_no_lock : Warning< "unlocking '%0' that was not locked">, - InGroup<ThreadSafety>, DefaultIgnore; + InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_double_lock : Warning< "locking '%0' that is already locked">, - InGroup<ThreadSafety>, DefaultIgnore; + InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_no_unlock : Warning< "mutex '%0' is still locked at the end of function">, - InGroup<ThreadSafety>, DefaultIgnore; + InGroup<ThreadSafetyAnalysis>, DefaultIgnore; +def warn_expecting_locked : Warning< + "expecting mutex '%0' to be locked at the end of function">, + InGroup<ThreadSafetyAnalysis>, DefaultIgnore; // FIXME: improve the error message about locks not in scope def warn_lock_some_predecessors : Warning< "mutex '%0' is not locked on every path through here">, - InGroup<ThreadSafety>, DefaultIgnore; + InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_expecting_lock_held_on_loop : Warning< "expecting mutex '%0' to be locked at start of each loop">, - InGroup<ThreadSafety>, DefaultIgnore; + InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def note_locked_here : Note<"mutex acquired here">; def warn_lock_exclusive_and_shared : Warning< "mutex '%0' is locked exclusively and shared in the same scope">, - InGroup<ThreadSafety>, DefaultIgnore; + InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def note_lock_exclusive_and_shared : Note< - "the other lock of mutex '%0' is here">, - InGroup<ThreadSafety>, DefaultIgnore; + "the other lock of mutex '%0' is here">; def warn_variable_requires_lock : Warning< "%select{reading|writing}2 variable '%0' requires locking " "%select{'%1'|'%1' exclusively}2">, - InGroup<ThreadSafety>, DefaultIgnore; + InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_var_deref_requires_lock : Warning< "%select{reading|writing}2 the value pointed to by '%0' requires locking " "%select{'%1'|'%1' exclusively}2">, - InGroup<ThreadSafety>, DefaultIgnore; + InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_variable_requires_any_lock : Warning< "%select{reading|writing}1 variable '%0' requires locking " "%select{any mutex|any mutex exclusively}1">, - InGroup<ThreadSafety>, DefaultIgnore; + InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_var_deref_requires_any_lock : Warning< "%select{reading|writing}1 the value pointed to by '%0' requires locking " "%select{any mutex|any mutex exclusively}1">, - InGroup<ThreadSafety>, DefaultIgnore; + InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_fun_requires_lock : Warning< "calling function '%0' requires %select{shared|exclusive}2 lock on '%1'">, - InGroup<ThreadSafety>, DefaultIgnore; + InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_fun_excludes_mutex : Warning< "cannot call function '%0' while mutex '%1' is locked">, - InGroup<ThreadSafety>, DefaultIgnore; + InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_cannot_resolve_lock : Warning< "cannot resolve lock expression">, - InGroup<ThreadSafety>, DefaultIgnore; + InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_impcast_vector_scalar : Warning< @@ -1755,8 +1890,7 @@ def warn_impcast_bitfield_precision_constant : Warning< "implicit truncation from %2 to bitfield changes value from %0 to %1">, InGroup<ConstantConversion>; def warn_impcast_literal_float_to_integer : Warning< - "implicit conversion turns literal floating-point number into integer: " - "%0 to %1">, + "implicit conversion from %0 to %1 changes value from %2 to %3">, InGroup<LiteralConversion>; def warn_impcast_string_literal_to_bool : Warning< "implicit conversion turns string literal into bool: %0 to %1">, @@ -1767,6 +1901,9 @@ def warn_impcast_different_enum_types : Warning< def warn_impcast_bool_to_null_pointer : Warning< "initialization of pointer of type %0 to null from a constant boolean " "expression">, InGroup<BoolConversion>; +def warn_non_literal_null_pointer : Warning< + "expression which evaluates to zero treated as a null pointer constant of " + "type %0">, InGroup<NonLiteralNullConversion>; def warn_impcast_null_pointer_to_integer : Warning< "implicit conversion of NULL constant to %0">, InGroup<NullConversion>; @@ -1783,28 +1920,37 @@ def warn_cast_align : Warning< InGroup<CastAlign>, DefaultIgnore; def warn_attribute_ignored_for_field_of_type : Warning< - "%0 attribute ignored for field of type %1">; + "%0 attribute ignored for field of type %1">, + InGroup<IgnoredAttributes>; def warn_transparent_union_attribute_field_size_align : Warning< "%select{alignment|size}0 of field %1 (%2 bits) does not match the " "%select{alignment|size}0 of the first field in transparent union; " - "transparent_union attribute ignored">; + "transparent_union attribute ignored">, + InGroup<IgnoredAttributes>; def note_transparent_union_first_field_size_align : Note< "%select{alignment|size}0 of first field is %1 bits">; def warn_transparent_union_attribute_not_definition : Warning< "transparent_union attribute can only be applied to a union definition; " - "attribute ignored">; + "attribute ignored">, + InGroup<IgnoredAttributes>; def warn_transparent_union_attribute_floating : Warning< "first field of a transparent union cannot have %select{floating point|" - "vector}0 type %1; transparent_union attribute ignored">; + "vector}0 type %1; transparent_union attribute ignored">, + InGroup<IgnoredAttributes>; def warn_transparent_union_attribute_zero_fields : Warning< "transparent union definition must contain at least one field; " - "transparent_union attribute ignored">; + "transparent_union attribute ignored">, + InGroup<IgnoredAttributes>; def warn_attribute_type_not_supported : Warning< - "'%0' attribute argument not supported: %1">; -def warn_attribute_unknown_visibility : Warning<"unknown visibility '%0'">; + "'%0' attribute argument not supported: %1">, + InGroup<IgnoredAttributes>; +def warn_attribute_unknown_visibility : Warning<"unknown visibility '%0'">, + InGroup<IgnoredAttributes>; def warn_attribute_protected_visibility : Warning<"target does not support 'protected' visibility; using 'default'">, InGroup<DiagGroup<"unsupported-visibility">>; +def err_mismatched_visibility: Error<"visibility does not match previous declaration">; +def note_previous_attribute : Note<"previous attribute is here">; def err_unknown_machine_mode : Error<"unknown machine mode %0">; def err_unsupported_machine_mode : Error<"unsupported machine mode %0">; def err_mode_not_primitive : Error< @@ -1814,13 +1960,17 @@ def err_mode_wrong_type : Error< def err_attr_wrong_decl : Error< "'%0' attribute invalid on this declaration, requires typedef or value">; def warn_attribute_nonnull_no_pointers : Warning< - "'nonnull' attribute applied to function with no pointer arguments">; + "'nonnull' attribute applied to function with no pointer arguments">, + InGroup<IgnoredAttributes>; def warn_attribute_malloc_pointer_only : Warning< - "'malloc' attribute only applies to functions returning a pointer type">; + "'malloc' attribute only applies to functions returning a pointer type">, + InGroup<IgnoredAttributes>; def warn_attribute_sentinel_named_arguments : Warning< - "'sentinel' attribute requires named arguments">; + "'sentinel' attribute requires named arguments">, + InGroup<IgnoredAttributes>; def warn_attribute_sentinel_not_variadic : Warning< - "'sentinel' attribute only supported for variadic %select{functions|blocks}0">; + "'sentinel' attribute only supported for variadic %select{functions|blocks}0">, + InGroup<IgnoredAttributes>; def err_attribute_sentinel_less_than_zero : Error< "'sentinel' parameter 1 less than zero">; def err_attribute_sentinel_not_zero_or_one : Error< @@ -1832,8 +1982,8 @@ def err_attribute_cleanup_arg_not_function : Error< def err_attribute_cleanup_func_must_take_one_arg : Error< "'cleanup' function %0 must take 1 parameter">; def err_attribute_cleanup_func_arg_incompatible_type : Error< - "'cleanup' function %0 parameter has type %1 which is incompatible with " - "type %2">; + "'cleanup' function %0 parameter has " + "%diff{type $ which is incompatible with type $|incompatible type}1,2">; def err_attribute_regparm_wrong_platform : Error< "'regparm' is not valid on this platform">; def err_attribute_regparm_invalid_number : Error< @@ -1842,9 +1992,11 @@ def err_attribute_regparm_invalid_number : Error< // Clang-Specific Attributes def warn_attribute_iboutlet : Warning< - "%0 attribute can only be applied to instance variables or properties">; + "%0 attribute can only be applied to instance variables or properties">, + InGroup<IgnoredAttributes>; def warn_attribute_ibaction: Warning< - "ibaction attribute can only be applied to Objective-C instance methods">; + "ibaction attribute can only be applied to Objective-C instance methods">, + InGroup<IgnoredAttributes>; def err_iboutletcollection_type : Error< "invalid type %0 as argument of iboutletcollection attribute">; def warn_iboutlet_object_type : Warning< @@ -1862,10 +2014,12 @@ def err_attribute_overloadable_no_prototype : Error< "'overloadable' function %0 must have a prototype">; def warn_ns_attribute_wrong_return_type : Warning< "%0 attribute only applies to %select{functions|methods}1 that " - "return %select{an Objective-C object|a pointer|a non-retainable pointer}2">; + "return %select{an Objective-C object|a pointer|a non-retainable pointer}2">, + InGroup<IgnoredAttributes>; def warn_ns_attribute_wrong_parameter_type : Warning< "%0 attribute only applies to %select{Objective-C object|pointer}1 " - "parameters">; + "parameters">, + InGroup<IgnoredAttributes>; def err_ns_bridged_not_interface : Error< "parameter of 'ns_bridged' attribute does not name an Objective-C class">; @@ -1928,8 +2082,9 @@ def note_default_argument_declared_here : Note< "default argument declared here">; def ext_param_promoted_not_compatible_with_prototype : ExtWarn< - "promoted type %0 of K&R function parameter is not compatible with the " - "parameter type %1 declared in a previous prototype">, + "%diff{promoted type $ of K&R function parameter is not compatible with the " + "parameter type $|promoted type of K&R function parameter is not compatible " + "with parameter type}0,1 declared in a previous prototype">, InGroup<KNRPromotedParameter>; @@ -1964,10 +2119,11 @@ def note_ovl_candidate : Note<"candidate " "is the implicit copy assignment operator|" "is the implicit move assignment operator|" "is an inherited constructor}0%1" - "%select{| has different class (expected %3 but has %4)" + "%select{| has different class%diff{ (expected $ but has $)|}3,4" "| has different number of parameters (expected %3 but has %4)" - "| has type mismatch at %ordinal3 parameter (expected %4 but has %5)" - "| has different return type (%3 expected but has %4)" + "| has type mismatch at %ordinal3 parameter" + "%diff{ (expected $ but has $)|}4,5" + "| has different return type%diff{ ($ expected but has $)|}3,4" "| has different qualifiers (expected " "%select{none|const|restrict|const and restrict|volatile|const and volatile" "|volatile and restrict|const, volatile, and restrict}3 but found " @@ -1981,7 +2137,7 @@ def note_ovl_candidate_incomplete_deduction : Note<"candidate template ignored: "couldn't infer template argument %0">; def note_ovl_candidate_inconsistent_deduction : Note< "candidate template ignored: deduced conflicting %select{types|values|" - "templates}0 for parameter %1 (%2 vs. %3)">; + "templates}0 for parameter %1%diff{ ($ vs. $)|}2,3">; def note_ovl_candidate_explicit_arg_mismatch_named : Note< "candidate template ignored: invalid explicitly-specified argument " "for template parameter %0">; @@ -1995,7 +2151,9 @@ def note_ovl_candidate_underqualified : Note< "candidate template ignored: can't deduce a type for %0 which would " "make %2 equal %1">; def note_ovl_candidate_substitution_failure : Note< - "candidate template ignored: substitution failure %0">; + "candidate template ignored: substitution failure%0%1">; +def note_ovl_candidate_disabled_by_enable_if : Note< + "candidate template ignored: disabled by %0%1">; // Note that we don't treat templates differently for this diagnostic. def note_ovl_candidate_arity : Note<"candidate " @@ -2009,6 +2167,17 @@ def note_ovl_candidate_arity : Note<"candidate " "not viable: requires%select{ at least| at most|}2 %3 argument%s3, but %4 " "%plural{1:was|:were}4 provided">; +def note_ovl_candidate_arity_one : Note<"candidate " + "%select{function|function|constructor|function|function|constructor|" + "constructor (the implicit default constructor)|" + "constructor (the implicit copy constructor)|" + "constructor (the implicit move constructor)|" + "function (the implicit copy assignment operator)|" + "function (the implicit move assignment operator)|" + "constructor (inherited)}0 %select{|template }1not viable: " + "%select{requires at least|allows at most single|requires single}2 " + "argument %3, but %plural{0:no|:%4}4 arguments were provided">; + def note_ovl_candidate_deleted : Note< "candidate %select{function|function|constructor|" "function |function |constructor |" @@ -2035,7 +2204,8 @@ def note_ovl_candidate_bad_conv_incomplete : Note<"candidate " "function (the implicit copy assignment operator)|" "function (the implicit move assignment operator)|" "constructor (inherited)}0%1 " - "not viable: cannot convert argument of incomplete type %2 to %3">; + "not viable: cannot convert argument of incomplete type " + "%diff{$ to $|to parameter type}2,3">; def note_ovl_candidate_bad_list_argument : Note<"candidate " "%select{function|function|constructor|" "function |function |constructor |" @@ -2065,12 +2235,13 @@ def note_ovl_candidate_bad_conv : Note<"candidate " "function (the implicit copy assignment operator)|" "function (the implicit move assignment operator)|" "constructor (inherited)}0%1" - " not viable: no known conversion from %2 to %3 for " - "%select{%ordinal5 argument|object argument}4; " - "%select{|dereference the argument with *|" - "take the address of the argument with &|" - "remove *|" - "remove &}6">; + " not viable: no known conversion " + "%diff{from $ to $|from argument type to parameter type}2,3 for " + "%select{%ordinal5 argument|object argument}4" + "%select{|; dereference the argument with *|" + "; take the address of the argument with &|" + "; remove *|" + "; remove &}6">; def note_ovl_candidate_bad_arc_conv : Note<"candidate " "%select{function|function|constructor|" "function |function |constructor |" @@ -2080,8 +2251,20 @@ def note_ovl_candidate_bad_arc_conv : Note<"candidate " "function (the implicit copy assignment operator)|" "function (the implicit move assignment operator)|" "constructor (inherited)}0%1" - " not viable: cannot implicitly convert argument of type %2 to %3 for " + " not viable: cannot implicitly convert argument " + "%diff{of type $ to $|type to parameter type}2,3 for " "%select{%ordinal5 argument|object argument}4 under ARC">; +def note_ovl_candidate_bad_lvalue : Note<"candidate " + "%select{function|function|constructor|" + "function |function |constructor |" + "constructor (the implicit default constructor)|" + "constructor (the implicit copy constructor)|" + "constructor (the implicit move constructor)|" + "function (the implicit copy assignment operator)|" + "function (the implicit move assignment operator)|" + "constructor (inherited)}0%1" + " not viable: expects an l-value for " + "%select{%ordinal3 argument|object argument}2">; def note_ovl_candidate_bad_addrspace : Note<"candidate " "%select{function|function|constructor|" "function |function |constructor |" @@ -2163,7 +2346,7 @@ def note_ovl_candidate_bad_target : Note< " %select{__device__|__global__|__host__|__host__ __device__}2 function">; def note_ambiguous_type_conversion: Note< - "because of ambiguity in conversion of %0 to %1">; + "because of ambiguity in conversion %diff{of $ to $|between types}0,1">; def note_ovl_builtin_binary_candidate : Note< "built-in candidate %0">; def note_ovl_builtin_unary_candidate : Note< @@ -2317,6 +2500,8 @@ def note_template_decl_here : Note<"template is declared here">; def note_member_of_template_here : Note<"member is declared here">; def err_template_arg_must_be_type : Error< "template argument for template type parameter must be a type">; +def err_template_arg_must_be_type_suggest : Error< + "template argument for template type parameter must be a type; did you forget 'typename'?">; def err_template_arg_must_be_expr : Error< "template argument for non-type template parameter must be an expression">; def err_template_arg_nontype_ambig : Error< @@ -2353,6 +2538,9 @@ def err_template_arg_not_ice : Error< "expression">; def err_template_arg_not_address_constant : Error< "non-type template argument of type %0 is not a constant expression">; +def warn_cxx98_compat_template_arg_null : Warning< + "use of null pointer as non-type template argument is incompatible with " + "C++98">, InGroup<CXX98Compat>, DefaultIgnore; def err_template_arg_untyped_null_constant : Error< "null non-type template argument must be cast to template parameter type %0">; def err_template_arg_wrongtype_null_constant : Error< @@ -2360,7 +2548,7 @@ def err_template_arg_wrongtype_null_constant : Error< "of type %1">; def err_deduced_non_type_template_arg_type_mismatch : Error< "deduced non-type template argument does not have the same type as the " - "its corresponding template parameter (%0 vs %1)">; + "its corresponding template parameter%diff{ ($ vs $)|}0,1">; def err_template_arg_not_convertible : Error< "non-type template argument of type %0 cannot be converted to a value " "of type %1">; @@ -2371,11 +2559,13 @@ def warn_template_arg_too_large : Warning< "non-type template argument value '%0' truncated to '%1' for " "template parameter of type %2">, InGroup<Conversion>, DefaultIgnore; def err_template_arg_no_ref_bind : Error< - "non-type template parameter of reference type %0 cannot bind to template " - "argument of type %1">; + "non-type template parameter of reference type " + "%diff{$ cannot bind to template argument of type $" + "|cannot bind to template of incompatible argument type}0,1">; def err_template_arg_ref_bind_ignores_quals : Error< - "reference binding of non-type template parameter of type %0 to template " - "argument of type %1 ignores qualifiers">; + "reference binding of non-type template parameter " + "%diff{of type $ to template argument of type $|to template argument}0,1 " + "ignores qualifiers">; def err_template_arg_not_decl_ref : Error< "non-type template argument does not refer to any declaration">; def err_template_arg_not_object_or_func_form : Error< @@ -2701,6 +2891,9 @@ def note_explicit_instantiation_definition_here : Note< // C++ typename-specifiers def err_typename_nested_not_found : Error<"no type named %0 in %1">; +def err_typename_nested_not_found_enable_if : Error< + "no type named 'type' in %0; 'enable_if' cannot be used to disable " + "this declaration">; def err_typename_nested_not_type : Error< "typename specifier refers to non-type member %0 in %1">; def note_typename_refers_here : Note< @@ -2768,28 +2961,28 @@ def err_unexpanded_parameter_pack_0 : Error< "size|static assertion|fixed underlying type|enumerator value|" "using declaration|friend declaration|qualifier|initializer|default argument|" "non-type template parameter type|exception type|partial specialization|" - "__if_exists name|__if_not_exists name}0 " + "__if_exists name|__if_not_exists name|lambda|block}0 " "contains an unexpanded parameter pack">; def err_unexpanded_parameter_pack_1 : Error< "%select{expression|base type|declaration type|data member type|bit-field " "size|static assertion|fixed underlying type|enumerator value|" "using declaration|friend declaration|qualifier|initializer|default argument|" "non-type template parameter type|exception type|partial specialization|" - "__if_exists name|__if_not_exists name}0 " + "__if_exists name|__if_not_exists name|lambda|block}0 " "contains unexpanded parameter pack %1">; def err_unexpanded_parameter_pack_2 : Error< "%select{expression|base type|declaration type|data member type|bit-field " "size|static assertion|fixed underlying type|enumerator value|" "using declaration|friend declaration|qualifier|initializer|default argument|" "non-type template parameter type|exception type|partial specialization|" - "__if_exists name|__if_not_exists name}0 " + "__if_exists name|__if_not_exists name|lambda|block}0 " "contains unexpanded parameter packs %1 and %2">; def err_unexpanded_parameter_pack_3_or_more : Error< "%select{expression|base type|declaration type|data member type|bit-field " "size|static assertion|fixed underlying type|enumerator value|" "using declaration|friend declaration|qualifier|initializer|default argument|" "non-type template parameter type|exception type|partial specialization|" - "__if_exists name|__if_not_exists name}0 " + "__if_exists name|__if_not_exists name|lambda|block}0 " "contains unexpanded parameter packs %1, %2, ...">; def err_pack_expansion_without_parameter_packs : Error< @@ -2878,8 +3071,8 @@ def note_deleted_dtor_no_operator_delete : Note< def note_deleted_special_member_class_subobject : Note< "%select{default constructor|copy constructor|move constructor|" "copy assignment operator|move assignment operator|destructor}0 of " - "%select{||||union }4%1 is implicitly deleted because " - "%select{base class %3|field %3}2 has " + "%1 is implicitly deleted because " + "%select{base class %3|%select{||||variant }4field %3}2 has " "%select{no|a deleted|multiple|an inaccessible|a non-trivial}4 " "%select{%select{default constructor|copy constructor|move constructor|copy " "assignment operator|move assignment operator|destructor}0|destructor}5" @@ -2898,8 +3091,8 @@ def note_deleted_copy_user_declared_move : Note< "copy %select{constructor|assignment operator}0 is implicitly deleted because" " %1 has a user-declared move %select{constructor|assignment operator}2">; def note_deleted_assign_field : Note< - "%select{copy|move}0 assignment operator of %0 is implicitly deleted " - "because field %1 is of %select{reference|const-qualified}3 type %2">; + "%select{copy|move}0 assignment operator of %1 is implicitly deleted " + "because field %2 is of %select{reference|const-qualified}4 type %3">; // This should eventually be an error. def warn_undefined_internal : Warning< @@ -2907,6 +3100,17 @@ def warn_undefined_internal : Warning< DiagGroup<"undefined-internal">; def note_used_here : Note<"used here">; +def warn_internal_in_extern_inline : ExtWarn< + "static %select{function|variable}0 %1 is used in an inline function with " + "external linkage">, InGroup<DiagGroup<"static-in-inline"> >; +def ext_internal_in_extern_inline : Extension< + "static %select{function|variable}0 %1 is used in an inline function with " + "external linkage">, InGroup<DiagGroup<"static-in-inline"> >; +def note_convert_inline_to_static : Note< + "use 'static' to give inline function %0 internal linkage">; +def note_internal_decl_declared_here : Note< + "%0 declared here">; + def warn_redefinition_of_typedef : ExtWarn< "redefinition of typedef %0 is a C11 feature">, InGroup<DiagGroup<"typedef-redefinition"> >; @@ -2939,7 +3143,8 @@ def warn_forward_class_redefinition : Warning< "redefinition of forward class %0 of a typedef name of an object type is ignored">, InGroup<DiagGroup<"objc-forward-class-redefinition">>; def err_redefinition_different_typedef : Error< - "%select{typedef|type alias|type alias template}0 redefinition with different types (%1 vs %2)">; + "%select{typedef|type alias|type alias template}0 " + "redefinition with different types%diff{ ($ vs $)|}1,2">; def err_tag_reference_non_tag : Error< "elaborated type refers to %select{a non-tag type|a typedef|a type alias|a template|a type alias template}0">; def err_tag_reference_conflict : Error< @@ -2977,6 +3182,9 @@ def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">; def err_duplicate_member : Error<"duplicate member %0">; def err_misplaced_ivar : Error< "ivars may not be placed in %select{categories|class extension}0">; +def warn_ivars_in_interface : Warning< + "declaration of ivars in the interface is deprecated">, + InGroup<DiagGroup<"objc-interface-ivars">>, DefaultIgnore; def ext_enum_value_not_int : Extension< "ISO C restricts enumerator values to range of 'int' (%0 is too " "%select{small|large}1)">; @@ -3041,7 +3249,8 @@ def err_local_cant_init : Error< "'__local' variable cannot have an initializer">; def err_block_extern_cant_init : Error< "'extern' variable cannot have an initializer">; -def warn_extern_init : Warning<"'extern' variable has an initializer">; +def warn_extern_init : Warning<"'extern' variable has an initializer">, + InGroup<DiagGroup<"extern-initializer">>; def err_variable_object_no_init : Error< "variable-sized object may not be initialized">; def err_excess_initializers : Error< @@ -3070,6 +3279,15 @@ def err_empty_scalar_initializer : Error<"scalar initializer cannot be empty">; def warn_cxx98_compat_empty_scalar_initializer : Warning< "scalar initialized from empty initializer list is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; +def warn_cxx98_compat_reference_list_init : Warning< + "reference initialized from initializer list is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; +def warn_cxx98_compat_initializer_list_init : Warning< + "initialization of initializer_list object is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; +def warn_cxx98_compat_ctor_list_init : Warning< + "constructor call from initializer list is incompatible with C++98">, + InGroup<CXX98Compat>, DefaultIgnore; def err_illegal_initializer : Error< "illegal initializer (only variables can be initialized)">; def err_illegal_initializer_type : Error<"illegal initializer type %0">; @@ -3190,7 +3408,7 @@ def note_protected_by___block : Note< def note_protected_by_objc_ownership : Note< "jump bypasses initialization of retaining variable">; def note_enters_block_captures_cxx_obj : Note< - "jump enters lifetime of block which captures a destructible c++ object">; + "jump enters lifetime of block which captures a destructible C++ object">; def note_enters_block_captures_strong : Note< "jump enters lifetime of block which strongly captures a variable">; def note_enters_block_captures_weak : Note< @@ -3219,7 +3437,7 @@ def note_exits_objc_autoreleasepool : Note< def note_exits_objc_ownership : Note< "jump exits scope of retaining variable">; def note_exits_block_captures_cxx_obj : Note< - "jump exits lifetime of block which captures a destructible c++ object">; + "jump exits lifetime of block which captures a destructible C++ object">; def note_exits_block_captures_strong : Note< "jump exits lifetime of block which strongly captures a variable">; def note_exits_block_captures_weak : Note< @@ -3329,7 +3547,8 @@ def warn_arc_non_pod_class_with_object_member : Warning< "to make it ABI-compatible">, InGroup<AutomaticReferenceCountingABI>, DefaultIgnore; def warn_arc_retained_assign : Warning< - "assigning retained object to %select{weak|unsafe_unretained}0 variable" + "assigning retained object to %select{weak|unsafe_unretained}0 " + "%select{property|variable}1" "; object will be released after assignment">, InGroup<ARCUnsafeRetainedAssign>; def warn_arc_retained_property_assign : Warning< @@ -3356,8 +3575,7 @@ def err_arc_autoreleasing_capture : Error< def err_arc_thread_ownership : Error< "thread-local variable has non-trivial ownership: type is %0">; def err_arc_indirect_no_ownership : Error< - "%select{pointer|reference}1 to non-const type %0 with no explicit ownership">, - InGroup<AutomaticReferenceCounting>; + "%select{pointer|reference}1 to non-const type %0 with no explicit ownership">; def err_arc_array_param_no_ownership : Error< "must explicitly describe intended ownership of an object array parameter">; def err_arc_pseudo_dtor_inconstant_quals : Error< @@ -3378,7 +3596,7 @@ def err_arc_receiver_forward_instance : Error< "receiver type %0 for instance message is a forward declaration">; def warn_receiver_forward_instance : Warning< "receiver type %0 for instance message is a forward declaration">, - InGroup<DiagGroup<"receiver-forward-class">>, DefaultIgnore; + InGroup<ForwardClassReceiver>, DefaultIgnore; def err_arc_collection_forward : Error< "collection expression type %0 is a forward declaration">; def err_arc_multiple_method_decl : Error< @@ -3454,7 +3672,7 @@ def err_illegal_decl_array_of_functions : Error< def err_illegal_decl_array_incomplete_type : Error< "array has incomplete element type %0">; def err_illegal_message_expr_incomplete_type : Error< - "objective-c message has incomplete result type %0">; + "Objective-C message has incomplete result type %0">; def err_illegal_decl_array_of_references : Error< "'%0' declared as array of references of type %1">; def err_decl_negative_array_size : Error< @@ -3507,14 +3725,18 @@ def ext_offsetof_extended_field_designator : Extension< InGroup<DiagGroup<"extended-offsetof">>; def warn_offsetof_non_pod_type : ExtWarn<"offset of on non-POD type %0">, InGroup<InvalidOffsetof>; +def warn_offsetof_non_standardlayout_type : ExtWarn< + "offset of on non-standard-layout type %0">, InGroup<InvalidOffsetof>; def err_offsetof_bitfield : Error<"cannot compute offset of bit-field %0">; def warn_floatingpoint_eq : Warning< "comparing floating point with == or != is unsafe">, InGroup<DiagGroup<"float-equal">>, DefaultIgnore; -def warn_division_by_zero : Warning<"division by zero is undefined">; -def warn_remainder_by_zero : Warning<"remainder by zero is undefined">; +def warn_division_by_zero : Warning<"division by zero is undefined">, + InGroup<DivZero>; +def warn_remainder_by_zero : Warning<"remainder by zero is undefined">, + InGroup<DivZero>; def warn_shift_negative : Warning<"shift count is negative">, InGroup<DiagGroup<"shift-count-negative">>; def warn_shift_gt_typewidth : Warning<"shift count >= width of type">, @@ -3576,17 +3798,17 @@ def warn_sizeof_array_param : Warning< InGroup<SizeofArrayArgument>; def err_sizeof_nonfragile_interface : Error< - "invalid application of '%select{alignof|sizeof}1' to interface %0 in " - "non-fragile ABI">; + "application of '%select{alignof|sizeof}1' to interface %0 is " + "not supported on this architecture and platform">; def err_atdef_nonfragile_interface : Error< - "invalid application of @defs in non-fragile ABI">; + "use of @defs is not supported on this architecture and platform">; def err_subscript_nonfragile_interface : Error< - "subscript requires size of interface %0, which is not constant in " - "non-fragile ABI">; + "subscript requires size of interface %0, which is not constant for " + "this architecture and platform">; def err_arithmetic_nonfragile_interface : Error< - "arithmetic on pointer to interface %0, which is not a constant size in " - "non-fragile ABI">; + "arithmetic on pointer to interface %0, which is not a constant size for " + "this architecture and platform">; def ext_subscript_non_lvalue : Extension< @@ -3624,6 +3846,8 @@ def warn_subscript_is_char : Warning<"array subscript is of type 'char'">, def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">; def err_no_member : Error<"no member named %0 in %1">; +def err_no_member_overloaded_arrow : Error< + "no member named %0 in %1; did you mean to use '->' instead of '.'?">; def err_member_not_yet_instantiated : Error< "no member %0 in %1; it has not yet been instantiated">; @@ -3636,11 +3860,15 @@ def note_enum_specialized_here : Note< "enum %0 was explicitly specialized here">; def err_member_redeclared : Error<"class member cannot be redeclared">; +def err_member_redeclared_in_instantiation : Error< + "multiple overloads of %0 instantiate to the same signature %1">; def err_member_name_of_class : Error<"member %0 has the same name as its class">; def err_member_def_undefined_record : Error< "out-of-line definition of %0 from class %1 without definition">; def err_member_def_does_not_match : Error< "out-of-line definition of %0 does not match any declaration in %1">; +def err_friend_decl_does_not_match : Error< + "friend declaration of %0 does not match any declaration in %1">; def err_member_def_does_not_match_suggest : Error< "out-of-line definition of %0 does not match any declaration in %1; " "did you mean %2?">; @@ -3664,8 +3892,8 @@ def note_member_def_close_const_match : Note< "member declaration does not match because " "it %select{is|is not}0 const qualified">; def note_member_def_close_param_match : Note< - "type of %ordinal0 parameter of member declaration does not match " - "definition (%1 vs %2)">; + "type of %ordinal0 parameter of member declaration does not match definition" + "%diff{ ($ vs $)|}1,2">; def err_typecheck_ivar_variable_size : Error< "instance variables must have a constant size">; def err_ivar_reference_type : Error< @@ -3697,12 +3925,15 @@ def err_array_init_not_init_list : Error< "array initializer must be an initializer " "list%select{| or string literal}0">; def err_array_init_different_type : Error< - "cannot initialize array of type %0 with array of type %1">; + "cannot initialize array %diff{of type $ with array of type $|" + "with different type of array}0,1">; def err_array_init_non_constant_array : Error< - "cannot initialize array of type %0 with non-constant array of type %1">; + "cannot initialize array %diff{of type $ with non-constant array of type $|" + "with different type of array}0,1">; def ext_array_init_copy : Extension< - "initialization of an array of type %0 from a compound literal of type %1 is " - "a GNU extension">, InGroup<GNU>; + "initialization of an array " + "%diff{of type $ from a compound literal of type $|" + "from a compound literal}0,1 is a GNU extension">, InGroup<GNU>; // This is intentionally not disabled by -Wno-gnu. def ext_array_init_parens : ExtWarn< "parenthesized initialization of a member array is a GNU extension">, @@ -3745,7 +3976,7 @@ def note_indirection_through_null : Note< "consider using __builtin_trap() or qualifying pointer with 'volatile'">; def warn_pointer_indirection_from_incompatible_type : Warning< "dereference of type %1 that was reinterpret_cast from type %0 has undefined " - "behavior.">, + "behavior">, InGroup<DiagGroup<"undefined-reinterpret-cast">>, DefaultIgnore; def err_objc_object_assignment : Error< @@ -3753,7 +3984,8 @@ def err_objc_object_assignment : Error< def err_typecheck_invalid_operands : Error< "invalid operands to binary expression (%0 and %1)">; def err_typecheck_sub_ptr_compatible : Error< - "%0 and %1 are not pointers to compatible types">; + "%diff{$ and $ are not pointers to compatible types|" + "pointers to incompatible types}0,1">; def ext_typecheck_ordered_comparison_of_pointer_integer : ExtWarn< "ordered comparison between pointer and integer (%0 and %1)">; def ext_typecheck_ordered_comparison_of_pointer_and_zero : Extension< @@ -3769,13 +4001,14 @@ def ext_typecheck_comparison_of_pointer_integer : ExtWarn< def err_typecheck_comparison_of_pointer_integer : Error< "comparison between pointer and integer (%0 and %1)">; def ext_typecheck_comparison_of_distinct_pointers : ExtWarn< - "comparison of distinct pointer types (%0 and %1)">; + "comparison of distinct pointer types%diff{ ($ and $)|}0,1">; def ext_typecheck_cond_incompatible_operands : ExtWarn< "incompatible operand types (%0 and %1)">; def err_cond_voidptr_arc : Error < - "operands to conditional of types %0 and %1 are incompatible in ARC mode">; + "operands to conditional of types%diff{ $ and $|}0,1 are incompatible " + "in ARC mode">; def err_typecheck_comparison_of_distinct_pointers : Error< - "comparison of distinct pointer types (%0 and %1)">; + "comparison of distinct pointer types%diff{ ($ and $)|}0,1">; def ext_typecheck_comparison_of_distinct_pointers_nonstandard : ExtWarn< "comparison of distinct pointer types (%0 and %1) uses non-standard " "composite pointer type %2">; @@ -3792,7 +4025,8 @@ def warn_runsigned_always_true_comparison : Warning< "comparison of %0 unsigned%select{| enum}2 expression is always %1">, InGroup<TautologicalCompare>; def warn_comparison_of_mixed_enum_types : Warning< - "comparison of two values with different enumeration types (%0 and %1)">, + "comparison of two values with different enumeration types" + "%diff{ ($ and $)|}0,1">, InGroup<DiagGroup<"enum-compare">>; def warn_null_in_arithmetic_operation : Warning< "use of NULL in arithmetic operation">, @@ -3865,8 +4099,8 @@ def err_objc_subscript_key_type : Error< def err_objc_subscript_dic_object_type : Error< "method object parameter type %0 is not object type">; def err_objc_subscript_object_type : Error< - "cannot assign to this %select{dictionary|array}1 because assigning method's 2nd parameter" - " of type %0 is not an objective-C pointer type">; + "cannot assign to this %select{dictionary|array}1 because assigning method's " + "2nd parameter of type %0 is not an Objective-C pointer type">; def err_objc_subscript_base_type : Error< "%select{dictionary|array}1 subscript base type %0 is not an Objective-C object">; def err_objc_multiple_subscript_type_conversion : Error< @@ -3874,17 +4108,17 @@ def err_objc_multiple_subscript_type_conversion : Error< "multiple type conversion functions">; def err_objc_subscript_type_conversion : Error< "indexing expression is invalid because subscript type %0 is not an integral" - " or objective-C pointer type">; + " or Objective-C pointer type">; def err_objc_subscript_pointer : Error< "indexing expression is invalid because subscript type %0 is not an" - " objective-C pointer">; + " Objective-C pointer">; def err_objc_indexing_method_result_type : Error< "method for accessing %select{dictionary|array}1 element must have Objective-C" " object return type instead of %0">; def err_objc_index_incomplete_class_type : Error< - "objective-C index expression has incomplete class type %0">; + "Objective-C index expression has incomplete class type %0">; def err_illegal_container_subscripting_op : Error< - "illegal operation on objective-c container subscripting">; + "illegal operation on Objective-C container subscripting">; def err_property_not_found_forward_class : Error< "property %0 cannot be found in forward class object %1">; def err_property_not_as_forward_class : Error< @@ -3902,7 +4136,7 @@ def ext_gnu_ptr_func_arith : Extension< "type%select{|s}2 %1%select{| and %3}2 is a GNU extension">, InGroup<PointerArith>; def error_readonly_message_assignment : Error< - "assigning to 'readonly' return result of an objective-c message not allowed">; + "assigning to 'readonly' return result of an Objective-C message not allowed">; def ext_integer_increment_complex : Extension< "ISO C does not support '++'/'--' on complex integer type %0">; def ext_integer_complement_complex : Extension< @@ -3930,13 +4164,17 @@ def err_imaginary_not_supported : Error<"imaginary types are not supported">; // Obj-c expressions def warn_root_inst_method_not_found : Warning< - "instance method %0 is being used on 'Class' which is not in the root class">; + "instance method %0 is being used on 'Class' which is not in the root class">, + InGroup<MethodAccess>; def warn_class_method_not_found : Warning< - "class method %objcclass0 not found (return type defaults to 'id')">; + "class method %objcclass0 not found (return type defaults to 'id')">, + InGroup<MethodAccess>; def warn_instance_method_on_class_found : Warning< - "instance method %0 found instead of class method %1">; + "instance method %0 found instead of class method %1">, + InGroup<MethodAccess>; def warn_inst_method_not_found : Warning< - "instance method %objcinstance0 not found (return type defaults to 'id')">; + "instance method %objcinstance0 not found (return type defaults to 'id')">, + InGroup<MethodAccess>; def error_no_super_class_message : Error< "no @interface declaration found in class messaging of %0">; def error_root_class_cannot_use_super : Error< @@ -3951,7 +4189,7 @@ def err_missing_open_square_message_send : Error< "missing '[' at start of message send expression">; def warn_bad_receiver_type : Warning< "receiver type %0 is not 'id' or interface pointer, consider " - "casting it to 'id'">; + "casting it to 'id'">,InGroup<ObjCReceiver>; def err_bad_receiver_type : Error<"bad receiver type %0">; def err_unknown_receiver_suggest : Error< "unknown receiver %0; did you mean %1?">; @@ -3978,7 +4216,7 @@ def warn_objc_pointer_cxx_catch_fragile : Warning< "can not catch an exception thrown with @throw in C++ in the non-unified " "exception model">, InGroup<ObjCNonUnifiedException>; def err_objc_object_catch : Error< - "can't catch an Objective C object by value">; + "can't catch an Objective-C object by value">; def err_incomplete_type_objc_at_encode : Error< "'@encode' of incomplete type %0">; @@ -4050,7 +4288,7 @@ def err_bad_cxx_cast_member_pointer_size : Error< def err_bad_reinterpret_cast_reference : Error< "reinterpret_cast of a %0 to %1 needs its address which is not allowed">; def warn_undefined_reinterpret_cast : Warning< - "reinterpret_cast from %0 to %1 has undefined behavior.">, + "reinterpret_cast from %0 to %1 has undefined behavior">, InGroup<DiagGroup<"undefined-reinterpret-cast">>, DefaultIgnore; // These messages don't adhere to the pattern. @@ -4191,11 +4429,12 @@ def err_conditional_void_nonvoid : Error< "%select{left|right}1 operand to ? is void, but %select{right|left}1 operand " "is of type %0">; def err_conditional_ambiguous : Error< - "conditional expression is ambiguous; %0 can be converted to %1 " - "and vice versa">; + "conditional expression is ambiguous; " + "%diff{$ can be converted to $ and vice versa|" + "types can be convert to each other}0,1">; def err_conditional_ambiguous_ovl : Error< - "conditional expression is ambiguous; %0 and %1 can be converted to several " - "common types">; + "conditional expression is ambiguous; %diff{$ and $|types}0,1 " + "can be converted to several common types">; def err_throw_incomplete : Error< "cannot throw object of incomplete type %0">; @@ -4233,10 +4472,6 @@ let CategoryName = "Lambda Issue" in { def note_lambda_decl : Note<"lambda expression begins here">; def err_lambda_unevaluated_operand : Error< "lambda expression in an unevaluated operand">; - def ext_lambda_implies_void_return : ExtWarn< - "C++11 requires lambda with omitted result type to consist of a single " - "return statement">, - InGroup<LambdaExtensions>; def err_lambda_return_init_list : Error< "cannot deduce lambda return type from initializer list">; def err_lambda_capture_default_arg : Error< @@ -4278,8 +4513,10 @@ def ext_pseudo_dtor_on_void : ExtWarn< "pseudo-destructors on type void are a Microsoft extension">, InGroup<Microsoft>; def err_pseudo_dtor_type_mismatch : Error< - "the type of object expression (%0) does not match the type being destroyed " - "(%1) in pseudo-destructor expression">; + "the type of object expression " + "%diff{($) does not match the type being destroyed ($)|" + "does not match the type being destroyed}0,1 " + "in pseudo-destructor expression">; def err_pseudo_dtor_call_with_args : Error< "call to pseudo-destructor cannot have any arguments">; def err_dtor_expr_without_call : Error< @@ -4296,11 +4533,12 @@ def err_type_defined_in_condition : Error< def err_typecheck_bool_condition : Error< "value of type %0 is not contextually convertible to 'bool'">; def err_typecheck_ambiguous_condition : Error< - "conversion from %0 to %1 is ambiguous">; + "conversion %diff{from $ to $|between types}0,1 is ambiguous">; def err_typecheck_nonviable_condition : Error< - "no viable conversion from %0 to %1">; + "no viable conversion%diff{ from $ to $|}0,1">; def err_typecheck_deleted_function : Error< - "conversion function from %0 to %1 invokes a deleted function">; + "conversion function %diff{from $ to $|between types}0,1 " + "invokes a deleted function">; def err_expected_class_or_namespace : Error<"expected a class or namespace">; def err_expected_class : Error<"%0 is not a class%select{ or namespace|, " @@ -4314,6 +4552,9 @@ def err_invalid_declarator_in_function : Error< def err_not_tag_in_scope : Error< "no %select{struct|union|class|enum}0 named %1 in %2">; +def err_no_typeid_with_fno_rtti : Error< + "cannot use typeid with -fno-rtti">; + def err_cannot_form_pointer_to_member_of_reference_type : Error< "cannot form a pointer-to-member to member %0 of reference type %1">; def err_incomplete_object_call : Error< @@ -4344,42 +4585,66 @@ def note_equality_comparison_silence : Note< // In most of these diagnostics the %2 is a value from the // Sema::AssignmentAction enumeration def err_typecheck_convert_incompatible : Error< - "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" - " %0 " - "%select{from incompatible type|to parameter of incompatible type|" - "from a function with incompatible result type|to incompatible type|" - "with an expression of incompatible type|to parameter of incompatible type|" - "to incompatible type}2 %1" + "%select{%diff{assigning to $ from incompatible type $|" + "assigning to type from incompatible type}0,1" + "|%diff{passing $ to parameter of incompatible type $|" + "passing type to parameter of incompatible type}0,1" + "|%diff{returning $ from a function with incompatible result type $|" + "returning type from a function with incompatible result type}0,1" + "|%diff{converting $ to incompatible type $|" + "converting type to incompatible type}0,1" + "|%diff{initializing $ with an expression of incompatible type $|" + "initializing type with an expression of incompatible type}0,1" + "|%diff{sending $ to parameter of incompatible type $|" + "sending type to parameter of incompatible type}0,1" + "|%diff{casting $ to incompatible type $|" + "casting type to incompatible type}0,1}2" "%select{|; dereference with *|" "; take the address with &|" "; remove *|" "; remove &}3" - "%select{|: different classes (%5 vs %6)" + "%select{|: different classes%diff{ ($ vs $)|}5,6" "|: different number of parameters (%5 vs %6)" - "|: type mismatch at %ordinal5 parameter (%6 vs %7)" - "|: different return type (%5 vs %6)" + "|: type mismatch at %ordinal5 parameter%diff{ ($ vs $)|}6,7" + "|: different return type%diff{ ($ vs $)|}5,6" "|: different qualifiers (" "%select{none|const|restrict|const and restrict|volatile|const and volatile|" "volatile and restrict|const, volatile, and restrict}5 vs " "%select{none|const|restrict|const and restrict|volatile|const and volatile|" "volatile and restrict|const, volatile, and restrict}6)}4">; def err_typecheck_missing_return_type_incompatible : Error< - "return type %0 must match previous return type %1 when %select{block " + "%diff{return type $ must match previous return type $|" + "return type must match previous return type}0,1 when %select{block " "literal|lambda expression}2 has unspecified explicit return type">; def warn_incompatible_qualified_id : Warning< - "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" - " %0 " - "%select{from incompatible type|to parameter of incompatible type|" - "from a function with incompatible result type|to incompatible type|" - "with an expression of incompatible type|to parameter of incompatible type|" - "to incompatible type}2 %1">; + "%select{%diff{assigning to $ from incompatible type $|" + "assigning to type from incompatible type}0,1" + "|%diff{passing $ to parameter of incompatible type $|" + "passing type to parameter of incompatible type}0,1" + "|%diff{returning $ from a function with incompatible result type $|" + "returning type from a function with incompatible result type}0,1" + "|%diff{converting $ to incompatible type $|" + "converting type to incompatible type}0,1" + "|%diff{initializing $ with an expression of incompatible type $|" + "initializing type with an expression of incompatible type}0,1" + "|%diff{sending $ to parameter of incompatible type $|" + "sending type to parameter of incompatible type}0,1" + "|%diff{casting $ to incompatible type $|" + "casting type to incompatible type}0,1}2">; def ext_typecheck_convert_pointer_int : ExtWarn< "incompatible pointer to integer conversion " - "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" - " %0 " - "%select{from|to parameter of type|from a function with result type|to type|" - "with an expression of type|to parameter of type|to type}2 %1" + "%select{%diff{assigning to $ from $|assigning to different types}0,1" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2" "%select{|; dereference with *|" "; take the address with &|" "; remove *|" @@ -4387,92 +4652,163 @@ def ext_typecheck_convert_pointer_int : ExtWarn< InGroup<IntConversion>; def ext_typecheck_convert_int_pointer : ExtWarn< "incompatible integer to pointer conversion " - "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" - " %0 " - "%select{from|to parameter of type|from a function with result type|to type|" - "with an expression of type|to parameter of type|to type}2 %1" + "%select{%diff{assigning to $ from $|assigning to different types}0,1" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2" "%select{|; dereference with *|" "; take the address with &|" "; remove *|" "; remove &}3">, InGroup<IntConversion>; def ext_typecheck_convert_pointer_void_func : Extension< - "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" - " %0 " - "%select{from|to parameter of type|from a function with result type|to type|" - "with an expression of type|to parameter of type|to type}2 %1 " - "converts between void pointer and function pointer">; + "%select{%diff{assigning to $ from $|assigning to different types}0,1" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2" + " converts between void pointer and function pointer">; def ext_typecheck_convert_incompatible_pointer_sign : ExtWarn< - "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" - " %0 " - "%select{from|to parameter of type|from a function with result type|to type|" - "with an expression of type|to parameter of type|to type}2 %1 " - "converts between pointers to integer types with different sign">, + "%select{%diff{assigning to $ from $|assigning to different types}0,1" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2" + " converts between pointers to integer types with different sign">, InGroup<DiagGroup<"pointer-sign">>; def ext_typecheck_convert_incompatible_pointer : ExtWarn< "incompatible pointer types " - "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" - " %0 " - "%select{from|to parameter of type|from a function with result type|to type|" - "with an expression of type|to parameter of type|to type}2 %1" + "%select{%diff{assigning to $ from $|assigning to different types}0,1" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2" "%select{|; dereference with *|" "; take the address with &|" "; remove *|" "; remove &}3">, InGroup<IncompatiblePointerTypes>; def ext_typecheck_convert_discards_qualifiers : ExtWarn< - "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" - " %0 " - "%select{from|to parameter of type|from a function with result type|to type|" - "with an expression of type|to parameter of type|to type}2 %1 discards " - "qualifiers">, + "%select{%diff{assigning to $ from $|assigning to different types}0,1" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2" + " discards qualifiers">, InGroup<IncompatiblePointerTypes>; def ext_nested_pointer_qualifier_mismatch : ExtWarn< - "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" - " %0 " - "%select{from|to parameter of type|from a function with result type|to type|" - "with an expression of type|to parameter of type|to type}2 %1 discards " - "qualifiers in nested pointer types">, + "%select{%diff{assigning to $ from $|assigning to different types}0,1" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2" + " discards qualifiers in nested pointer types">, InGroup<IncompatiblePointerTypes>; def warn_incompatible_vectors : Warning< "incompatible vector types " - "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" - " %0 " - "%select{from|to parameter of type|from a function with result type|to type|" - "with an expression of type|to parameter of type|to type}2 %1">, + "%select{%diff{assigning to $ from $|assigning to different types}0,1" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2">, InGroup<VectorConversion>, DefaultIgnore; def err_int_to_block_pointer : Error< "invalid block pointer conversion " - "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" - " %0 " - "%select{from|to parameter of type|from a function with result type|to type|" - "with an expression of type|to parameter of type|to type}2 %1">; + "%select{%diff{assigning to $ from $|assigning to different types}0,1" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2">; def err_typecheck_convert_incompatible_block_pointer : Error< "incompatible block pointer types " - "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" - " %0 " - "%select{from|to parameter of type|from a function with result type|to type|" - "with an expression of type|to parameter of type|to type}2 %1">; + "%select{%diff{assigning to $ from $|assigning to different types}0,1" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2">; def err_typecheck_incompatible_address_space : Error< - "%select{assigning %1 to %0" - "|passing %0 to parameter of type %1" - "|returning %0 from a function with result type %1" - "|converting %0 to type %1" - "|initializing %0 with an expression of type %1" - "|sending %0 to parameter of type %1" - "|casting %0 to type %1}2" + "%select{%diff{assigning $ to $|assigning to different types}1,0" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2" " changes address space of pointer">; def err_typecheck_incompatible_ownership : Error< - "%select{assigning %1 to %0" - "|passing %0 to parameter of type %1" - "|returning %0 from a function with result type %1" - "|converting %0 to type %1" - "|initializing %0 with an expression of type %1" - "|sending %0 to parameter of type %1" - "|casting %0 to type %1}2" + "%select{%diff{assigning $ to $|assigning to different types}1,0" + "|%diff{passing $ to parameter of type $|" + "passing to parameter of different type}0,1" + "|%diff{returning $ from a function with result type $|" + "returning from function with different return type}0,1" + "|%diff{converting $ to type $|converting between types}0,1" + "|%diff{initializing $ with an expression of type $|" + "initializing with expression of different type}0,1" + "|%diff{sending $ to parameter of type $|" + "sending to parameter of different type}0,1" + "|%diff{casting $ to type $|casting between types}0,1}2" " changes retain/release properties of pointer">; def err_typecheck_comparison_of_distinct_blocks : Error< - "comparison of distinct block types (%0 and %1)">; + "comparison of distinct block types%diff{ ($ and $)|}0,1">; def err_typecheck_array_not_modifiable_lvalue : Error< "array type %0 is not assignable">; @@ -4505,18 +4841,34 @@ def err_typecheck_call_too_few_args : Error< "too few %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " "expected %1, have %2">; +def err_typecheck_call_too_few_args_one : Error< + "too few %select{|||execution configuration }0arguments to " + "%select{function|block|method|kernel function}0 call, " + "single argument %1 was not specified">; def err_typecheck_call_too_few_args_at_least : Error< "too few %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " "expected at least %1, have %2">; +def err_typecheck_call_too_few_args_at_least_one : Error< + "too few %select{|||execution configuration }0arguments to " + "%select{function|block|method|kernel function}0 call, " + "at least argument %1 must be specified">; def err_typecheck_call_too_many_args : Error< "too many %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " "expected %1, have %2">; +def err_typecheck_call_too_many_args_one : Error< + "too many %select{|||execution configuration }0arguments to " + "%select{function|block|method|kernel function}0 call, " + "expected single argument %1, have %2 arguments">; def err_typecheck_call_too_many_args_at_most : Error< "too many %select{|||execution configuration }0arguments to " "%select{function|block|method|kernel function}0 call, " "expected at most %1, have %2">; +def err_typecheck_call_too_many_args_at_most_one : Error< + "too many %select{|||execution configuration }0arguments to " + "%select{function|block|method|kernel function}0 call, " + "expected at most single argument %1, have %2 arguments">; def note_callee_decl : Note< "%0 declared here">; def note_defined_here : Note<"%0 defined here">; @@ -4558,11 +4910,19 @@ def err_ref_bad_target : Error< "reference to %select{__device__|__global__|__host__|__host__ __device__}0 " "function %1 in %select{__device__|__global__|__host__|__host__ __device__}2 function">; +def warn_non_pod_vararg_with_format_string : Warning< + "cannot pass %select{non-POD|non-trivial}0 object of type %1 to variadic " + "%select{function|block|method|constructor}2; expected type from format " + "string was %3">, InGroup<DiagGroup<"non-pod-varargs">>, DefaultError; +// The arguments to this diagnostic should match the warning above. +def err_cannot_pass_objc_interface_to_vararg_format : Error< + "cannot pass object with interface type %1 by value to variadic " + "%select{function|block|method|constructor}2; expected type from format " + "string was %3">; def err_cannot_pass_objc_interface_to_vararg : Error< - "cannot pass object with interface type %0 by-value through variadic " - "%select{function|block|method}1">; - + "cannot pass object with interface type %0 by value through variadic " + "%select{function|block|method|constructor}1">; def warn_cannot_pass_non_pod_arg_to_vararg : Warning< "cannot pass object of %select{non-POD|non-trivial}0 type %1 through variadic" " %select{function|block|method|constructor}2; call will abort at runtime">, @@ -4573,7 +4933,8 @@ def warn_cxx98_compat_pass_non_pod_arg_to_vararg : Warning< InGroup<CXX98Compat>, DefaultIgnore; def err_typecheck_call_invalid_ordered_compare : Error< - "ordered compare requires two args of floating point type (%0 and %1)">; + "ordered compare requires two args of floating point type" + "%diff{ ($ and $)|}0,1">; def err_typecheck_call_invalid_unary_fp : Error< "floating point classification requires argument of floating point type " "(passed in %0)">; @@ -4597,17 +4958,18 @@ def err_cast_pointer_to_non_pointer_int : Error< def err_typecheck_expect_scalar_operand : Error< "operand of type %0 where arithmetic or pointer type is required">; def err_typecheck_cond_incompatible_operands : Error< - "incompatible operand types (%0 and %1)">; + "incompatible operand types%diff{ ($ and $)|}0,1">; def ext_typecheck_cond_incompatible_operands_nonstandard : ExtWarn< - "incompatible operand types (%0 and %1) use non-standard composite pointer " - "type %2">; + "incompatible operand types%diff{ ($ and $)|}0,1 use non-standard composite " + "pointer type %2">; def err_cast_selector_expr : Error< "cannot type cast @selector expression">; def warn_typecheck_cond_incompatible_pointers : ExtWarn< - "pointer type mismatch (%0 and %1)">, + "pointer type mismatch%diff{ ($ and $)|}0,1">, InGroup<DiagGroup<"pointer-type-mismatch">>; def warn_typecheck_cond_pointer_integer_mismatch : ExtWarn< - "pointer/integer type mismatch in conditional expression (%0 and %1)">, + "pointer/integer type mismatch in conditional expression" + "%diff{ ($ and $)|}0,1">, InGroup<DiagGroup<"conditional-type-mismatch">>; def err_typecheck_choose_expr_requires_constant : Error< "'__builtin_choose_expr' requires a constant expression">; @@ -4628,6 +4990,10 @@ def warn_unused_call : Warning< def warn_unused_result : Warning< "ignoring return value of function declared with warn_unused_result " "attribute">, InGroup<DiagGroup<"unused-result">>; +def warn_unused_volatile : Warning< + "expression result unused; assign into a variable to force a volatile load">, + InGroup<DiagGroup<"unused-volatile-lvalue">>; + def warn_unused_comparison : Warning< "%select{equality|inequality}0 comparison result unused">, InGroup<UnusedComparison>; @@ -4661,7 +5027,8 @@ let CategoryName = "Inline Assembly Issue" in { def err_asm_invalid_type_in_input : Error< "invalid type %0 in asm input for constraint '%1'">; def err_asm_tying_incompatible_types : Error< - "unsupported inline asm: input with type %0 matching output with type %1">; + "unsupported inline asm: input with type " + "%diff{$ matching output with type $|}0,1">; def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">; def warn_asm_label_on_auto_decl : Warning< "ignored asm label '%0' on automatic variable">; @@ -4673,12 +5040,16 @@ let CategoryName = "Inline Assembly Issue" in { "invalid use of a cast in a inline asm context requiring an l-value: " "accepted due to -fheinous-gnu-extensions, but clang may remove support " "for this in the future">; + + def warn_unsupported_msasm : ExtWarn< + "MS-style inline assembly is not supported">, InGroup<Microsoft>; } let CategoryName = "Semantic Issue" in { def err_invalid_conversion_between_vectors : Error< - "invalid conversion between vector type %0 and %1 of different size">; + "invalid conversion between vector type%diff{ $ and $|}0,1 of different " + "size">; def err_invalid_conversion_between_vector_and_integer : Error< "invalid conversion between vector type %0 and integer type %1 " "of different size">; @@ -4730,6 +5101,9 @@ def err_in_class_initializer_literal_type : Error< "'constexpr' specifier">; def err_in_class_initializer_non_constant : Error< "in-class initializer for static data member is not a constant expression">; +def err_in_class_initializer_references_def_ctor : Error< + "defaulted default constructor of %0 cannot be used by non-static data " + "member initializer which appears before end of class definition">; def ext_in_class_initializer_non_constant : Extension< "in-class initializer for static data member is not a constant expression; " @@ -4846,9 +5220,9 @@ def err_operator_new_delete_invalid_result_type : Error< def err_operator_new_delete_dependent_result_type : Error< "%0 cannot have a dependent return type; use %1 instead">; def err_operator_new_delete_too_few_parameters : Error< - "%0 must have at least one parameter.">; + "%0 must have at least one parameter">; def err_operator_new_delete_template_too_few_parameters : Error< - "%0 template must have at least two parameters.">; + "%0 template must have at least two parameters">; def err_operator_new_dependent_param_type : Error< "%0 cannot take a dependent type as first parameter; " @@ -4912,60 +5286,33 @@ def warn_cxx98_compat_explicit_conversion_functions : Warning< InGroup<CXX98Compat>, DefaultIgnore; // C++11 defaulted functions -def err_defaulted_default_ctor_params : Error< - "an explicitly-defaulted default constructor must have no parameters">; -def err_defaulted_copy_ctor_params : Error< - "an explicitly-defaulted copy constructor must have exactly one parameter">; -def err_defaulted_copy_ctor_volatile_param : Error< - "the parameter for an explicitly-defaulted copy constructor may not be " - "volatile">; -def err_defaulted_copy_ctor_const_param : Error< - "the parameter for this explicitly-defaulted copy constructor is const, but " - "a member or base requires it to be non-const">; -def err_defaulted_copy_assign_params : Error< - "an explicitly-defaulted copy assignment operator must have exactly one " - "parameter">; -def err_defaulted_copy_assign_return_type : Error< - "an explicitly-defaulted copy assignment operator must return an unqualified " - "lvalue reference to its class type">; +def err_defaulted_special_member_params : Error< + "an explicitly-defaulted %select{|copy |move }0constructor cannot " + "have default arguments">; +def err_defaulted_special_member_return_type : Error< + "explicitly-defaulted %select{copy|move}0 assignment operator must " + "return %1">; +def err_defaulted_special_member_quals : Error< + "an explicitly-defaulted %select{copy|move}0 assignment operator may not " + "have 'const', 'constexpr' or 'volatile' qualifiers">; +def err_defaulted_special_member_volatile_param : Error< + "the parameter for an explicitly-defaulted %select{<<ERROR>>|" + "copy constructor|move constructor|copy assignment operator|" + "move assignment operator|<<ERROR>>}0 may not be volatile">; +def err_defaulted_special_member_move_const_param : Error< + "the parameter for an explicitly-defaulted move " + "%select{constructor|assignment operator}0 may not be const">; +def err_defaulted_special_member_copy_const_param : Error< + "the parameter for this explicitly-defaulted copy " + "%select{constructor|assignment operator}0 is const, but a member or base " + "requires it to be non-const">; +def err_defaulted_special_member_copy_non_const_param : Error< + "explicitly-defaulted copy %select{constructor|assignment operator}0 with " + "a non-const parameter must be defaulted outside the class, unless a base or " + "member requires the parameter to be non-const">; def err_defaulted_copy_assign_not_ref : Error< "the parameter for an explicitly-defaulted copy assignment operator must be an " "lvalue reference type">; -def err_defaulted_copy_assign_volatile_param : Error< - "the parameter for an explicitly-defaulted copy assignment operator may not " - "be volatile">; -def err_defaulted_copy_assign_const_param : Error< - "the parameter for this explicitly-defaulted copy assignment operator is " - "const, but a member or base requires it to be non-const">; -def err_defaulted_copy_assign_quals : Error< - "an explicitly-defaulted copy assignment operator may not have 'const', " - "'constexpr' or 'volatile' qualifiers">; -def err_defaulted_move_ctor_params : Error< - "an explicitly-defaulted move constructor must have exactly one parameter">; -def err_defaulted_move_ctor_volatile_param : Error< - "the parameter for an explicitly-defaulted move constructor may not be " - "volatile">; -def err_defaulted_move_ctor_const_param : Error< - "the parameter for an explicitly-defaulted move constructor may not be " - "const">; -def err_defaulted_move_assign_params : Error< - "an explicitly-defaulted move assignment operator must have exactly one " - "parameter">; -def err_defaulted_move_assign_return_type : Error< - "an explicitly-defaulted move assignment operator must return an unqualified " - "lvalue reference to its class type">; -def err_defaulted_move_assign_not_ref : Error< - "the parameter for an explicitly-defaulted move assignment operator must be an " - "rvalue reference type">; -def err_defaulted_move_assign_volatile_param : Error< - "the parameter for an explicitly-defaulted move assignment operator may not " - "be volatile">; -def err_defaulted_move_assign_const_param : Error< - "the parameter for an explicitly-defaulted move assignment operator may not " - "be const">; -def err_defaulted_move_assign_quals : Error< - "an explicitly-defaulted move assignment operator may not have 'const', " - "'constexpr' or 'volatile' qualifiers">; def err_incorrect_defaulted_exception_spec : Error< "exception specification of explicitly defaulted %select{default constructor|" "copy constructor|move constructor|copy assignment operator|move assignment " @@ -4995,9 +5342,6 @@ def warn_array_index_exceeds_bounds : Warning< def note_array_index_out_of_bounds : Note< "array %0 declared here">; -def warn_printf_write_back : Warning< - "use of '%%n' in format string discouraged (potentially insecure)">, - InGroup<FormatSecurity>; def warn_printf_insufficient_data_args : Warning< "more '%%' conversions than data arguments">, InGroup<Format>; def warn_printf_data_arg_not_used : Warning< @@ -5066,7 +5410,8 @@ def warn_scanf_scanlist_incomplete : Warning< "no closing ']' for '%%[' in scanf format string">, InGroup<Format>; def note_format_string_defined : Note<"format string is defined here">; - +def note_printf_c_str: Note<"did you mean to call the %0 method?">; + def warn_null_arg : Warning< "null passed to a callee which requires a non-null argument">, InGroup<NonNull>; @@ -5118,6 +5463,10 @@ def warn_stringcompare : Warning< "unspecified (use strncmp instead)">, InGroup<DiagGroup<"string-compare">>; +def warn_identity_field_assign : Warning< + "assigning %select{field|instance variable}0 to itself">, + InGroup<SelfAssignmentField>; + // Generic selections. def err_assoc_type_incomplete : Error< "type %0 in generic association incomplete">; @@ -5141,14 +5490,15 @@ def err_blocks_disable : Error<"blocks support disabled - compile with -fblocks" def err_block_returning_array_function : Error< "block cannot return %select{array|function}0 type %1">; -// Builtin annotation string. -def err_builtin_annotation_not_string_constant : Error< - "__builtin_annotation requires a non wide string constant">; +// Builtin annotation +def err_builtin_annotation_first_arg : Error< + "first argument to __builtin_annotation must be an integer">; +def err_builtin_annotation_second_arg : Error< + "second argument to __builtin_annotation must be a non-wide string constant">; // CFString checking def err_cfstring_literal_not_string_constant : Error< - "CFString literal is not a string constant">, - InGroup<DiagGroup<"CFString-literal">>; + "CFString literal is not a string constant">; def warn_cfstring_truncated : Warning< "input conversion stopped due to an input byte that does not " "belong to the input codeset UTF-8">, @@ -5168,6 +5518,8 @@ def warn_case_value_overflow : Warning< "overflow converting case value to switch condition type (%0 to %1)">, InGroup<DiagGroup<"switch">>; def err_duplicate_case : Error<"duplicate case value '%0'">; +def err_duplicate_case_differing_expr : Error< + "duplicate case value: '%0' and '%1' both equal '%2'">; def warn_case_empty_range : Warning<"empty case range specified">; def warn_missing_case_for_condition : Warning<"no case matching constant switch condition '%0'">; @@ -5197,11 +5549,35 @@ def warn_missing_cases : Warning< "%0 enumeration values not handled in switch: %1, %2, %3...">, InGroup<Switch>; +def warn_unannotated_fallthrough : Warning< + "unannotated fall-through between switch labels">, + InGroup<ImplicitFallthrough>, DefaultIgnore; +def warn_unannotated_fallthrough_per_function : Warning< + "unannotated fall-through between switch labels in partly-annotated " + "function">, InGroup<ImplicitFallthroughPerFunction>, DefaultIgnore; +def note_insert_fallthrough_fixit : Note< + "insert '[[clang::fallthrough]];' to silence this warning">; +def note_insert_break_fixit : Note< + "insert 'break;' to avoid fall-through">; +def err_fallthrough_attr_wrong_target : Error< + "clang::fallthrough attribute is only allowed on empty statements">; +def note_fallthrough_insert_semi_fixit : Note<"did you forget ';'?">; +def err_fallthrough_attr_outside_switch : Error< + "fallthrough annotation is outside switch statement">; +def warn_fallthrough_attr_invalid_placement : Warning< + "fallthrough annotation does not directly precede switch label">, + InGroup<ImplicitFallthrough>; +def warn_fallthrough_attr_unreachable : Warning< + "fallthrough annotation in unreachable code">, + InGroup<ImplicitFallthrough>; + def warn_unreachable_default : Warning< "default label in switch which covers all enumeration values">, InGroup<CoveredSwitchDefault>, DefaultIgnore; def warn_not_in_enum : Warning<"case value not in enumerated type %0">, InGroup<Switch>; +def warn_not_in_enum_assignement : Warning<"integer constant not in range " + "of enumerated type %0">, InGroup<DiagGroup<"assign-enum">>, DefaultIgnore; def err_typecheck_statement_requires_scalar : Error< "statement requires expression of scalar type (%0 invalid)">; def err_typecheck_statement_requires_integer : Error< @@ -5229,8 +5605,7 @@ def warn_empty_while_body : Warning< def warn_empty_switch_body : Warning< "switch statement has empty body">, InGroup<EmptyBody>; def note_empty_body_on_separate_line : Note< - "put the semicolon on a separate line to silence this warning">, - InGroup<EmptyBody>; + "put the semicolon on a separate line to silence this warning">; def err_va_start_used_in_non_variadic_function : Error< "'va_start' used in function with fixed args">; @@ -5318,17 +5693,22 @@ def err_selector_element_not_lvalue : Error< def err_selector_element_type : Error< "selector element type %0 is not a valid object">; def err_collection_expr_type : Error< - "collection expression type %0 is not a valid object">; + "the type %0 is not a pointer to a fast-enumerable object">; def warn_collection_expr_type : Warning< "collection expression type %0 may not respond to %1">; def err_invalid_conversion_between_ext_vectors : Error< "invalid conversion between ext-vector type %0 and %1">; +def warn_duplicate_attribute : Warning< + "attribute %0 is already applied with different parameters">, + InGroup<IgnoredAttributes>; + // Type def ext_invalid_sign_spec : Extension<"'%0' cannot be signed or unsigned">; def warn_receiver_forward_class : Warning< - "receiver %0 is a forward class and corresponding @interface may not exist">; + "receiver %0 is a forward class and corresponding @interface may not exist">, + InGroup<ForwardClassReceiver>; def note_method_sent_forward_class : Note<"method %0 is used for the forward class">; def ext_missing_declspec : ExtWarn< "declaration specifier missing, defaulting to 'int'">; @@ -5376,13 +5756,19 @@ def warn_attribute_method_def : Warning< "attributes on method implementation and its declaration must match">, InGroup<DiagGroup<"mismatched-method-attributes">>; def ext_typecheck_base_super : Warning< - "method parameter type %0 does not match " - "super class method parameter type %1">, InGroup<SuperSubClassMismatch>, DefaultIgnore; + "method parameter type " + "%diff{$ does not match super class method parameter type $|" + "does not match super class method parameter type}0,1">, + InGroup<SuperSubClassMismatch>, DefaultIgnore; def warn_missing_method_return_type : Warning< "method has no return type specified; defaults to 'id'">, InGroup<MissingMethodReturnType>, DefaultIgnore; +def warn_direct_ivar_access : Warning<"instance variable %0 is being " + "directly accessed">, InGroup<DiagGroup<"direct-ivar-access">>, DefaultIgnore; // Spell-checking diagnostics +def err_unknown_type_or_class_name_suggest : Error< + "unknown %select{type|class}2 name %0; did you mean %1?">; def err_unknown_typename_suggest : Error< "unknown type name %0; did you mean %1?">; def err_unknown_nested_typename_suggest : Error< @@ -5457,14 +5843,19 @@ def err_filter_expression_integral : Error< // OpenCL warnings and errors. def err_invalid_astype_of_different_size : Error< "invalid reinterpretation: sizes of %0 and %1 must match">; +def err_static_kernel : Error< + "kernel functions cannot be declared static">; +def err_static_function_scope : Error< + "variables in function scope cannot be declared static">; } // end of sema category let CategoryName = "Related Result Type Issue" in { // Objective-C related result type compatibility def warn_related_result_type_compatibility_class : Warning< - "method is expected to return an instance of its class type %0, but " - "is declared to return %1">; + "method is expected to return an instance of its class type " + "%diff{$, but is declared to return $|" + ", but is declared to return different type}0,1">; def warn_related_result_type_compatibility_protocol : Warning< "protocol method is expected to return an instance of the implementing " "class, but is declared to return %0">; @@ -5494,5 +5885,9 @@ def err_module_private_definition : Error< "definition of %0 must be imported before it is required">; } -} // end of sema component. +let CategoryName = "Documentation Issue" in { +def warn_not_a_doxygen_trailing_member_comment : Warning< + "not a Doxygen trailing comment">, InGroup<Documentation>, DefaultIgnore; +} // end of documentation issue category +} // end of sema component. diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td index 7f9fe26..a440e80 100644 --- a/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/include/clang/Basic/DiagnosticSerializationKinds.td @@ -10,7 +10,7 @@ let Component = "Serialization" in { def err_fe_unable_to_read_pch_file : Error< - "unable to read PCH file: '%0'">; + "unable to read PCH file %0: '%1'">; def err_fe_not_a_pch_file : Error< "input is not a PCH file: '%0'">; def err_fe_pch_malformed : Error< @@ -22,6 +22,8 @@ def err_fe_pch_error_at_end_block : Error< def err_fe_pch_file_modified : Error< "file '%0' has been modified since the precompiled header was built">, DefaultFatal; +def err_fe_pch_file_overridden : Error< + "file '%0' from the precompiled header has been overridden">; def warn_pch_target_triple : Error< "PCH file was compiled for the target '%0' but the current translation " diff --git a/include/clang/Basic/ExceptionSpecificationType.h b/include/clang/Basic/ExceptionSpecificationType.h index e911bde..edd89ec 100644 --- a/include/clang/Basic/ExceptionSpecificationType.h +++ b/include/clang/Basic/ExceptionSpecificationType.h @@ -6,10 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the ExceptionSpecificationType enumeration and various -// utility functions. -// +/// +/// \file +/// \brief Defines the ExceptionSpecificationType enumeration and various +/// utility functions. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_EXCEPTIONSPECIFICATIONTYPE_H #define LLVM_CLANG_BASIC_EXCEPTIONSPECIFICATIONTYPE_H @@ -24,7 +25,7 @@ enum ExceptionSpecificationType { EST_MSAny, ///< Microsoft throw(...) extension EST_BasicNoexcept, ///< noexcept EST_ComputedNoexcept, ///< noexcept(expression) - EST_Delayed, ///< not known yet + EST_Unevaluated, ///< not evaluated yet, for special member function EST_Uninstantiated ///< not instantiated yet }; @@ -36,6 +37,10 @@ inline bool isNoexceptExceptionSpec(ExceptionSpecificationType ESpecType) { return ESpecType == EST_BasicNoexcept || ESpecType == EST_ComputedNoexcept; } +inline bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType) { + return ESpecType == EST_Unevaluated || ESpecType == EST_Uninstantiated; +} + /// \brief Possible results from evaluation of a noexcept expression. enum CanThrowResult { CT_Cannot, diff --git a/include/clang/Basic/ExpressionTraits.h b/include/clang/Basic/ExpressionTraits.h index c4e6a1c..e877715 100644 --- a/include/clang/Basic/ExpressionTraits.h +++ b/include/clang/Basic/ExpressionTraits.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines enumerations for expression traits intrinsics. -// +/// +/// \file +/// \brief Defines enumerations for expression traits intrinsics. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_EXPRESSIONTRAITS_H diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h index 5c7d9eb..b00f2b7 100644 --- a/include/clang/Basic/FileManager.h +++ b/include/clang/Basic/FileManager.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the FileManager interface. -// +/// +/// \file +/// \brief Defines the clang::FileManager interface and associated types. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_FILEMANAGER_H @@ -40,9 +41,8 @@ namespace clang { class FileManager; class FileSystemStatCache; -/// DirectoryEntry - Cached information about one directory (either on -/// the disk or in the virtual file system). -/// +/// \brief Cached information about one directory (either on disk or in +/// the virtual file system). class DirectoryEntry { const char *Name; // Name of the directory. friend class FileManager; @@ -51,10 +51,11 @@ public: const char *getName() const { return Name; } }; -/// FileEntry - Cached information about one file (either on the disk -/// or in the virtual file system). If the 'FD' member is valid, then -/// this FileEntry has an open file descriptor for the file. +/// \brief Cached information about one file (either on disk +/// or in the virtual file system). /// +/// If the 'FD' member is valid, then this FileEntry has an open file +/// descriptor for the file. class FileEntry { const char *Name; // Name of the file. off_t Size; // File size in bytes. @@ -96,8 +97,7 @@ public: time_t getModificationTime() const { return ModTime; } mode_t getFileMode() const { return FileMode; } - /// getDir - Return the directory the file lives in. - /// + /// \brief Return the directory the file lives in. const DirectoryEntry *getDir() const { return Dir; } bool operator<(const FileEntry &RHS) const { @@ -105,10 +105,12 @@ public: } }; -/// FileManager - Implements support for file system lookup, file system -/// caching, and directory search management. This also handles more advanced -/// properties, such as uniquing files based on "inode", so that a file with two -/// names (e.g. symlinked) will be treated as a single file. +/// \brief Implements support for file system lookup, file system caching, +/// and directory search management. +/// +/// This also handles more advanced properties, such as uniquing files based +/// on "inode", so that a file with two names (e.g. symlinked) will be treated +/// as a single file. /// class FileManager : public RefCountedBase<FileManager> { FileSystemOptions FileSystemOpts; @@ -116,30 +118,37 @@ class FileManager : public RefCountedBase<FileManager> { class UniqueDirContainer; class UniqueFileContainer; - /// UniqueRealDirs/UniqueRealFiles - Cache for existing real - /// directories/files. - /// + /// \brief Cache for existing real directories. UniqueDirContainer &UniqueRealDirs; + + /// \brief Cache for existing real files. UniqueFileContainer &UniqueRealFiles; - /// \brief The virtual directories that we have allocated. For each - /// virtual file (e.g. foo/bar/baz.cpp), we add all of its parent + /// \brief The virtual directories that we have allocated. + /// + /// For each virtual file (e.g. foo/bar/baz.cpp), we add all of its parent /// directories (foo/ and foo/bar/) here. SmallVector<DirectoryEntry*, 4> VirtualDirectoryEntries; /// \brief The virtual files that we have allocated. SmallVector<FileEntry*, 4> VirtualFileEntries; - /// SeenDirEntries/SeenFileEntries - This is a cache that maps paths - /// to directory/file entries (either real or virtual) we have - /// looked up. The actual Entries for real directories/files are + /// \brief A cache that maps paths to directory entries (either real or + /// virtual) we have looked up + /// + /// The actual Entries for real directories/files are /// owned by UniqueRealDirs/UniqueRealFiles above, while the Entries /// for virtual directories/files are owned by /// VirtualDirectoryEntries/VirtualFileEntries above. /// llvm::StringMap<DirectoryEntry*, llvm::BumpPtrAllocator> SeenDirEntries; + + /// \brief A cache that maps paths to file entries (either real or + /// virtual) we have looked up. + /// + /// \see SeenDirEntries llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator> SeenFileEntries; - /// NextFileUID - Each FileEntry we create is assigned a unique ID #. + /// \brief Each FileEntry we create is assigned a unique ID #. /// unsigned NextFileUID; @@ -177,8 +186,13 @@ public: /// \brief Removes the specified FileSystemStatCache object from the manager. void removeStatCache(FileSystemStatCache *statCache); - /// getDirectory - Lookup, cache, and verify the specified directory - /// (real or virtual). This returns NULL if the directory doesn't exist. + /// \brief Removes all FileSystemStatCache objects from the manager. + void clearStatCaches(); + + /// \brief Lookup, cache, and verify the specified directory (real or + /// virtual). + /// + /// This returns NULL if the directory doesn't exist. /// /// \param CacheFailure If true and the file does not exist, we'll cache /// the failure to find this file. @@ -186,7 +200,9 @@ public: bool CacheFailure = true); /// \brief Lookup, cache, and verify the specified file (real or - /// virtual). This returns NULL if the file doesn't exist. + /// virtual). + /// + /// This returns NULL if the file doesn't exist. /// /// \param OpenFile if true and the file exists, it will be opened. /// @@ -199,23 +215,29 @@ public: const FileSystemOptions &getFileSystemOptions() { return FileSystemOpts; } /// \brief Retrieve a file entry for a "virtual" file that acts as - /// if there were a file with the given name on disk. The file - /// itself is not accessed. + /// if there were a file with the given name on disk. + /// + /// The file itself is not accessed. const FileEntry *getVirtualFile(StringRef Filename, off_t Size, time_t ModificationTime); /// \brief Open the specified file as a MemoryBuffer, returning a new /// MemoryBuffer if successful, otherwise returning null. llvm::MemoryBuffer *getBufferForFile(const FileEntry *Entry, - std::string *ErrorStr = 0); + std::string *ErrorStr = 0, + bool isVolatile = false); llvm::MemoryBuffer *getBufferForFile(StringRef Filename, std::string *ErrorStr = 0); - // getNoncachedStatValue - Will get the 'stat' information for the given path. - // If the path is relative, it will be resolved against the WorkingDir of the - // FileManager's FileSystemOptions. + /// \brief Get the 'stat' information for the given \p Path. + /// + /// If the path is relative, it will be resolved against the WorkingDir of the + /// FileManager's FileSystemOptions. bool getNoncachedStatValue(StringRef Path, struct stat &StatBuf); + /// \brief Remove the real file \p Entry from the cache. + void invalidateCache(const FileEntry *Entry); + /// \brief If path is not absolute and FileSystemOptions set the working /// directory, the path is modified to be relative to the given /// working directory. @@ -226,6 +248,11 @@ public: void GetUniqueIDMapping( SmallVectorImpl<const FileEntry *> &UIDToFiles) const; + /// \brief Modifies the size and modification time of a previously created + /// FileEntry. Use with caution. + static void modifyFileEntry(FileEntry *File, off_t Size, + time_t ModificationTime); + void PrintStats() const; }; diff --git a/include/clang/Basic/FileSystemOptions.h b/include/clang/Basic/FileSystemOptions.h index 81e928d..38f1346 100644 --- a/include/clang/Basic/FileSystemOptions.h +++ b/include/clang/Basic/FileSystemOptions.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the FileSystemOptions interface. -// +/// +/// \file +/// \brief Defines the clang::FileSystemOptions interface. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_FILESYSTEMOPTIONS_H diff --git a/include/clang/Basic/FileSystemStatCache.h b/include/clang/Basic/FileSystemStatCache.h index 96a2f90..a802c7c 100644 --- a/include/clang/Basic/FileSystemStatCache.h +++ b/include/clang/Basic/FileSystemStatCache.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the FileSystemStatCache interface. -// +/// +/// \file +/// \brief Defines the FileSystemStatCache interface. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_FILESYSTEMSTATCACHE_H @@ -34,13 +35,14 @@ public: virtual ~FileSystemStatCache() {} enum LookupResult { - CacheExists, //< We know the file exists and its cached stat data. - CacheMissing //< We know that the file doesn't exist. + CacheExists, ///< We know the file exists and its cached stat data. + CacheMissing ///< We know that the file doesn't exist. }; - /// FileSystemStatCache::get - Get the 'stat' information for the specified - /// path, using the cache to accellerate it if possible. This returns true if - /// the path does not exist or false if it exists. + /// \brief Get the 'stat' information for the specified path, using the cache + /// to accelerate it if possible. + /// + /// \returns \c true if the path does not exist or \c false if it exists. /// /// If FileDescriptor is non-null, then this lookup should only return success /// for files (not directories). If it is null this lookup should only return diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index cc0080b..dc6acda 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -6,10 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the IdentifierInfo, IdentifierTable, and Selector -// interfaces. -// +/// +/// \file +/// \brief Defines the clang::IdentifierInfo, clang::IdentifierTable, and +/// clang::Selector interfaces. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_IDENTIFIERTABLE_H @@ -37,12 +38,12 @@ namespace clang { class MultiKeywordSelector; // private class used by Selector class DeclarationName; // AST class that stores declaration names - /// IdentifierLocPair - A simple pair of identifier info and location. + /// \brief A simple pair of identifier info and location. typedef std::pair<IdentifierInfo*, SourceLocation> IdentifierLocPair; -/// IdentifierInfo - One of these records is kept for each identifier that -/// is lexed. This contains information about whether the token was #define'd, +/// One of these records is kept for each identifier that +/// is lexed. This contains information about whether the token was \#define'd, /// is a language keyword, or if it is a front-end token of some sort (e.g. a /// variable or function name). The preprocessor keeps this information in a /// set, and all tok::identifier tokens have a pointer to one of these. @@ -67,7 +68,7 @@ class IdentifierInfo { bool OutOfDate : 1; // True if there may be additional // information about this identifier // stored externally. - bool IsModulesImport : 1; // True if this is the 'import' contextual + bool IsModulesImport : 1; // True if this is the 'import' contextual // keyword. // 1 bit left in 32-bit word. @@ -83,15 +84,16 @@ public: IdentifierInfo(); - /// isStr - Return true if this is the identifier for the specified string. + /// \brief Return true if this is the identifier for the specified string. + /// /// This is intended to be used for string literals only: II->isStr("foo"). template <std::size_t StrLen> bool isStr(const char (&Str)[StrLen]) const { return getLength() == StrLen-1 && !memcmp(getNameStart(), Str, StrLen-1); } - /// getNameStart - Return the beginning of the actual string for this - /// identifier. The returned string is properly null terminated. + /// \brief Return the beginning of the actual null-terminated string for this + /// identifier. /// const char *getNameStart() const { if (Entry) return Entry->getKeyData(); @@ -104,7 +106,7 @@ public: return ((const actualtype*) this)->second; } - /// getLength - Efficiently return the length of this identifier info. + /// \brief Efficiently return the length of this identifier info. /// unsigned getLength() const { if (Entry) return Entry->getKeyLength(); @@ -118,13 +120,12 @@ public: return (((unsigned) p[0]) | (((unsigned) p[1]) << 8)) - 1; } - /// getName - Return the actual identifier string. + /// \brief Return the actual identifier string. StringRef getName() const { return StringRef(getNameStart(), getLength()); } - /// hasMacroDefinition - Return true if this identifier is #defined to some - /// other value. + /// \brief Return true if this identifier is \#defined to some other value. bool hasMacroDefinition() const { return HasMacro; } @@ -158,13 +159,14 @@ public: RevertedTokenID = true; } - /// getPPKeywordID - Return the preprocessor keyword ID for this identifier. + /// \brief Return the preprocessor keyword ID for this identifier. + /// /// For example, "define" will return tok::pp_define. tok::PPKeywordKind getPPKeywordID() const; - /// getObjCKeywordID - Return the Objective-C keyword ID for the this - /// identifier. For example, 'class' will return tok::objc_class if ObjC is - /// enabled. + /// \brief Return the Objective-C keyword ID for the this identifier. + /// + /// For example, 'class' will return tok::objc_class if ObjC is enabled. tok::ObjCKeywordKind getObjCKeywordID() const { if (ObjCOrBuiltinID < tok::NUM_OBJC_KEYWORDS) return tok::ObjCKeywordKind(ObjCOrBuiltinID); @@ -400,10 +402,11 @@ public: virtual IdentifierInfo *GetIdentifier(unsigned ID) = 0; }; -/// IdentifierTable - This table implements an efficient mapping from strings to -/// IdentifierInfo nodes. It has no other purpose, but this is an -/// extremely performance-critical piece of the code, as each occurrence of -/// every identifier goes through here when lexed. +/// \brief Implements an efficient mapping from strings to IdentifierInfo nodes. +/// +/// This has no other purpose, but this is an extremely performance-critical +/// piece of the code, as each occurrence of every identifier goes through +/// here when lexed. class IdentifierTable { // Shark shows that using MallocAllocator is *much* slower than using this // BumpPtrAllocator! @@ -413,8 +416,8 @@ class IdentifierTable { IdentifierInfoLookup* ExternalLookup; public: - /// IdentifierTable ctor - Create the identifier table, populating it with - /// info about the language keywords for the language specified by LangOpts. + /// \brief Create the identifier table, populating it with info about the + /// language keywords for the language specified by \p LangOpts. IdentifierTable(const LangOptions &LangOpts, IdentifierInfoLookup* externalLookup = 0); @@ -432,8 +435,8 @@ public: return HashTable.getAllocator(); } - /// get - Return the identifier token info for the specified named identifier. - /// + /// \brief Return the identifier token info for the specified named + /// identifier. IdentifierInfo &get(StringRef Name) { llvm::StringMapEntry<IdentifierInfo*> &Entry = HashTable.GetOrCreateValue(Name); @@ -507,15 +510,16 @@ public: iterator end() const { return HashTable.end(); } unsigned size() const { return HashTable.size(); } - /// PrintStats - Print some statistics to stderr that indicate how well the + /// \brief Print some statistics to stderr that indicate how well the /// hashing is doing. void PrintStats() const; void AddKeywords(const LangOptions &LangOpts); }; -/// ObjCMethodFamily - A family of Objective-C methods. These -/// families have no inherent meaning in the language, but are +/// \brief A family of Objective-C methods. +/// +/// These families have no inherent meaning in the language, but are /// nonetheless central enough in the existing implementations to /// merit direct AST support. While, in theory, arbitrary methods can /// be considered to form families, we focus here on the methods @@ -562,11 +566,13 @@ enum ObjCMethodFamily { /// InvalidObjCMethodFamily. enum { ObjCMethodFamilyBitWidth = 4 }; -/// An invalid value of ObjCMethodFamily. +/// \brief An invalid value of ObjCMethodFamily. enum { InvalidObjCMethodFamily = (1 << ObjCMethodFamilyBitWidth) - 1 }; -/// Selector - This smart pointer class efficiently represents Objective-C -/// method names. This class will either point to an IdentifierInfo or a +/// \brief Smart pointer class that efficiently represents Objective-C method +/// names. +/// +/// This class will either point to an IdentifierInfo or a /// MultiKeywordSelector (which is private). This enables us to optimize /// selectors that take no arguments and selectors that take 1 argument, which /// accounts for 78% of all selectors in Cocoa.h. @@ -574,9 +580,10 @@ class Selector { friend class Diagnostic; enum IdentifierInfoFlag { - // MultiKeywordSelector = 0. + // Empty selector = 0. ZeroArg = 0x1, OneArg = 0x2, + MultiArg = 0x3, ArgFlags = ZeroArg|OneArg }; uintptr_t InfoPtr; // a pointer to the MultiKeywordSelector or IdentifierInfo. @@ -590,13 +597,18 @@ class Selector { Selector(MultiKeywordSelector *SI) { InfoPtr = reinterpret_cast<uintptr_t>(SI); assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo"); + InfoPtr |= MultiArg; } IdentifierInfo *getAsIdentifierInfo() const { - if (getIdentifierInfoFlag()) + if (getIdentifierInfoFlag() < MultiArg) return reinterpret_cast<IdentifierInfo *>(InfoPtr & ~ArgFlags); return 0; } + MultiKeywordSelector *getMultiKeywordSelector() const { + return reinterpret_cast<MultiKeywordSelector *>(InfoPtr & ~ArgFlags); + } + unsigned getIdentifierInfoFlag() const { return InfoPtr & ArgFlags; } @@ -661,11 +673,12 @@ public: /// name was supplied. StringRef getNameForSlot(unsigned argIndex) const; - /// getAsString - Derive the full selector name (e.g. "foo:bar:") and return + /// \brief Derive the full selector name (e.g. "foo:bar:") and return /// it as an std::string. + // FIXME: Add a print method that uses a raw_ostream. std::string getAsString() const; - /// getMethodFamily - Derive the conventional family of this method. + /// \brief Derive the conventional family of this method. ObjCMethodFamily getMethodFamily() const { return getMethodFamilyImpl(*this); } @@ -678,7 +691,7 @@ public: } }; -/// SelectorTable - This table allows us to fully hide how we implement +/// \brief This table allows us to fully hide how we implement /// multi-keyword caching. class SelectorTable { void *Impl; // Actually a SelectorTableImpl @@ -688,9 +701,10 @@ public: SelectorTable(); ~SelectorTable(); - /// getSelector - This can create any sort of selector. NumArgs indicates - /// whether this is a no argument selector "foo", a single argument selector - /// "foo:" or multi-argument "foo:bar:". + /// \brief Can create any sort of selector. + /// + /// \p NumArgs indicates whether this is a no argument selector "foo", a + /// single argument selector "foo:" or multi-argument "foo:bar:". Selector getSelector(unsigned NumArgs, IdentifierInfo **IIV); Selector getUnarySelector(IdentifierInfo *ID) { @@ -700,11 +714,12 @@ public: return Selector(ID, 0); } - /// Return the total amount of memory allocated for managing selectors. + /// \brief Return the total amount of memory allocated for managing selectors. size_t getTotalMemory() const; - /// constructSetterName - Return the setter name for the given - /// identifier, i.e. "set" + Name where the initial character of Name + /// \brief Return the setter name for the given identifier. + /// + /// This is "set" + \p Name where the initial character of \p Name /// has been capitalized. static Selector constructSetterName(IdentifierTable &Idents, SelectorTable &SelTable, diff --git a/include/clang/Basic/LLVM.h b/include/clang/Basic/LLVM.h index 813b49e..13c5b44 100644 --- a/include/clang/Basic/LLVM.h +++ b/include/clang/Basic/LLVM.h @@ -7,9 +7,10 @@ // //===----------------------------------------------------------------------===// // -// This file forward declares and imports various common LLVM datatypes that -// clang wants to use unqualified. -// +/// \file +/// \brief Forward declares and imports various common LLVM datatypes that +/// clang wants to use unqualified. +/// //===----------------------------------------------------------------------===// #ifndef CLANG_BASIC_LLVM_H diff --git a/include/clang/Basic/Lambda.h b/include/clang/Basic/Lambda.h index df50d94..b1ad6ac 100644 --- a/include/clang/Basic/Lambda.h +++ b/include/clang/Basic/Lambda.h @@ -6,9 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines several types used to describe C++ lambda -// expressions that are shared between the parser and AST. +/// +/// \file +/// \brief Defines several types used to describe C++ lambda expressions +/// that are shared between the parser and AST. +/// //===----------------------------------------------------------------------===// @@ -17,16 +19,15 @@ namespace clang { -/// LambdaCaptureDefault - The default, if any, capture method for a -/// lambda expression. +/// \brief The default, if any, capture method for a lambda expression. enum LambdaCaptureDefault { LCD_None, LCD_ByCopy, LCD_ByRef }; -/// LambdaCaptureKind - The different capture forms in a lambda -/// introducer: 'this' or a copied or referenced variable. +/// \brief The different capture forms in a lambda introducer: 'this' or a +/// copied or referenced variable. enum LambdaCaptureKind { LCK_This, LCK_ByCopy, diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index d2ce7c0..fab17a2 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -50,8 +50,6 @@ LANGOPT(CPlusPlus , 1, 0, "C++") LANGOPT(CPlusPlus0x , 1, 0, "C++0x") LANGOPT(ObjC1 , 1, 0, "Objective-C 1") LANGOPT(ObjC2 , 1, 0, "Objective-C 2") -LANGOPT(ObjCNonFragileABI , 1, 0, "Objective-C modern abi") -LANGOPT(ObjCNonFragileABI2 , 1, 0, "Objective-C enhanced modern abi") BENIGN_LANGOPT(ObjCDefaultSynthProperties , 1, 0, "Objective-C auto-synthesized properties") BENIGN_LANGOPT(ObjCInferRelatedResultType , 1, 1, @@ -80,7 +78,6 @@ LANGOPT(SjLjExceptions , 1, 0, "setjmp-longjump exception handling") LANGOPT(TraditionalCPP , 1, 0, "traditional CPP emulation") LANGOPT(RTTI , 1, 1, "run-time type information") LANGOPT(MSBitfields , 1, 0, "Microsoft-compatible structure layout") -LANGOPT(NeXTRuntime , 1, 1, "NeXT Objective-C runtime") LANGOPT(Freestanding, 1, 0, "freestanding implementation") LANGOPT(NoBuiltin , 1, 0, "disable builtin functions") @@ -102,6 +99,7 @@ LANGOPT(GNUInline , 1, 0, "GNU inline semantics") LANGOPT(NoInlineDefine , 1, 0, "__NO_INLINE__ predefined macro") LANGOPT(Deprecated , 1, 0, "__DEPRECATED predefined macro") LANGOPT(FastMath , 1, 0, "__FAST_MATH__ predefined macro") +LANGOPT(FiniteMathOnly , 1, 0, "__FINITE_MATH_ONLY__ predefined macro") BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __weak/__strong ivars") @@ -112,6 +110,7 @@ LANGOPT(ShortWChar , 1, 0, "unsigned short wchar_t") LANGOPT(ShortEnums , 1, 0, "short enum types") LANGOPT(OpenCL , 1, 0, "OpenCL") +LANGOPT(OpenCLVersion , 32, 0, "OpenCL version") LANGOPT(CUDA , 1, 0, "CUDA") LANGOPT(AssumeSaneOperatorNew , 1, 1, "implicit __attribute__((malloc)) for C++'s new operators") @@ -125,7 +124,7 @@ BENIGN_LANGOPT(InlineVisibilityHidden , 1, 0, "hidden default visibility for inl BENIGN_LANGOPT(ParseUnknownAnytype, 1, 0, "__unknown_anytype") BENIGN_LANGOPT(DebuggerSupport , 1, 0, "debugger support") BENIGN_LANGOPT(DebuggerCastResultToId, 1, 0, "for 'po' in the debugger, cast the result to id if it is of unknown type") -BENIGN_LANGOPT(DebuggerObjCLiteral , 1, 0, "debugger objective-C literals and subscripting support") +BENIGN_LANGOPT(DebuggerObjCLiteral , 1, 0, "debugger Objective-C literals and subscripting support") BENIGN_LANGOPT(AddressSanitizer , 1, 0, "AddressSanitizer enabled") BENIGN_LANGOPT(ThreadSanitizer , 1, 0, "ThreadSanitizer enabled") @@ -150,8 +149,9 @@ ENUM_LANGOPT(StackProtector, StackProtectorMode, 2, SSPOff, "stack protector mode") ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, SOB_Undefined, "signed integer overflow handling") +ENUM_LANGOPT(FPContractMode, FPContractModeKind, 2, FPC_On, "FP_CONTRACT mode") -BENIGN_LANGOPT(InstantiationDepth, 32, 1024, +BENIGN_LANGOPT(InstantiationDepth, 32, 512, "maximum template instantiation depth") BENIGN_LANGOPT(ConstexprCallDepth, 32, 512, "maximum constexpr call depth") diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index ce4ff06..fbb014e 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the LangOptions interface. -// +/// +/// \file +/// \brief Defines the clang::LangOptions interface. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_LANGOPTIONS_H @@ -16,6 +17,7 @@ #include <string> #include "clang/Basic/LLVM.h" +#include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Visibility.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" @@ -39,8 +41,8 @@ protected: #include "clang/Basic/LangOptions.def" }; -/// LangOptions - This class keeps track of the various options that can be -/// enabled, which controls the dialect of C that is accepted. +/// \brief Keeps track of the various options that can be +/// enabled, which controls the dialect of C or C++ that is accepted. class LangOptions : public RefCountedBase<LangOptions>, public LangOptionsBase { public: typedef clang::Visibility Visibility; @@ -54,10 +56,20 @@ public: SOB_Trapping // -ftrapv }; + enum FPContractModeKind { + FPC_Off, // Form fused FP ops only where result will not be affected. + FPC_On, // Form fused FP ops according to FP_CONTRACT rules. + FPC_Fast // Aggressively fuse FP ops (E.g. FMA). + }; + public: + clang::ObjCRuntime ObjCRuntime; + std::string ObjCConstantStringClass; - /// The name of the handler function to be called when -ftrapv is specified. + /// \brief The name of the handler function to be called when -ftrapv is + /// specified. + /// /// If none is specified, abort (GCC-compatible behaviour). std::string OverflowHandler; @@ -82,7 +94,7 @@ public: void resetNonModularOptions(); }; -/// Floating point control options +/// \brief Floating point control options class FPOptions { public: unsigned fp_contract : 1; @@ -93,7 +105,7 @@ public: fp_contract(LangOpts.DefaultFPContract) {} }; -/// OpenCL volatile options +/// \brief OpenCL volatile options class OpenCLOptions { public: #define OPENCLEXT(nm) unsigned nm : 1; @@ -116,7 +128,6 @@ enum TranslationUnitKind { TU_Module }; - /// \brief } // end namespace clang #endif diff --git a/include/clang/Basic/Linkage.h b/include/clang/Basic/Linkage.h index 09a5a0b..6bc1f5d 100644 --- a/include/clang/Basic/Linkage.h +++ b/include/clang/Basic/Linkage.h @@ -6,10 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the Linkage enumeration and various utility -// functions. -// +/// +/// \file +/// \brief Defines the Linkage enumeration and various utility functions. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_LINKAGE_H #define LLVM_CLANG_BASIC_LINKAGE_H @@ -28,8 +28,9 @@ enum Linkage { /// translation units). InternalLinkage, - /// \brief External linkage within a unique namespace. From the - /// language perspective, these entities have external + /// \brief External linkage within a unique namespace. + /// + /// From the language perspective, these entities have external /// linkage. However, since they reside in an anonymous namespace, /// their names are unique to this translation unit, which is /// equivalent to having internal linkage from the code-generation @@ -41,8 +42,9 @@ enum Linkage { ExternalLinkage }; -/// \brief A more specific kind of linkage. This is relevant to CodeGen and -/// AST file reading. +/// \brief A more specific kind of linkage than enum Linkage. +/// +/// This is relevant to CodeGen and AST file reading. enum GVALinkage { GVA_Internal, GVA_C99Inline, @@ -52,14 +54,13 @@ enum GVALinkage { GVA_ExplicitTemplateInstantiation }; -/// \brief Determine whether the given linkage is semantically -/// external. +/// \brief Determine whether the given linkage is semantically external. inline bool isExternalLinkage(Linkage L) { return L == UniqueExternalLinkage || L == ExternalLinkage; } /// \brief Compute the minimum linkage given two linages. -static inline Linkage minLinkage(Linkage L1, Linkage L2) { +inline Linkage minLinkage(Linkage L1, Linkage L2) { return L1 < L2? L1 : L2; } diff --git a/include/clang/Basic/MacroBuilder.h b/include/clang/Basic/MacroBuilder.h index 1d0f1e8..6df3a38 100644 --- a/include/clang/Basic/MacroBuilder.h +++ b/include/clang/Basic/MacroBuilder.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the MacroBuilder utility class. -// +/// +/// \file +/// \brief Defines the clang::MacroBuilder utility class. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_MACROBUILDER_H @@ -24,13 +25,13 @@ class MacroBuilder { public: MacroBuilder(raw_ostream &Output) : Out(Output) {} - /// Append a #define line for macro of the form "#define Name Value\n". + /// Append a \#define line for macro of the form "\#define Name Value\n". void defineMacro(const Twine &Name, const Twine &Value = "1") { Out << "#define " << Name << ' ' << Value << '\n'; } - /// Append a #undef line for Name. Name should be of the form XXX - /// and we emit "#undef XXX". + /// Append a \#undef line for Name. Name should be of the form XXX + /// and we emit "\#undef XXX". void undefineMacro(const Twine &Name) { Out << "#undef " << Name << '\n'; } diff --git a/include/clang/Basic/Makefile b/include/clang/Basic/Makefile index 702afac..6a33133 100644 --- a/include/clang/Basic/Makefile +++ b/include/clang/Basic/Makefile @@ -1,6 +1,7 @@ CLANG_LEVEL := ../../.. BUILT_SOURCES = \ DiagnosticAnalysisKinds.inc DiagnosticASTKinds.inc \ + DiagnosticCommentKinds.inc \ DiagnosticCommonKinds.inc DiagnosticDriverKinds.inc \ DiagnosticFrontendKinds.inc DiagnosticLexKinds.inc \ DiagnosticParseKinds.inc DiagnosticSemaKinds.inc \ diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h index 82dbd5b..c8027f4 100644 --- a/include/clang/Basic/Module.h +++ b/include/clang/Basic/Module.h @@ -6,10 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the Module class, which describes a module in the source -// code. -// +/// +/// \file +/// \brief Defines the clang::Module class, which describes a module in the +/// source code. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_MODULE_H #define LLVM_CLANG_BASIC_MODULE_H @@ -137,7 +138,7 @@ public: llvm::SmallVector<ExportDecl, 2> Exports; /// \brief Describes an exported module that has not yet been resolved - /// (perhaps because tASThe module it refers to has not yet been loaded). + /// (perhaps because the module it refers to has not yet been loaded). struct UnresolvedExportDecl { /// \brief The location of the 'export' keyword in the module map file. SourceLocation ExportLoc; @@ -243,7 +244,7 @@ public: return Umbrella && Umbrella.is<const DirectoryEntry *>(); } - /// \briaf Add the given feature requirement to the list of features + /// \brief Add the given feature requirement to the list of features /// required by this module. /// /// \param Feature The feature that is required by this module (and diff --git a/include/clang/Basic/ObjCRuntime.h b/include/clang/Basic/ObjCRuntime.h new file mode 100644 index 0000000..b24fe7c --- /dev/null +++ b/include/clang/Basic/ObjCRuntime.h @@ -0,0 +1,264 @@ +//===--- ObjCRuntime.h - Objective-C Runtime Configuration ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Defines types useful for describing an Objective-C runtime. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_OBJCRUNTIME_H +#define LLVM_CLANG_OBJCRUNTIME_H + +#include "clang/Basic/VersionTuple.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/ErrorHandling.h" + +namespace clang { + +/// \brief The basic abstraction for the target Objective-C runtime. +class ObjCRuntime { +public: + /// \brief The basic Objective-C runtimes that we know about. + enum Kind { + /// 'macosx' is the Apple-provided NeXT-derived runtime on Mac OS + /// X platforms that use the non-fragile ABI; the version is a + /// release of that OS. + MacOSX, + + /// 'macosx-fragile' is the Apple-provided NeXT-derived runtime on + /// Mac OS X platforms that use the fragile ABI; the version is a + /// release of that OS. + FragileMacOSX, + + /// 'ios' is the Apple-provided NeXT-derived runtime on iOS or the iOS + /// simulator; it is always non-fragile. The version is a release + /// version of iOS. + iOS, + + /// 'gcc' is the Objective-C runtime shipped with GCC, implementing a + /// fragile Objective-C ABI + GCC, + + /// 'gnustep' is the modern non-fragile GNUstep runtime. + GNUstep, + + /// 'objfw' is the Objective-C runtime included in ObjFW + ObjFW + }; + +private: + Kind TheKind; + VersionTuple Version; + +public: + /// A bogus initialization of the runtime. + ObjCRuntime() : TheKind(MacOSX) {} + + ObjCRuntime(Kind kind, const VersionTuple &version) + : TheKind(kind), Version(version) {} + + void set(Kind kind, VersionTuple version) { + TheKind = kind; + Version = version; + } + + Kind getKind() const { return TheKind; } + const VersionTuple &getVersion() const { return Version; } + + /// \brief Does this runtime follow the set of implied behaviors for a + /// "non-fragile" ABI? + bool isNonFragile() const { + switch (getKind()) { + case FragileMacOSX: return false; + case GCC: return false; + case MacOSX: return true; + case GNUstep: return true; + case ObjFW: return false; + case iOS: return true; + } + llvm_unreachable("bad kind"); + } + + /// The inverse of isNonFragile(): does this runtime follow the set of + /// implied behaviors for a "fragile" ABI? + bool isFragile() const { return !isNonFragile(); } + + /// The default dispatch mechanism to use for the specified architecture + bool isLegacyDispatchDefaultForArch(llvm::Triple::ArchType Arch) { + // The GNUstep runtime uses a newer dispatch method by default from + // version 1.6 onwards + if (getKind() == GNUstep && getVersion() >= VersionTuple(1, 6)) { + if (Arch == llvm::Triple::arm || + Arch == llvm::Triple::x86 || + Arch == llvm::Triple::x86_64) + return false; + // Mac runtimes use legacy dispatch everywhere except x86-64 + } else if (isNeXTFamily() && isNonFragile()) + return Arch != llvm::Triple::x86_64; + return true; + } + + /// \brief Is this runtime basically of the GNUstep family of runtimes? + bool isGNUFamily() const { + switch (getKind()) { + case FragileMacOSX: + case MacOSX: + case iOS: + return false; + case GCC: + case GNUstep: + case ObjFW: + return true; + } + llvm_unreachable("bad kind"); + } + + /// \brief Is this runtime basically of the NeXT family of runtimes? + bool isNeXTFamily() const { + // For now, this is just the inverse of isGNUFamily(), but that's + // not inherently true. + return !isGNUFamily(); + } + + /// \brief Does this runtime natively provide the ARC entrypoints? + /// + /// ARC cannot be directly supported on a platform that does not provide + /// these entrypoints, although it may be supportable via a stub + /// library. + bool hasARC() const { + switch (getKind()) { + case FragileMacOSX: return false; + case MacOSX: return getVersion() >= VersionTuple(10, 7); + case iOS: return getVersion() >= VersionTuple(5); + + case GCC: return false; + case GNUstep: return getVersion() >= VersionTuple(1, 6); + case ObjFW: return false; // XXX: this will change soon + } + llvm_unreachable("bad kind"); + } + + /// \brief Does this runtime natively provide ARC-compliant 'weak' + /// entrypoints? + bool hasWeak() const { + // Right now, this is always equivalent to the ARC decision. + return hasARC(); + } + + /// \brief Does this runtime directly support the subscripting methods? + /// + /// This is really a property of the library, not the runtime. + bool hasSubscripting() const { + switch (getKind()) { + case FragileMacOSX: return false; + case MacOSX: return getVersion() >= VersionTuple(10, 8); + case iOS: return false; + + // This is really a lie, because some implementations and versions + // of the runtime do not support ARC. Probably -fgnu-runtime + // should imply a "maximal" runtime or something? + case GCC: return true; + case GNUstep: return true; + case ObjFW: return true; + } + llvm_unreachable("bad kind"); + } + + /// \brief Does this runtime allow sizeof or alignof on object types? + bool allowsSizeofAlignof() const { + return isFragile(); + } + + /// \brief Does this runtime allow pointer arithmetic on objects? + /// + /// This covers +, -, ++, --, and (if isSubscriptPointerArithmetic() + /// yields true) []. + bool allowsPointerArithmetic() const { + switch (getKind()) { + case FragileMacOSX: + case GCC: + return true; + case MacOSX: + case iOS: + case GNUstep: + case ObjFW: + return false; + } + llvm_unreachable("bad kind"); + } + + /// \brief Is subscripting pointer arithmetic? + bool isSubscriptPointerArithmetic() const { + return allowsPointerArithmetic(); + } + + /// \brief Does this runtime provide an objc_terminate function? + /// + /// This is used in handlers for exceptions during the unwind process; + /// without it, abort() must be used in pure ObjC files. + bool hasTerminate() const { + switch (getKind()) { + case FragileMacOSX: return getVersion() >= VersionTuple(10, 8); + case MacOSX: return getVersion() >= VersionTuple(10, 8); + case iOS: return getVersion() >= VersionTuple(5); + case GCC: return false; + case GNUstep: return false; + case ObjFW: return false; + } + llvm_unreachable("bad kind"); + } + + /// \brief Does this runtime support weakly importing classes? + bool hasWeakClassImport() const { + switch (getKind()) { + case MacOSX: return true; + case iOS: return true; + case FragileMacOSX: return false; + case GCC: return true; + case GNUstep: return true; + case ObjFW: return true; + } + llvm_unreachable("bad kind"); + } + /// \brief Does this runtime use zero-cost exceptions? + bool hasUnwindExceptions() const { + switch (getKind()) { + case MacOSX: return true; + case iOS: return true; + case FragileMacOSX: return false; + case GCC: return true; + case GNUstep: return true; + case ObjFW: return true; + } + llvm_unreachable("bad kind"); + } + + /// \brief Try to parse an Objective-C runtime specification from the given + /// string. + /// + /// \return true on error. + bool tryParse(StringRef input); + + std::string getAsString() const; + + friend bool operator==(const ObjCRuntime &left, const ObjCRuntime &right) { + return left.getKind() == right.getKind() && + left.getVersion() == right.getVersion(); + } + + friend bool operator!=(const ObjCRuntime &left, const ObjCRuntime &right) { + return !(left == right); + } +}; + +raw_ostream &operator<<(raw_ostream &out, const ObjCRuntime &value); + +} // end namespace clang + +#endif diff --git a/include/clang/Basic/OnDiskHashTable.h b/include/clang/Basic/OnDiskHashTable.h index b92f1cf..79273fc 100644 --- a/include/clang/Basic/OnDiskHashTable.h +++ b/include/clang/Basic/OnDiskHashTable.h @@ -6,10 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines facilities for reading and writing on-disk hash -// tables. -// +/// +/// \file +/// \brief Defines facilities for reading and writing on-disk hash tables. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_ON_DISK_HASH_TABLE_H #define LLVM_CLANG_BASIC_ON_DISK_HASH_TABLE_H diff --git a/include/clang/Basic/OpenCL.h b/include/clang/Basic/OpenCL.h index 6f9785f..3b3f259 100644 --- a/include/clang/Basic/OpenCL.h +++ b/include/clang/Basic/OpenCL.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines some OpenCL-specific enums. -// +/// +/// \file +/// \brief Defines some OpenCL-specific enums. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_OPENCL_H @@ -16,7 +17,7 @@ namespace clang { -/// Names for the OpenCL image access qualifiers (OpenCL 1.1 6.6). +/// \brief Names for the OpenCL image access qualifiers (OpenCL 1.1 6.6). enum OpenCLImageAccess { CLIA_read_only = 1, CLIA_write_only = 2, diff --git a/include/clang/Basic/OperatorKinds.h b/include/clang/Basic/OperatorKinds.h index c0a9505..108014f 100644 --- a/include/clang/Basic/OperatorKinds.h +++ b/include/clang/Basic/OperatorKinds.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines C++ overloaded operators. -// +/// +/// \file +/// \brief Defines an enumeration for C++ overloaded operators. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_OPERATOR_KINDS_H @@ -16,10 +17,10 @@ namespace clang { -/// OverloadedOperatorKind - Enumeration specifying the different kinds of -/// C++ overloaded operators. +/// \brief Enumeration specifying the different kinds of C++ overloaded +/// operators. enum OverloadedOperatorKind { - OO_None, //< Not an overloaded operator + OO_None, ///< Not an overloaded operator #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ OO_##Name, #include "clang/Basic/OperatorKinds.def" diff --git a/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h index 007e6a4..3f4626e 100644 --- a/include/clang/Basic/PartialDiagnostic.h +++ b/include/clang/Basic/PartialDiagnostic.h @@ -6,10 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file implements a partial diagnostic that can be emitted anwyhere -// in a DiagnosticBuilder stream. -// +/// +/// \file +/// \brief Implements a partial diagnostic that can be emitted anwyhere +/// in a DiagnosticBuilder stream. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_PARTIALDIAGNOSTIC_H @@ -37,25 +38,26 @@ public: Storage() : NumDiagArgs(0), NumDiagRanges(0) { } enum { - /// MaxArguments - The maximum number of arguments we can hold. We + /// \brief The maximum number of arguments we can hold. We /// currently only support up to 10 arguments (%0-%9). + /// /// A single diagnostic with more than that almost certainly has to /// be simplified anyway. MaxArguments = PartialDiagnostic::MaxArguments }; - /// NumDiagArgs - This contains the number of entries in Arguments. + /// \brief The number of entries in Arguments. unsigned char NumDiagArgs; - /// NumDiagRanges - This is the number of ranges in the DiagRanges array. + /// \brief This is the number of ranges in the DiagRanges array. unsigned char NumDiagRanges; - /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum - /// values, with one for each argument. This specifies whether the argument - /// is in DiagArgumentsStr or in DiagArguments. + /// \brief Specifies for each argument whether it is in DiagArgumentsStr + /// or in DiagArguments. unsigned char DiagArgumentsKind[MaxArguments]; - /// DiagArgumentsVal - The values for the various substitution positions. + /// \brief The values for the various substitution positions. + /// /// This is used when the argument is not an std::string. The specific value /// is mangled into an intptr_t and the interpretation depends on exactly /// what sort of argument kind it is. @@ -65,12 +67,13 @@ public: /// string arguments. std::string DiagArgumentsStr[MaxArguments]; - /// DiagRanges - The list of ranges added to this diagnostic. It currently - /// only support 10 ranges, could easily be extended if needed. + /// \brief The list of ranges added to this diagnostic. + /// + /// It currently only support 10 ranges, could easily be extended if needed. CharSourceRange DiagRanges[10]; - /// FixItHints - If valid, provides a hint with some code - /// to insert, remove, or modify at a particular position. + /// \brief If valid, provides a hint with some code to insert, remove, or + /// modify at a particular position. SmallVector<FixItHint, 6> FixItHints; }; @@ -114,10 +117,10 @@ private: // in the sense that its bits can be safely memcpy'ed and destructed // in the new location. - /// DiagID - The diagnostic ID. + /// \brief The diagnostic ID. mutable unsigned DiagID; - /// DiagStorage - Storage for args and ranges. + /// \brief Storage for args and ranges. mutable Storage *DiagStorage; /// \brief Allocator used to allocate storage for this diagnostic. @@ -179,6 +182,12 @@ private: } public: + struct NullDiagnostic {}; + /// \brief Create a null partial diagnostic, which cannot carry a payload, + /// and only exists to be swapped with a real partial diagnostic. + PartialDiagnostic(NullDiagnostic) + : DiagID(0), DiagStorage(0), Allocator(0) { } + PartialDiagnostic(unsigned DiagID, StorageAllocator &Allocator) : DiagID(DiagID), DiagStorage(0), Allocator(&Allocator) { } @@ -237,6 +246,12 @@ public: freeStorage(); } + void swap(PartialDiagnostic &PD) { + std::swap(DiagID, PD.DiagID); + std::swap(DiagStorage, PD.DiagStorage); + std::swap(Allocator, PD.Allocator); + } + unsigned getDiagID() const { return DiagID; } void AddTaggedVal(intptr_t V, DiagnosticsEngine::ArgumentKind Kind) const { @@ -283,6 +298,18 @@ public: DB.AddFixItHint(DiagStorage->FixItHints[i]); } + void EmitToString(DiagnosticsEngine &Diags, + llvm::SmallVectorImpl<char> &Buf) const { + // FIXME: It should be possible to render a diagnostic to a string without + // messing with the state of the diagnostics engine. + DiagnosticBuilder DB(Diags.Report(getDiagID())); + Emit(DB); + DB.FlushCounts(); + Diagnostic(&Diags).FormatDiagnostic(Buf); + DB.Clear(); + Diags.Clear(); + } + /// \brief Clear out this partial diagnostic, giving it a new diagnostic ID /// and removing all of its arguments, ranges, and fix-it hints. void Reset(unsigned DiagID = 0) { diff --git a/include/clang/Basic/PrettyStackTrace.h b/include/clang/Basic/PrettyStackTrace.h index 06a1264..967d0d1 100644 --- a/include/clang/Basic/PrettyStackTrace.h +++ b/include/clang/Basic/PrettyStackTrace.h @@ -6,11 +6,12 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the PrettyStackTraceEntry class, which is used to make -// crashes give more contextual information about what the program was doing -// when it crashed. -// +/// +/// \file +/// \brief Defines the PrettyStackTraceEntry class, which is used to make +/// crashes give more contextual information about what the program was doing +/// when it crashed. +/// //===----------------------------------------------------------------------===// #ifndef CLANG_BASIC_PRETTYSTACKTRACE_H @@ -21,8 +22,8 @@ namespace clang { - /// PrettyStackTraceLoc - If a crash happens while one of these objects are - /// live, the message is printed out along with the specified source location. + /// If a crash happens while one of these objects are live, the message + /// is printed out along with the specified source location. class PrettyStackTraceLoc : public llvm::PrettyStackTraceEntry { SourceManager &SM; SourceLocation Loc; diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h index d5fa7e7..d6bba38 100644 --- a/include/clang/Basic/SourceLocation.h +++ b/include/clang/Basic/SourceLocation.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the SourceLocation class. -// +/// +/// \file +/// \brief Defines the clang::SourceLocation class and associated facilities. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_SOURCELOCATION_H @@ -31,12 +32,12 @@ namespace clang { class SourceManager; -/// FileID - This is an opaque identifier used by SourceManager which refers to -/// a source file (MemoryBuffer) along with its #include path and #line data. +/// \brief An opaque identifier used by SourceManager which refers to a +/// source file (MemoryBuffer) along with its \#include path and \#line data. /// class FileID { - /// ID - Opaque identifier, 0 is "invalid". >0 is this module, <-1 is - /// something loaded from another module. + /// \brief A mostly-opaque identifier, where 0 is "invalid", >0 is + /// this module, and <-1 is something loaded from another module. int ID; public: FileID() : ID(0) {} @@ -135,24 +136,28 @@ public: return L; } - /// getRawEncoding - When a SourceLocation itself cannot be used, this returns - /// an (opaque) 32-bit integer encoding for it. This should only be passed - /// to SourceLocation::getFromRawEncoding, it should not be inspected - /// directly. + /// \brief When a SourceLocation itself cannot be used, this returns + /// an (opaque) 32-bit integer encoding for it. + /// + /// This should only be passed to SourceLocation::getFromRawEncoding, it + /// should not be inspected directly. unsigned getRawEncoding() const { return ID; } - /// getFromRawEncoding - Turn a raw encoding of a SourceLocation object into + /// \brief Turn a raw encoding of a SourceLocation object into /// a real SourceLocation. + /// + /// \see getRawEncoding. static SourceLocation getFromRawEncoding(unsigned Encoding) { SourceLocation X; X.ID = Encoding; return X; } - /// getPtrEncoding - When a SourceLocation itself cannot be used, this returns - /// an (opaque) pointer encoding for it. This should only be passed - /// to SourceLocation::getFromPtrEncoding, it should not be inspected - /// directly. + /// \brief When a SourceLocation itself cannot be used, this returns + /// an (opaque) pointer encoding for it. + /// + /// This should only be passed to SourceLocation::getFromPtrEncoding, it + /// should not be inspected directly. void* getPtrEncoding() const { // Double cast to avoid a warning "cast to pointer from integer of different // size". @@ -161,7 +166,7 @@ public: /// getFromPtrEncoding - Turn a pointer encoding of a SourceLocation object /// into a real SourceLocation. - static SourceLocation getFromPtrEncoding(void *Encoding) { + static SourceLocation getFromPtrEncoding(const void *Encoding) { return getFromRawEncoding((unsigned)(uintptr_t)Encoding); } @@ -181,7 +186,7 @@ inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) { return LHS.getRawEncoding() < RHS.getRawEncoding(); } -/// SourceRange - a trival tuple used to represent a source range. +/// \brief A trival tuple used to represent a source range. class SourceRange { SourceLocation B; SourceLocation E; @@ -208,7 +213,8 @@ public: } }; -/// CharSourceRange - This class represents a character granular source range. +/// \brief Represents a character-granular source range. +/// /// The underlying SourceRange can either specify the starting/ending character /// of the range, or it can specify the start or the range and the start of the /// last token of the range (a "token range"). In the token range case, the @@ -242,7 +248,7 @@ public: return getCharRange(SourceRange(B, E)); } - /// isTokenRange - Return true if the end of this range specifies the start of + /// \brief Return true if the end of this range specifies the start of /// the last token. Return false if the end of this range specifies the last /// character in the range. bool isTokenRange() const { return IsTokenRange; } @@ -259,17 +265,19 @@ public: bool isInvalid() const { return !isValid(); } }; -/// FullSourceLoc - A SourceLocation and its associated SourceManager. Useful -/// for argument passing to functions that expect both objects. +/// \brief A SourceLocation and its associated SourceManager. +/// +/// This is useful for argument passing to functions that expect both objects. class FullSourceLoc : public SourceLocation { const SourceManager *SrcMgr; public: - /// Creates a FullSourceLoc where isValid() returns false. + /// \brief Creates a FullSourceLoc where isValid() returns \c false. explicit FullSourceLoc() : SrcMgr(0) {} explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM) : SourceLocation(Loc), SrcMgr(&SM) {} + /// \pre This FullSourceLoc has an associated SourceManager. const SourceManager &getManager() const { assert(SrcMgr && "SourceManager is NULL."); return *SrcMgr; @@ -290,13 +298,14 @@ public: const llvm::MemoryBuffer* getBuffer(bool *Invalid = 0) const; - /// getBufferData - Return a StringRef to the source buffer data for the + /// \brief Return a StringRef to the source buffer data for the /// specified FileID. StringRef getBufferData(bool *Invalid = 0) const; - /// getDecomposedLoc - Decompose the specified location into a raw FileID + - /// Offset pair. The first element is the FileID, the second is the - /// offset from the start of the buffer of the location. + /// \brief Decompose the specified location into a raw FileID + Offset pair. + /// + /// The first element is the FileID, the second is the offset from the + /// start of the buffer of the location. std::pair<FileID, unsigned> getDecomposedLoc() const; bool isInSystemHeader() const; @@ -323,8 +332,9 @@ public: } }; - /// Prints information about this FullSourceLoc to stderr. Useful for - /// debugging. + /// \brief Prints information about this FullSourceLoc to stderr. + /// + /// This is useful for debugging. LLVM_ATTRIBUTE_USED void dump() const; friend inline bool @@ -340,10 +350,11 @@ public: }; -/// PresumedLoc - This class represents an unpacked "presumed" location which -/// can be presented to the user. A 'presumed' location can be modified by -/// #line and GNU line marker directives and is always the expansion point of -/// a normal location. +/// \brief Represents an unpacked "presumed" location which can be presented +/// to the user. +/// +/// A 'presumed' location can be modified by \#line and GNU line marker +/// directives and is always the expansion point of a normal location. /// /// You can get a PresumedLoc from a SourceLocation with SourceManager. class PresumedLoc { @@ -356,25 +367,30 @@ public: : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) { } - /// isInvalid - Return true if this object is invalid or uninitialized. This - /// occurs when created with invalid source locations or when walking off - /// the top of a #include stack. + /// \brief Return true if this object is invalid or uninitialized. + /// + /// This occurs when created with invalid source locations or when walking + /// off the top of a \#include stack. bool isInvalid() const { return Filename == 0; } bool isValid() const { return Filename != 0; } - /// getFilename - Return the presumed filename of this location. This can be - /// affected by #line etc. + /// \brief Return the presumed filename of this location. + /// + /// This can be affected by \#line etc. const char *getFilename() const { return Filename; } - /// getLine - Return the presumed line number of this location. This can be - /// affected by #line etc. + /// \brief Return the presumed line number of this location. + /// + /// This can be affected by \#line etc. unsigned getLine() const { return Line; } - /// getColumn - Return the presumed column number of this location. This can - /// not be affected by #line, but is packaged here for convenience. + /// \brief Return the presumed column number of this location. + /// + /// This cannot be affected by \#line, but is packaged here for convenience. unsigned getColumn() const { return Col; } - /// getIncludeLoc - Return the presumed include location of this location. + /// \brief Return the presumed include location of this location. + /// /// This can be affected by GNU linemarker directives. SourceLocation getIncludeLoc() const { return IncludeLoc; } }; diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index bcb2d56..32268d7 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -6,22 +6,46 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the SourceManager interface. -// +/// +/// \file +/// \brief Defines the SourceManager interface. +/// +/// There are three different types of locations in a file: a spelling +/// location, an expansion location, and a presumed location. +/// +/// Given an example of: +/// \code +/// #define min(x, y) x < y ? x : y +/// \endcode +/// +/// and then later on a use of min: +/// \code +/// #line 17 +/// return min(a, b); +/// \endcode +/// +/// The expansion location is the line in the source code where the macro +/// was expanded (the return statement), the spelling location is the +/// location in the source where the macro was originally defined, +/// and the presumed location is where the line directive states that +/// the line is 17, or any other line. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_SOURCEMANAGER_H #define LLVM_CLANG_SOURCEMANAGER_H #include "clang/Basic/LLVM.h" +#include "clang/Basic/FileManager.h" #include "clang/Basic/SourceLocation.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/DataTypes.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/Support/MemoryBuffer.h" #include <map> #include <vector> @@ -38,38 +62,25 @@ class LangOptions; class ASTWriter; class ASTReader; -/// There are three different types of locations in a file: a spelling -/// location, an expansion location, and a presumed location. -/// -/// Given an example of: -/// #define min(x, y) x < y ? x : y -/// -/// and then later on a use of min: -/// #line 17 -/// return min(a, b); -/// -/// The expansion location is the line in the source code where the macro -/// was expanded (the return statement), the spelling location is the -/// location in the source where the macro was originally defined, -/// and the presumed location is where the line directive states that -/// the line is 17, or any other line. - -/// SrcMgr - Public enums and private classes that are part of the +/// \namespace +/// \brief Public enums and private classes that are part of the /// SourceManager implementation. /// namespace SrcMgr { - /// CharacteristicKind - This is used to represent whether a file or directory - /// holds normal user code, system code, or system code which is implicitly - /// 'extern "C"' in C++ mode. Entire directories can be tagged with this - /// (this is maintained by DirectoryLookup and friends) as can specific - /// FileInfos when a #pragma system_header is seen or various other cases. + /// \brief Indicates whether a file or directory holds normal user code, + /// system code, or system code which is implicitly 'extern "C"' in C++ mode. + /// + /// Entire directories can be tagged with this (this is maintained by + /// DirectoryLookup and friends) as can specific FileInfos when a \#pragma + /// system_header is seen or in various other cases. /// enum CharacteristicKind { C_User, C_System, C_ExternCSystem }; - /// ContentCache - One instance of this struct is kept for every file - /// loaded or used. This object owns the MemoryBuffer object. + /// \brief One instance of this struct is kept for every file loaded or used. + //// + /// This object owns the MemoryBuffer object. class ContentCache { enum CCFlags { /// \brief Whether the buffer is invalid. @@ -78,30 +89,37 @@ namespace SrcMgr { DoNotFreeFlag = 0x02 }; - /// Buffer - The actual buffer containing the characters from the input - /// file. This is owned by the ContentCache object. - /// The bits indicate indicates whether the buffer is invalid. + /// \brief The actual buffer containing the characters from the input + /// file. + /// + /// This is owned by the ContentCache object. The bits indicate + /// whether the buffer is invalid. mutable llvm::PointerIntPair<const llvm::MemoryBuffer *, 2> Buffer; public: - /// Reference to the file entry representing this ContentCache. + /// \brief Reference to the file entry representing this ContentCache. + /// /// This reference does not own the FileEntry object. - /// It is possible for this to be NULL if - /// the ContentCache encapsulates an imaginary text buffer. + /// + /// It is possible for this to be NULL if the ContentCache encapsulates + /// an imaginary text buffer. const FileEntry *OrigEntry; /// \brief References the file which the contents were actually loaded from. + /// /// Can be different from 'Entry' if we overridden the contents of one file /// with the contents of another file. const FileEntry *ContentsEntry; - /// SourceLineCache - A bump pointer allocated array of offsets for each - /// source line. This is lazily computed. This is owned by the - /// SourceManager BumpPointerAllocator object. + /// \brief A bump pointer allocated array of offsets for each source line. + /// + /// This is lazily computed. This is owned by the SourceManager + /// BumpPointerAllocator object. unsigned *SourceLineCache; - /// NumLines - The number of lines in this ContentCache. This is only valid - /// if SourceLineCache is non-null. + /// \brief The number of lines in this ContentCache. + /// + /// This is only valid if SourceLineCache is non-null. unsigned NumLines : 31; /// \brief Indicates whether the buffer itself was provided to override @@ -110,22 +128,29 @@ namespace SrcMgr { /// When true, the original entry may be a virtual file that does not /// exist. unsigned BufferOverridden : 1; + + /// \brief True if this content cache was initially created for a source + /// file considered as a system one. + unsigned IsSystemFile : 1; ContentCache(const FileEntry *Ent = 0) : Buffer(0, false), OrigEntry(Ent), ContentsEntry(Ent), - SourceLineCache(0), NumLines(0), BufferOverridden(false) {} + SourceLineCache(0), NumLines(0), BufferOverridden(false), + IsSystemFile(false) {} ContentCache(const FileEntry *Ent, const FileEntry *contentEnt) : Buffer(0, false), OrigEntry(Ent), ContentsEntry(contentEnt), - SourceLineCache(0), NumLines(0), BufferOverridden(false) {} + SourceLineCache(0), NumLines(0), BufferOverridden(false), + IsSystemFile(false) {} ~ContentCache(); /// The copy ctor does not allow copies where source object has either - /// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory - /// is not transferred, so this is a logical error. + /// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory + /// is not transferred, so this is a logical error. ContentCache(const ContentCache &RHS) - : Buffer(0, false), SourceLineCache(0), BufferOverridden(false) + : Buffer(0, false), SourceLineCache(0), BufferOverridden(false), + IsSystemFile(false) { OrigEntry = RHS.OrigEntry; ContentsEntry = RHS.ContentsEntry; @@ -136,13 +161,13 @@ namespace SrcMgr { NumLines = RHS.NumLines; } - /// getBuffer - Returns the memory buffer for the associated content. + /// \brief Returns the memory buffer for the associated content. /// /// \param Diag Object through which diagnostics will be emitted if the - /// buffer cannot be retrieved. + /// buffer cannot be retrieved. /// /// \param Loc If specified, is the location that invalid file diagnostics - /// will be emitted at. + /// will be emitted at. /// /// \param Invalid If non-NULL, will be set \c true if an error occurred. const llvm::MemoryBuffer *getBuffer(DiagnosticsEngine &Diag, @@ -150,15 +175,18 @@ namespace SrcMgr { SourceLocation Loc = SourceLocation(), bool *Invalid = 0) const; - /// getSize - Returns the size of the content encapsulated by this - /// ContentCache. This can be the size of the source file or the size of an - /// arbitrary scratch buffer. If the ContentCache encapsulates a source - /// file this size is retrieved from the file's FileEntry. + /// \brief Returns the size of the content encapsulated by this + /// ContentCache. + /// + /// This can be the size of the source file or the size of an + /// arbitrary scratch buffer. If the ContentCache encapsulates a source + /// file this size is retrieved from the file's FileEntry. unsigned getSize() const; - /// getSizeBytesMapped - Returns the number of bytes actually mapped for - /// this ContentCache. This can be 0 if the MemBuffer was not actually - /// expanded. + /// \brief Returns the number of bytes actually mapped for this + /// ContentCache. + /// + /// This can be 0 if the MemBuffer was not actually expanded. unsigned getSizeBytesMapped() const; /// Returns the kind of memory used to back the memory buffer for @@ -196,35 +224,37 @@ namespace SrcMgr { ContentCache &operator=(const ContentCache& RHS); }; - /// FileInfo - Information about a FileID, basically just the logical file + /// \brief Information about a FileID, basically just the logical file /// that it represents and include stack information. /// /// Each FileInfo has include stack information, indicating where it came - /// from. This information encodes the #include chain that a token was + /// from. This information encodes the \#include chain that a token was /// expanded from. The main include file has an invalid IncludeLoc. /// /// FileInfos contain a "ContentCache *", with the contents of the file. /// class FileInfo { - /// IncludeLoc - The location of the #include that brought in this file. - /// This is an invalid SLOC for the main file (top of the #include chain). + /// \brief The location of the \#include that brought in this file. + /// + /// This is an invalid SLOC for the main file (top of the \#include chain). unsigned IncludeLoc; // Really a SourceLocation /// \brief Number of FileIDs (files and macros) that were created during - /// preprocessing of this #include, including this SLocEntry. + /// preprocessing of this \#include, including this SLocEntry. + /// /// Zero means the preprocessor didn't provide such info for this SLocEntry. unsigned NumCreatedFIDs; - /// Data - This contains the ContentCache* and the bits indicating the - /// characteristic of the file and whether it has #line info, all bitmangled - /// together. + /// \brief Contains the ContentCache* and the bits indicating the + /// characteristic of the file and whether it has \#line info, all + /// bitmangled together. uintptr_t Data; friend class clang::SourceManager; friend class clang::ASTWriter; friend class clang::ASTReader; public: - /// get - Return a FileInfo object. + /// \brief Return a FileInfo object. static FileInfo get(SourceLocation IL, const ContentCache *Con, CharacteristicKind FileCharacter) { FileInfo X; @@ -244,36 +274,35 @@ namespace SrcMgr { return reinterpret_cast<const ContentCache*>(Data & ~7UL); } - /// getCharacteristic - Return whether this is a system header or not. + /// \brief Return whether this is a system header or not. CharacteristicKind getFileCharacteristic() const { return (CharacteristicKind)(Data & 3); } - /// hasLineDirectives - Return true if this FileID has #line directives in - /// it. + /// \brief Return true if this FileID has \#line directives in it. bool hasLineDirectives() const { return (Data & 4) != 0; } - /// setHasLineDirectives - Set the flag that indicates that this FileID has + /// \brief Set the flag that indicates that this FileID has /// line table entries associated with it. void setHasLineDirectives() { Data |= 4; } }; - /// ExpansionInfo - Each ExpansionInfo encodes the expansion location - where + /// \brief Each ExpansionInfo encodes the expansion location - where /// the token was ultimately expanded, and the SpellingLoc - where the actual /// character data for the token came from. class ExpansionInfo { // Really these are all SourceLocations. - /// SpellingLoc - Where the spelling for the token can be found. + /// \brief Where the spelling for the token can be found. unsigned SpellingLoc; - /// ExpansionLocStart/ExpansionLocEnd - In a macro expansion, these + /// In a macro expansion, ExpansionLocStart and ExpansionLocEnd /// indicate the start and end of the expansion. In object-like macros, - /// these will be the same. In a function-like macro expansion, the start + /// they will be the same. In a function-like macro expansion, the start /// will be the identifier and the end will be the ')'. Finally, in - /// macro-argument instantitions, the end will be 'SourceLocation()', an + /// macro-argument instantiations, the end will be 'SourceLocation()', an /// invalid location. unsigned ExpansionLocStart, ExpansionLocEnd; @@ -305,11 +334,12 @@ namespace SrcMgr { getExpansionLocStart() != getExpansionLocEnd(); } - /// create - Return a ExpansionInfo for an expansion. Start and End specify - /// the expansion range (where the macro is expanded), and SpellingLoc - /// specifies the spelling location (where the characters from the token - /// come from). All three can refer to normal File SLocs or expansion - /// locations. + /// \brief Return a ExpansionInfo for an expansion. + /// + /// Start and End specify the expansion range (where the macro is + /// expanded), and SpellingLoc specifies the spelling location (where + /// the characters from the token come from). All three can refer to + /// normal File SLocs or expansion locations. static ExpansionInfo create(SourceLocation SpellingLoc, SourceLocation Start, SourceLocation End) { ExpansionInfo X; @@ -319,14 +349,15 @@ namespace SrcMgr { return X; } - /// createForMacroArg - Return a special ExpansionInfo for the expansion of - /// a macro argument into a function-like macro's body. ExpansionLoc - /// specifies the expansion location (where the macro is expanded). This - /// doesn't need to be a range because a macro is always expanded at - /// a macro parameter reference, and macro parameters are always exactly - /// one token. SpellingLoc specifies the spelling location (where the - /// characters from the token come from). ExpansionLoc and SpellingLoc can - /// both refer to normal File SLocs or expansion locations. + /// \brief Return a special ExpansionInfo for the expansion of + /// a macro argument into a function-like macro's body. + /// + /// ExpansionLoc specifies the expansion location (where the macro is + /// expanded). This doesn't need to be a range because a macro is always + /// expanded at a macro parameter reference, and macro parameters are + /// always exactly one token. SpellingLoc specifies the spelling location + /// (where the characters from the token come from). ExpansionLoc and + /// SpellingLoc can both refer to normal File SLocs or expansion locations. /// /// Given the code: /// \code @@ -335,7 +366,7 @@ namespace SrcMgr { /// \endcode /// /// When expanding '\c F(42)', the '\c x' would call this with an - /// SpellingLoc pointing at '\c 42' anad an ExpansionLoc pointing at its + /// SpellingLoc pointing at '\c 42' and an ExpansionLoc pointing at its /// location in the definition of '\c F'. static ExpansionInfo createForMacroArg(SourceLocation SpellingLoc, SourceLocation ExpansionLoc) { @@ -346,9 +377,10 @@ namespace SrcMgr { } }; - /// SLocEntry - This is a discriminated union of FileInfo and - /// ExpansionInfo. SourceManager keeps an array of these objects, and - /// they are uniquely identified by the FileID datatype. + /// \brief This is a discriminated union of FileInfo and ExpansionInfo. + /// + /// SourceManager keeps an array of these objects, and they are uniquely + /// identified by the FileID datatype. class SLocEntry { unsigned Offset; // low bit is set for expansion info. union { @@ -401,37 +433,43 @@ public: }; -/// IsBeforeInTranslationUnitCache - This class holds the cache used by -/// isBeforeInTranslationUnit. The cache structure is complex enough to be -/// worth breaking out of SourceManager. +/// \brief Holds the cache used by isBeforeInTranslationUnit. +/// +/// The cache structure is complex enough to be worth breaking out of +/// SourceManager. class IsBeforeInTranslationUnitCache { - /// L/R QueryFID - These are the FID's of the cached query. If these match up - /// with a subsequent query, the result can be reused. + /// \brief The FileID's of the cached query. + /// + /// If these match up with a subsequent query, the result can be reused. FileID LQueryFID, RQueryFID; - /// \brief True if LQueryFID was created before RQueryFID. This is used - /// to compare macro expansion locations. + /// \brief True if LQueryFID was created before RQueryFID. + /// + /// This is used to compare macro expansion locations. bool IsLQFIDBeforeRQFID; - /// CommonFID - This is the file found in common between the two #include - /// traces. It is the nearest common ancestor of the #include tree. + /// \brief The file found in common between the two \#include traces, i.e., + /// the nearest common ancestor of the \#include tree. FileID CommonFID; - /// L/R CommonOffset - This is the offset of the previous query in CommonFID. - /// Usually, this represents the location of the #include for QueryFID, but if - /// LQueryFID is a parent of RQueryFID (or vise versa) then these can be a + /// \brief The offset of the previous query in CommonFID. + /// + /// Usually, this represents the location of the \#include for QueryFID, but + /// if LQueryFID is a parent of RQueryFID (or vice versa) then these can be a /// random token in the parent. unsigned LCommonOffset, RCommonOffset; public: - /// isCacheValid - Return true if the currently cached values match up with - /// the specified LHS/RHS query. If not, we can't use the cache. + /// \brief Return true if the currently cached values match up with + /// the specified LHS/RHS query. + /// + /// If not, we can't use the cache. bool isCacheValid(FileID LHS, FileID RHS) const { return LQueryFID == LHS && RQueryFID == RHS; } - /// getCachedResult - If the cache is valid, compute the result given the - /// specified offsets in the LHS/RHS FID's. + /// \brief If the cache is valid, compute the result given the + /// specified offsets in the LHS/RHS FileID's. bool getCachedResult(unsigned LOffset, unsigned ROffset) const { // If one of the query files is the common file, use the offset. Otherwise, // use the #include loc in the common file. @@ -449,7 +487,7 @@ public: return LOffset < ROffset; } - // Set up a new query. + /// \brief Set up a new query. void setQueryFIDs(FileID LHS, FileID RHS, bool isLFIDBeforeRFID) { assert(LHS != RHS); LQueryFID = LHS; @@ -474,7 +512,7 @@ public: /// \brief This class handles loading and caching of source files into memory. /// /// This object owns the MemoryBuffer objects for all of the loaded -/// files and assigns unique FileID's for each unique #include chain. +/// files and assigns unique FileID's for each unique \#include chain. /// /// The SourceManager can be queried for information about SourceLocation /// objects, turning them into either spelling or expansion locations. Spelling @@ -491,8 +529,10 @@ class SourceManager : public RefCountedBase<SourceManager> { mutable llvm::BumpPtrAllocator ContentCacheAlloc; - /// FileInfos - Memoized information about all of the files tracked by this - /// SourceManager. This set allows us to merge ContentCache entries based + /// \brief Memoized information about all of the files tracked by this + /// SourceManager. + /// + /// This map allows us to merge ContentCache entries based /// on their FileEntry*. All ContentCache objects will thus have unique, /// non-null, FileEntry pointers. llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> FileInfos; @@ -501,11 +541,31 @@ class SourceManager : public RefCountedBase<SourceManager> { /// files, should report the original file name. Defaults to true. bool OverridenFilesKeepOriginalName; - /// \brief Files that have been overriden with the contents from another file. - llvm::DenseMap<const FileEntry *, const FileEntry *> OverriddenFiles; + /// \brief True if non-system source files should be treated as volatile + /// (likely to change while trying to use them). Defaults to false. + bool UserFilesAreVolatile; + + struct OverriddenFilesInfoTy { + /// \brief Files that have been overriden with the contents from another + /// file. + llvm::DenseMap<const FileEntry *, const FileEntry *> OverriddenFiles; + /// \brief Files that were overridden with a memory buffer. + llvm::DenseSet<const FileEntry *> OverriddenFilesWithBuffer; + }; + + /// \brief Lazily create the object keeping overridden files info, since + /// it is uncommonly used. + OwningPtr<OverriddenFilesInfoTy> OverriddenFilesInfo; + + OverriddenFilesInfoTy &getOverriddenFilesInfo() { + if (!OverriddenFilesInfo) + OverriddenFilesInfo.reset(new OverriddenFilesInfoTy); + return *OverriddenFilesInfo; + } - /// MemBufferInfos - Information about various memory buffers that we have - /// read in. All FileEntry* within the stored ContentCache objects are NULL, + /// \brief Information about various memory buffers that we have read in. + /// + /// All FileEntry* within the stored ContentCache objects are NULL, /// as they do not refer to a file. std::vector<SrcMgr::ContentCache*> MemBufferInfos; @@ -545,23 +605,25 @@ class SourceManager : public RefCountedBase<SourceManager> { /// \brief An external source for source location entries. ExternalSLocEntrySource *ExternalSLocEntries; - /// LastFileIDLookup - This is a one-entry cache to speed up getFileID. + /// \brief A one-entry cache to speed up getFileID. + /// /// LastFileIDLookup records the last FileID looked up or created, because it /// is very common to look up many tokens from the same file. mutable FileID LastFileIDLookup; - /// LineTable - This holds information for #line directives. It is referenced - /// by indices from SLocEntryTable. + /// \brief Holds information for \#line directives. + /// + /// This is referenced by indices from SLocEntryTable. LineTableInfo *LineTable; - /// LastLineNo - These ivars serve as a cache used in the getLineNumber + /// \brief These ivars serve as a cache used in the getLineNumber /// method which is used to speedup getLineNumber calls to nearby locations. mutable FileID LastLineNoFileIDQuery; mutable SrcMgr::ContentCache *LastLineNoContentCache; mutable unsigned LastLineNoFilePos; mutable unsigned LastLineNoResult; - /// MainFileID - The file ID for the main source file of the translation unit. + /// \brief The file ID for the main source file of the translation unit. FileID MainFileID; /// \brief The file ID for the precompiled preamble there is one. @@ -588,7 +650,8 @@ class SourceManager : public RefCountedBase<SourceManager> { explicit SourceManager(const SourceManager&); void operator=(const SourceManager&); public: - SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr); + SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr, + bool UserFilesAreVolatile = false); ~SourceManager(); void clearIDTables(); @@ -603,9 +666,15 @@ public: OverridenFilesKeepOriginalName = value; } - /// createMainFileIDForMembuffer - Create the FileID for a memory buffer - /// that will represent the FileID for the main source. One example - /// of when this would be used is when the main source is read from STDIN. + /// \brief True if non-system source files should be treated as volatile + /// (likely to change while trying to use them). + bool userFilesAreVolatile() const { return UserFilesAreVolatile; } + + /// \brief Create the FileID for a memory buffer that will represent the + /// FileID for the main source. + /// + /// One example of when this would be used is when the main source is read + /// from STDIN. FileID createMainFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer) { assert(MainFileID.isInvalid() && "MainFileID already set!"); MainFileID = createFileIDForMemBuffer(Buffer); @@ -616,10 +685,10 @@ public: // MainFileID creation and querying methods. //===--------------------------------------------------------------------===// - /// getMainFileID - Returns the FileID of the main source file. + /// \brief Returns the FileID of the main source file. FileID getMainFileID() const { return MainFileID; } - /// createMainFileID - Create the FileID for the main source file. + /// \brief Create the FileID for the main source file. FileID createMainFileID(const FileEntry *SourceFile, SrcMgr::CharacteristicKind Kind = SrcMgr::C_User) { assert(MainFileID.isInvalid() && "MainFileID already set!"); @@ -646,20 +715,24 @@ public: // Methods to create new FileID's and macro expansions. //===--------------------------------------------------------------------===// - /// createFileID - Create a new FileID that represents the specified file - /// being #included from the specified IncludePosition. This translates NULL - /// into standard input. + /// \brief Create a new FileID that represents the specified file + /// being \#included from the specified IncludePosition. + /// + /// This translates NULL into standard input. FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID = 0, unsigned LoadedOffset = 0) { - const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile); + const SrcMgr::ContentCache * + IR = getOrCreateContentCache(SourceFile, + /*isSystemFile=*/FileCharacter != SrcMgr::C_User); assert(IR && "getOrCreateContentCache() cannot return NULL"); return createFileID(IR, IncludePos, FileCharacter, LoadedID, LoadedOffset); } - /// createFileIDForMemBuffer - Create a new FileID that represents the - /// specified memory buffer. This does no caching of the buffer and takes - /// ownership of the MemoryBuffer, so only pass a MemoryBuffer to this once. + /// \brief Create a new FileID that represents the specified memory buffer. + /// + /// This does no caching of the buffer and takes ownership of the + /// MemoryBuffer, so only pass a MemoryBuffer to this once. FileID createFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer, int LoadedID = 0, unsigned LoadedOffset = 0, SourceLocation IncludeLoc = SourceLocation()) { @@ -667,7 +740,7 @@ public: SrcMgr::C_User, LoadedID, LoadedOffset); } - /// createMacroArgExpansionLoc - Return a new SourceLocation that encodes the + /// \brief Return a new SourceLocation that encodes the /// fact that a token from SpellingLoc should actually be referenced from /// ExpansionLoc, and that it represents the expansion of a macro argument /// into the function-like macro body. @@ -675,7 +748,7 @@ public: SourceLocation ExpansionLoc, unsigned TokLength); - /// createExpansionLoc - Return a new SourceLocation that encodes the fact + /// \brief Return a new SourceLocation that encodes the fact /// that a token from SpellingLoc should actually be referenced from /// ExpansionLoc. SourceLocation createExpansionLoc(SourceLocation Loc, @@ -706,7 +779,7 @@ public: const llvm::MemoryBuffer *Buffer, bool DoNotFree = false); - /// \brief Override the the given source file with another one. + /// \brief Override the given source file with another one. /// /// \param SourceFile the source file which will be overriden. /// @@ -715,13 +788,32 @@ public: void overrideFileContents(const FileEntry *SourceFile, const FileEntry *NewFile); + /// \brief Returns true if the file contents have been overridden. + bool isFileOverridden(const FileEntry *File) { + if (OverriddenFilesInfo) { + if (OverriddenFilesInfo->OverriddenFilesWithBuffer.count(File)) + return true; + if (OverriddenFilesInfo->OverriddenFiles.find(File) != + OverriddenFilesInfo->OverriddenFiles.end()) + return true; + } + return false; + } + + /// \brief Disable overridding the contents of a file, previously enabled + /// with #overrideFileContents. + /// + /// This should be called before parsing has begun. + void disableFileContentsOverride(const FileEntry *File); + //===--------------------------------------------------------------------===// // FileID manipulation methods. //===--------------------------------------------------------------------===// - /// getBuffer - Return the buffer for the specified FileID. If there is an - /// error opening this buffer the first time, this manufactures a temporary - /// buffer and returns a non-empty error string. + /// \brief Return the buffer for the specified FileID. + /// + /// If there is an error opening this buffer the first time, this + /// manufactures a temporary buffer and returns a non-empty error string. const llvm::MemoryBuffer *getBuffer(FileID FID, SourceLocation Loc, bool *Invalid = 0) const { bool MyInvalid = false; @@ -752,7 +844,7 @@ public: Invalid); } - /// getFileEntryForID - Returns the FileEntry record for the provided FileID. + /// \brief Returns the FileEntry record for the provided FileID. const FileEntry *getFileEntryForID(FileID FID) const { bool MyInvalid = false; const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid); @@ -765,7 +857,7 @@ public: return Content->OrigEntry; } - /// Returns the FileEntry record for the provided SLocEntry. + /// \brief Returns the FileEntry record for the provided SLocEntry. const FileEntry *getFileEntryForSLocEntry(const SrcMgr::SLocEntry &sloc) const { const SrcMgr::ContentCache *Content = sloc.getFile().getContentCache(); @@ -774,7 +866,7 @@ public: return Content->OrigEntry; } - /// getBufferData - Return a StringRef to the source buffer data for the + /// \brief Return a StringRef to the source buffer data for the /// specified FileID. /// /// \param FID The file ID whose contents will be returned. @@ -808,10 +900,11 @@ public: // SourceLocation manipulation methods. //===--------------------------------------------------------------------===// - /// getFileID - Return the FileID for a SourceLocation. This is a very - /// hot method that is used for all SourceManager queries that start with a - /// SourceLocation object. It is responsible for finding the entry in - /// SLocEntryTable which contains the specified location. + /// \brief Return the FileID for a SourceLocation. + /// + /// This is a very hot method that is used for all SourceManager queries + /// that start with a SourceLocation object. It is responsible for finding + /// the entry in SLocEntryTable which contains the specified location. /// FileID getFileID(SourceLocation SpellingLoc) const { unsigned SLocOffset = SpellingLoc.getOffset(); @@ -823,8 +916,15 @@ public: return getFileIDSlow(SLocOffset); } - /// getLocForStartOfFile - Return the source location corresponding to the - /// first byte of the specified file. + /// \brief Return the filename of the file containing a SourceLocation. + StringRef getFilename(SourceLocation SpellingLoc) const { + if (const FileEntry *F = getFileEntryForID(getFileID(SpellingLoc))) + return F->getName(); + return StringRef(); + } + + /// \brief Return the source location corresponding to the first byte of + /// the specified file. SourceLocation getLocForStartOfFile(FileID FID) const { bool Invalid = false; const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); @@ -847,7 +947,7 @@ public: return SourceLocation::getFileLoc(FileOffset + getFileIDSize(FID) - 1); } - /// \brief Returns the include location if \p FID is a #include'd file + /// \brief Returns the include location if \p FID is a \#include'd file /// otherwise it returns an invalid location. SourceLocation getIncludeLoc(FileID FID) const { bool Invalid = false; @@ -858,7 +958,7 @@ public: return Entry.getFile().getIncludeLoc(); } - /// getExpansionLoc - Given a SourceLocation object, return the expansion + /// \brief Given a SourceLocation object \p Loc, return the expansion /// location referenced by the ID. SourceLocation getExpansionLoc(SourceLocation Loc) const { // Handle the non-mapped case inline, defer to out of line code to handle @@ -875,20 +975,24 @@ public: return getFileLocSlowCase(Loc); } - /// getImmediateExpansionRange - Loc is required to be an expansion location. - /// Return the start/end of the expansion information. + /// \brief Return the start/end of the expansion information for an + /// expansion location. + /// + /// \pre \p Loc is required to be an expansion location. std::pair<SourceLocation,SourceLocation> getImmediateExpansionRange(SourceLocation Loc) const; - /// getExpansionRange - Given a SourceLocation object, return the range of + /// \brief Given a SourceLocation object, return the range of /// tokens covered by the expansion the ultimate file. std::pair<SourceLocation,SourceLocation> getExpansionRange(SourceLocation Loc) const; - /// getSpellingLoc - Given a SourceLocation object, return the spelling - /// location referenced by the ID. This is the place where the characters - /// that make up the lexed token can be found. + /// \brief Given a SourceLocation object, return the spelling + /// location referenced by the ID. + /// + /// This is the place where the characters that make up the lexed token + /// can be found. SourceLocation getSpellingLoc(SourceLocation Loc) const { // Handle the non-mapped case inline, defer to out of line code to handle // expansions. @@ -896,15 +1000,18 @@ public: return getSpellingLocSlowCase(Loc); } - /// getImmediateSpellingLoc - Given a SourceLocation object, return the - /// spelling location referenced by the ID. This is the first level down - /// towards the place where the characters that make up the lexed token can be - /// found. This should not generally be used by clients. + /// \brief Given a SourceLocation object, return the spelling location + /// referenced by the ID. + /// + /// This is the first level down towards the place where the characters + /// that make up the lexed token can be found. This should not generally + /// be used by clients. SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const; - /// getDecomposedLoc - Decompose the specified location into a raw FileID + - /// Offset pair. The first element is the FileID, the second is the - /// offset from the start of the buffer of the location. + /// \brief Decompose the specified location into a raw FileID + Offset pair. + /// + /// The first element is the FileID, the second is the offset from the + /// start of the buffer of the location. std::pair<FileID, unsigned> getDecomposedLoc(SourceLocation Loc) const { FileID FID = getFileID(Loc); bool Invalid = false; @@ -914,9 +1021,10 @@ public: return std::make_pair(FID, Loc.getOffset()-E.getOffset()); } - /// getDecomposedExpansionLoc - Decompose the specified location into a raw - /// FileID + Offset pair. If the location is an expansion record, walk - /// through it until we find the final location expanded. + /// \brief Decompose the specified location into a raw FileID + Offset pair. + /// + /// If the location is an expansion record, walk through it until we find + /// the final location expanded. std::pair<FileID, unsigned> getDecomposedExpansionLoc(SourceLocation Loc) const { FileID FID = getFileID(Loc); @@ -932,9 +1040,10 @@ public: return getDecomposedExpansionLocSlowCase(E); } - /// getDecomposedSpellingLoc - Decompose the specified location into a raw - /// FileID + Offset pair. If the location is an expansion record, walk - /// through it until we find its spelling record. + /// \brief Decompose the specified location into a raw FileID + Offset pair. + /// + /// If the location is an expansion record, walk through it until we find + /// its spelling record. std::pair<FileID, unsigned> getDecomposedSpellingLoc(SourceLocation Loc) const { FileID FID = getFileID(Loc); @@ -949,22 +1058,25 @@ public: return getDecomposedSpellingLocSlowCase(E, Offset); } - /// getFileOffset - This method returns the offset from the start - /// of the file that the specified SourceLocation represents. This is not very - /// meaningful for a macro ID. + /// \brief Returns the offset from the start of the file that the + /// specified SourceLocation represents. + /// + /// This is not very meaningful for a macro ID. unsigned getFileOffset(SourceLocation SpellingLoc) const { return getDecomposedLoc(SpellingLoc).second; } - /// isMacroArgExpansion - This method tests whether the given source location - /// represents a macro argument's expansion into the function-like macro - /// definition. Such source locations only appear inside of the expansion + /// \brief Tests whether the given source location represents a macro + /// argument's expansion into the function-like macro definition. + /// + /// Such source locations only appear inside of the expansion /// locations representing where a particular function-like macro was /// expanded. bool isMacroArgExpansion(SourceLocation Loc) const; /// \brief Returns true if \p Loc is inside the [\p Start, +\p Length) /// chunk of the source location address space. + /// /// If it's true and \p RelativeOffset is non-null, it will be set to the /// relative offset of \p Loc inside the chunk. bool isInSLocAddrSpace(SourceLocation Loc, @@ -988,9 +1100,10 @@ public: } /// \brief Return true if both \p LHS and \p RHS are in the local source - /// location address space or the loaded one. If it's true and \p - /// RelativeOffset is non-null, it will be set to the offset of \p RHS - /// relative to \p LHS. + /// location address space or the loaded one. + /// + /// If it's true and \p RelativeOffset is non-null, it will be set to the + /// offset of \p RHS relative to \p LHS. bool isInSameSLocAddrSpace(SourceLocation LHS, SourceLocation RHS, int *RelativeOffset) const { unsigned LHSOffs = LHS.getOffset(), RHSOffs = RHS.getOffset(); @@ -1010,13 +1123,14 @@ public: // Queries about the code at a SourceLocation. //===--------------------------------------------------------------------===// - /// getCharacterData - Return a pointer to the start of the specified location + /// \brief Return a pointer to the start of the specified location /// in the appropriate spelling MemoryBuffer. /// /// \param Invalid If non-NULL, will be set \c true if an error occurs. const char *getCharacterData(SourceLocation SL, bool *Invalid = 0) const; - /// getColumnNumber - Return the column # for the specified file position. + /// \brief Return the column # for the specified file position. + /// /// This is significantly cheaper to compute than the line number. This /// returns zero if the column number isn't known. This may only be called /// on a file sloc, so you must choose a spelling or expansion location @@ -1029,34 +1143,41 @@ public: unsigned getPresumedColumnNumber(SourceLocation Loc, bool *Invalid = 0) const; - /// getLineNumber - Given a SourceLocation, return the spelling line number - /// for the position indicated. This requires building and caching a table of - /// line offsets for the MemoryBuffer, so this is not cheap: use only when - /// about to emit a diagnostic. + /// \brief Given a SourceLocation, return the spelling line number + /// for the position indicated. + /// + /// This requires building and caching a table of line offsets for the + /// MemoryBuffer, so this is not cheap: use only when about to emit a + /// diagnostic. unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid = 0) const; unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid = 0) const; unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid = 0) const; unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid = 0) const; - /// Return the filename or buffer identifier of the buffer the location is in. - /// Note that this name does not respect #line directives. Use getPresumedLoc - /// for normal clients. + /// \brief Return the filename or buffer identifier of the buffer the + /// location is in. + /// + /// Note that this name does not respect \#line directives. Use + /// getPresumedLoc for normal clients. const char *getBufferName(SourceLocation Loc, bool *Invalid = 0) const; - /// getFileCharacteristic - return the file characteristic of the specified - /// source location, indicating whether this is a normal file, a system + /// \brief Return the file characteristic of the specified source + /// location, indicating whether this is a normal file, a system /// header, or an "implicit extern C" system header. /// /// This state can be modified with flags on GNU linemarker directives like: + /// \code /// # 4 "foo.h" 3 + /// \endcode /// which changes all source locations in the current file after that to be /// considered to be from a system header. SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const; - /// getPresumedLoc - This method returns the "presumed" location of a - /// SourceLocation specifies. A "presumed location" can be modified by #line - /// or GNU line marker directives. This provides a view on the data that a - /// user should see in diagnostics, for example. + /// \brief Returns the "presumed" location of a SourceLocation specifies. + /// + /// A "presumed location" can be modified by \#line or GNU line marker + /// directives. This provides a view on the data that a user should see + /// in diagnostics, for example. /// /// Note that a presumed location is always given as the expansion point of /// an expansion location, not at the spelling location. @@ -1067,25 +1188,23 @@ public: /// presumed location. PresumedLoc getPresumedLoc(SourceLocation Loc) const; - /// isFromSameFile - Returns true if both SourceLocations correspond to - /// the same file. + /// \brief Returns true if both SourceLocations correspond to the same file. bool isFromSameFile(SourceLocation Loc1, SourceLocation Loc2) const { return getFileID(Loc1) == getFileID(Loc2); } - /// isFromMainFile - Returns true if the file of provided SourceLocation is - /// the main file. + /// \brief Returns true if the file of provided SourceLocation is the main + /// file. bool isFromMainFile(SourceLocation Loc) const { return getFileID(Loc) == getMainFileID(); } - /// isInSystemHeader - Returns if a SourceLocation is in a system header. + /// \brief Returns if a SourceLocation is in a system header. bool isInSystemHeader(SourceLocation Loc) const { return getFileCharacteristic(Loc) != SrcMgr::C_User; } - /// isInExternCSystemHeader - Returns if a SourceLocation is in an "extern C" - /// system header. + /// \brief Returns if a SourceLocation is in an "extern C" system header. bool isInExternCSystemHeader(SourceLocation Loc) const { return getFileCharacteristic(Loc) == SrcMgr::C_ExternCSystem; } @@ -1117,13 +1236,14 @@ public: // Line Table Manipulation Routines //===--------------------------------------------------------------------===// - /// getLineTableFilenameID - Return the uniqued ID for the specified filename. + /// \brief Return the uniqued ID for the specified filename. /// unsigned getLineTableFilenameID(StringRef Str); - /// AddLineNote - Add a line note to the line table for the FileID and offset - /// specified by Loc. If FilenameID is -1, it is considered to be - /// unspecified. + /// \brief Add a line note to the line table for the FileID and offset + /// specified by Loc. + /// + /// If FilenameID is -1, it is considered to be unspecified. void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID); void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID, bool IsFileEntry, bool IsFileExit, @@ -1139,7 +1259,7 @@ public: // Queries for performance analysis. //===--------------------------------------------------------------------===// - /// Return the total amount of physical memory allocated by the + /// \brief Return the total amount of physical memory allocated by the /// ContentCache allocator. size_t getContentCacheSize() const { return ContentCacheAlloc.getTotalMemory(); @@ -1153,12 +1273,12 @@ public: : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {} }; - /// Return the amount of memory used by memory buffers, breaking down + /// \brief Return the amount of memory used by memory buffers, breaking down /// by heap-backed versus mmap'ed memory. MemoryBufferSizes getMemoryBufferSizes() const; - // Return the amount of memory used for various side tables and - // data structures in the SourceManager. + /// \brief Return the amount of memory used for various side tables and + /// data structures in the SourceManager. size_t getDataStructureSizes() const; //===--------------------------------------------------------------------===// @@ -1199,19 +1319,6 @@ public: /// \returns true if LHS source location comes before RHS, false otherwise. bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const; - /// \brief Comparison function class. - class LocBeforeThanCompare : public std::binary_function<SourceLocation, - SourceLocation, bool> { - SourceManager &SM; - - public: - explicit LocBeforeThanCompare(SourceManager &SM) : SM(SM) { } - - bool operator()(SourceLocation LHS, SourceLocation RHS) const { - return SM.isBeforeInTranslationUnit(LHS, RHS); - } - }; - /// \brief Determines the order of 2 source locations in the "source location /// address space". bool isBeforeInSLocAddrSpace(SourceLocation LHS, SourceLocation RHS) const { @@ -1241,7 +1348,7 @@ public: return FileInfos.find(File) != FileInfos.end(); } - /// PrintStats - Print statistics to stderr. + /// \brief Print statistics to stderr. /// void PrintStats() const; @@ -1313,6 +1420,65 @@ public: return !isLoadedFileID(FID); } + /// Get a presumed location suitable for displaying in a diagnostic message, + /// taking into account macro arguments and expansions. + PresumedLoc getPresumedLocForDisplay(SourceLocation Loc) const { + // This is a condensed form of the algorithm used by emitCaretDiagnostic to + // walk to the top of the macro call stack. + while (Loc.isMacroID()) { + Loc = skipToMacroArgExpansion(Loc); + Loc = getImmediateMacroCallerLoc(Loc); + } + + return getPresumedLoc(Loc); + } + + /// Look through spelling locations for a macro argument expansion, and if + /// found skip to it so that we can trace the argument rather than the macros + /// in which that argument is used. If no macro argument expansion is found, + /// don't skip anything and return the starting location. + SourceLocation skipToMacroArgExpansion(SourceLocation StartLoc) const { + for (SourceLocation L = StartLoc; L.isMacroID(); + L = getImmediateSpellingLoc(L)) { + if (isMacroArgExpansion(L)) + return L; + } + // Otherwise just return initial location, there's nothing to skip. + return StartLoc; + } + + /// Gets the location of the immediate macro caller, one level up the stack + /// toward the initial macro typed into the source. + SourceLocation getImmediateMacroCallerLoc(SourceLocation Loc) const { + if (!Loc.isMacroID()) return Loc; + + // When we have the location of (part of) an expanded parameter, its + // spelling location points to the argument as typed into the macro call, + // and therefore is used to locate the macro caller. + if (isMacroArgExpansion(Loc)) + return getImmediateSpellingLoc(Loc); + + // Otherwise, the caller of the macro is located where this macro is + // expanded (while the spelling is part of the macro definition). + return getImmediateExpansionRange(Loc).first; + } + + /// Gets the location of the immediate macro callee, one level down the stack + /// toward the leaf macro. + SourceLocation getImmediateMacroCalleeLoc(SourceLocation Loc) const { + if (!Loc.isMacroID()) return Loc; + + // When we have the location of (part of) an expanded parameter, its + // expansion location points to the unexpanded parameter reference within + // the macro definition (or callee). + if (isMacroArgExpansion(Loc)) + return getImmediateExpansionRange(Loc).first; + + // Otherwise, the callee of the macro is located where this location was + // spelled inside the macro definition. + return getImmediateSpellingLoc(Loc); + } + private: const llvm::MemoryBuffer *getFakeBufferForRecovery() const; const SrcMgr::ContentCache *getFakeContentCacheForRecovery() const; @@ -1332,15 +1498,14 @@ private: return getLoadedSLocEntry(static_cast<unsigned>(-ID - 2), Invalid); } - /// createExpansionLoc - Implements the common elements of storing an - /// expansion info struct into the SLocEntry table and producing a source - /// location that refers to it. + /// Implements the common elements of storing an expansion info struct into + /// the SLocEntry table and producing a source location that refers to it. SourceLocation createExpansionLocImpl(const SrcMgr::ExpansionInfo &Expansion, unsigned TokLength, int LoadedID = 0, unsigned LoadedOffset = 0); - /// isOffsetInFileID - Return true if the specified FileID contains the + /// \brief Return true if the specified FileID contains the /// specified SourceLocation offset. This is a very hot method. inline bool isOffsetInFileID(FileID FID, unsigned SLocOffset) const { const SrcMgr::SLocEntry &Entry = getSLocEntry(FID); @@ -1352,28 +1517,29 @@ private: return true; // If it is the last local entry, then it does if the location is local. - if (static_cast<unsigned>(FID.ID+1) == LocalSLocEntryTable.size()) { + if (FID.ID+1 == static_cast<int>(LocalSLocEntryTable.size())) return SLocOffset < NextLocalOffset; - } // Otherwise, the entry after it has to not include it. This works for both // local and loaded entries. - return SLocOffset < getSLocEntry(FileID::get(FID.ID+1)).getOffset(); + return SLocOffset < getSLocEntryByID(FID.ID+1).getOffset(); } - /// createFileID - Create a new fileID for the specified ContentCache and - /// include position. This works regardless of whether the ContentCache - /// corresponds to a file or some other input source. + /// \brief Create a new fileID for the specified ContentCache and + /// include position. + /// + /// This works regardless of whether the ContentCache corresponds to a + /// file or some other input source. FileID createFileID(const SrcMgr::ContentCache* File, SourceLocation IncludePos, SrcMgr::CharacteristicKind DirCharacter, int LoadedID, unsigned LoadedOffset); const SrcMgr::ContentCache * - getOrCreateContentCache(const FileEntry *SourceFile); + getOrCreateContentCache(const FileEntry *SourceFile, + bool isSystemFile = false); - /// createMemBufferContentCache - Create a new ContentCache for the specified - /// memory buffer. + /// \brief Create a new ContentCache for the specified memory buffer. const SrcMgr::ContentCache* createMemBufferContentCache(const llvm::MemoryBuffer *Buf); @@ -1396,6 +1562,35 @@ private: friend class ASTWriter; }; +/// \brief Comparison function object. +template<typename T> +class BeforeThanCompare; + +/// \brief Compare two source locations. +template<> +class BeforeThanCompare<SourceLocation> { + SourceManager &SM; + +public: + explicit BeforeThanCompare(SourceManager &SM) : SM(SM) { } + + bool operator()(SourceLocation LHS, SourceLocation RHS) const { + return SM.isBeforeInTranslationUnit(LHS, RHS); + } +}; + +/// \brief Compare two non-overlapping source ranges. +template<> +class BeforeThanCompare<SourceRange> { + SourceManager &SM; + +public: + explicit BeforeThanCompare(SourceManager &SM) : SM(SM) { } + + bool operator()(SourceRange LHS, SourceRange RHS) { + return SM.isBeforeInTranslationUnit(LHS.getBegin(), RHS.getBegin()); + } +}; } // end namespace clang diff --git a/include/clang/Basic/SourceManagerInternals.h b/include/clang/Basic/SourceManagerInternals.h index 1cb16b4..af95b78 100644 --- a/include/clang/Basic/SourceManagerInternals.h +++ b/include/clang/Basic/SourceManagerInternals.h @@ -6,15 +6,16 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the implementation details of the SourceManager -// class. -// +/// +/// \file +/// \brief Defines implementation details of the clang::SourceManager class. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_SOURCEMANAGER_INTERNALS_H #define LLVM_CLANG_SOURCEMANAGER_INTERNALS_H +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/StringMap.h" #include <map> @@ -26,22 +27,23 @@ namespace clang { //===----------------------------------------------------------------------===// struct LineEntry { - /// FileOffset - The offset in this file that the line entry occurs at. + /// \brief The offset in this file that the line entry occurs at. unsigned FileOffset; - /// LineNo - The presumed line number of this line entry: #line 4. + /// \brief The presumed line number of this line entry: \#line 4. unsigned LineNo; - /// FilenameID - The ID of the filename identified by this line entry: - /// #line 4 "foo.c". This is -1 if not specified. + /// \brief The ID of the filename identified by this line entry: + /// \#line 4 "foo.c". This is -1 if not specified. int FilenameID; - /// Flags - Set the 0 if no flags, 1 if a system header, + /// \brief Set the 0 if no flags, 1 if a system header, SrcMgr::CharacteristicKind FileKind; - /// IncludeOffset - This is the offset of the virtual include stack location, - /// which is manipulated by GNU linemarker directives. If this is 0 then - /// there is no virtual #includer. + /// \brief The offset of the virtual include stack location, + /// which is manipulated by GNU linemarker directives. + /// + /// If this is 0 then there is no virtual \#includer. unsigned IncludeOffset; static LineEntry get(unsigned Offs, unsigned Line, int Filename, @@ -71,20 +73,20 @@ inline bool operator<(unsigned Offset, const LineEntry &E) { return Offset < E.FileOffset; } -/// LineTableInfo - This class is used to hold and unique data used to -/// represent #line information. +/// \brief Used to hold and unique data used to represent \#line information. class LineTableInfo { - /// FilenameIDs - This map is used to assign unique IDs to filenames in - /// #line directives. This allows us to unique the filenames that + /// \brief Map used to assign unique IDs to filenames in \#line directives. + /// + /// This allows us to unique the filenames that /// frequently reoccur and reference them with indices. FilenameIDs holds /// the mapping from string -> ID, and FilenamesByID holds the mapping of ID /// to string. llvm::StringMap<unsigned, llvm::BumpPtrAllocator> FilenameIDs; std::vector<llvm::StringMapEntry<unsigned>*> FilenamesByID; - /// LineEntries - This is a map from FileIDs to a list of line entries (sorted - /// by the offset they occur in the file. - std::map<int, std::vector<LineEntry> > LineEntries; + /// \brief Map from FileIDs to a list of line entries (sorted by the offset + /// at which they occur in the file). + std::map<FileID, std::vector<LineEntry> > LineEntries; public: LineTableInfo() { } @@ -104,25 +106,26 @@ public: } unsigned getNumFilenames() const { return FilenamesByID.size(); } - void AddLineNote(int FID, unsigned Offset, + void AddLineNote(FileID FID, unsigned Offset, unsigned LineNo, int FilenameID); - void AddLineNote(int FID, unsigned Offset, + void AddLineNote(FileID FID, unsigned Offset, unsigned LineNo, int FilenameID, unsigned EntryExit, SrcMgr::CharacteristicKind FileKind); - /// FindNearestLineEntry - Find the line entry nearest to FID that is before - /// it. If there is no line entry before Offset in FID, return null. - const LineEntry *FindNearestLineEntry(int FID, unsigned Offset); + /// \brief Find the line entry nearest to FID that is before it. + /// + /// If there is no line entry before \p Offset in \p FID, returns null. + const LineEntry *FindNearestLineEntry(FileID FID, unsigned Offset); // Low-level access - typedef std::map<int, std::vector<LineEntry> >::iterator iterator; + typedef std::map<FileID, std::vector<LineEntry> >::iterator iterator; iterator begin() { return LineEntries.begin(); } iterator end() { return LineEntries.end(); } /// \brief Add a new line entry that has already been encoded into /// the internal representation of the line table. - void AddEntry(int FID, const std::vector<LineEntry> &Entries); + void AddEntry(FileID FID, const std::vector<LineEntry> &Entries); }; } // end namespace clang diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index 9e71827..96cada1 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -6,10 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines various enumerations that describe declaration and -// type specifiers. -// +/// +/// \file +/// \brief Defines various enumerations that describe declaration and +/// type specifiers. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_SPECIFIERS_H @@ -63,9 +64,8 @@ namespace clang { TST_error // erroneous type }; - /// WrittenBuiltinSpecs - Structure that packs information about the - /// type specifiers that were written in a particular type specifier - /// sequence. + /// \brief Structure that packs information about the type specifiers that + /// were written in a particular type specifier sequence. struct WrittenBuiltinSpecs { /*DeclSpec::TST*/ unsigned Type : 5; /*DeclSpec::TSS*/ unsigned Sign : 2; @@ -73,9 +73,8 @@ namespace clang { bool ModeAttr : 1; }; - /// AccessSpecifier - A C++ access specifier (public, private, - /// protected), plus the special value "none" which means - /// different things in different contexts. + /// \brief A C++ access specifier (public, private, protected), plus the + /// special value "none" which means different things in different contexts. enum AccessSpecifier { AS_public, AS_protected, @@ -83,24 +82,24 @@ namespace clang { AS_none }; - /// ExprValueKind - The categorization of expression values, - /// currently following the C++0x scheme. + /// \brief The categorization of expression values, currently following the + /// C++11 scheme. enum ExprValueKind { - /// An r-value expression (a pr-value in the C++0x taxonomy) + /// \brief An r-value expression (a pr-value in the C++11 taxonomy) /// produces a temporary value. VK_RValue, - /// An l-value expression is a reference to an object with + /// \brief An l-value expression is a reference to an object with /// independent storage. VK_LValue, - /// An x-value expression is a reference to an object with + /// \brief An x-value expression is a reference to an object with /// independent storage but which can be "moved", i.e. /// efficiently cannibalized for its resources. VK_XValue }; - /// A further classification of the kind of object referenced by an + /// \brief A further classification of the kind of object referenced by an /// l-value or x-value. enum ExprObjectKind { /// An ordinary object is located at an address in memory. @@ -112,13 +111,13 @@ namespace clang { /// A vector component is an element or range of elements on a vector. OK_VectorComponent, - /// An Objective C property is a logical field of an Objective-C - /// object which is read and written via Objective C method calls. + /// An Objective-C property is a logical field of an Objective-C + /// object which is read and written via Objective-C method calls. OK_ObjCProperty, - /// An Objective C array/dictionary subscripting which reads an object - /// or writes at the subscripted array/dictionary element via - /// Objective C method calls. + /// An Objective-C array/dictionary subscripting which reads an + /// object or writes at the subscripted array/dictionary element via + /// Objective-C method calls. OK_ObjCSubscript }; @@ -159,15 +158,22 @@ namespace clang { SC_Register }; - /// Checks whether the given storage class is legal for functions. + /// \brief Checks whether the given storage class is legal for functions. inline bool isLegalForFunction(StorageClass SC) { return SC <= SC_PrivateExtern; } - /// Checks whether the given storage class is legal for variables. + /// \brief Checks whether the given storage class is legal for variables. inline bool isLegalForVariable(StorageClass SC) { return true; } + + /// \brief In-class initialization styles for non-static data members. + enum InClassInitStyle { + ICIS_NoInit, ///< No in-class initializer. + ICIS_CopyInit, ///< Copy initialization. + ICIS_ListInit ///< Direct list-initialization. + }; } // end namespace clang #endif // LLVM_CLANG_BASIC_SPECIFIERS_H diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td index e7718cd..47738af 100644 --- a/include/clang/Basic/StmtNodes.td +++ b/include/clang/Basic/StmtNodes.td @@ -31,6 +31,9 @@ def DefaultStmt : DStmt<SwitchCase>; // GNU Extensions def AsmStmt : Stmt; +// MS Extensions +def MSAsmStmt : Stmt; + // Obj-C statements def ObjCAtTryStmt : Stmt; def ObjCAtCatchStmt : Stmt; @@ -134,7 +137,7 @@ def LambdaExpr : DStmt<Expr>; // Obj-C Expressions. def ObjCStringLiteral : DStmt<Expr>; -def ObjCNumericLiteral : DStmt<Expr>; +def ObjCBoxedExpr : DStmt<Expr>; def ObjCArrayLiteral : DStmt<Expr>; def ObjCDictionaryLiteral : DStmt<Expr>; def ObjCEncodeExpr : DStmt<Expr>; diff --git a/include/clang/Basic/TargetBuiltins.h b/include/clang/Basic/TargetBuiltins.h index 7c04bf7..1d5004c 100644 --- a/include/clang/Basic/TargetBuiltins.h +++ b/include/clang/Basic/TargetBuiltins.h @@ -6,6 +6,12 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Enumerates target-specific builtins in their own namespaces within +/// namespace ::clang. +/// +//===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_TARGET_BUILTINS_H #define LLVM_CLANG_BASIC_TARGET_BUILTINS_H @@ -15,7 +21,7 @@ namespace clang { - /// ARM builtins + /// \brief ARM builtins namespace ARM { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, @@ -25,7 +31,7 @@ namespace clang { }; } - /// PPC builtins + /// \brief PPC builtins namespace PPC { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, @@ -35,18 +41,18 @@ namespace clang { }; } - /// PTX builtins - namespace PTX { + /// \brief NVPTX builtins + namespace NVPTX { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, #define BUILTIN(ID, TYPE, ATTRS) BI##ID, -#include "clang/Basic/BuiltinsPTX.def" +#include "clang/Basic/BuiltinsNVPTX.def" LastTSBuiltin }; } - /// X86 builtins + /// \brief X86 builtins namespace X86 { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, @@ -56,9 +62,9 @@ namespace clang { }; } - /// NeonTypeFlags - Flags to identify the types for overloaded Neon - /// builtins. These must be kept in sync with the flags in - /// utils/TableGen/NeonEmitter.h. + /// \brief Flags to identify the types for overloaded Neon builtins. + /// + /// These must be kept in sync with the flags in utils/TableGen/NeonEmitter.h. class NeonTypeFlags { enum { EltTypeMask = 0xf, @@ -96,7 +102,7 @@ namespace clang { bool isQuad() const { return (Flags & QuadFlag) != 0; } }; - /// Hexagon builtins + /// \brief Hexagon builtins namespace Hexagon { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, @@ -105,6 +111,16 @@ namespace clang { LastTSBuiltin }; } + + /// \brief MIPS builtins + namespace Mips { + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#include "clang/Basic/BuiltinsMips.def" + LastTSBuiltin + }; + } } // end namespace clang. #endif diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index a03cf83..54d49e6 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the TargetInfo interface. -// +/// +/// \file +/// \brief Defines the clang::TargetInfo interface. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_TARGETINFO_H @@ -41,7 +42,7 @@ class TargetOptions; namespace Builtin { struct Info; } -/// TargetCXXABI - The types of C++ ABIs for which we can generate code. +/// \brief The types of C++ ABIs for which we can generate code. enum TargetCXXABI { /// The generic ("Itanium") C++ ABI, documented at: /// http://www.codesourcery.com/public/cxx-abi/ @@ -57,7 +58,7 @@ enum TargetCXXABI { CXXABI_Microsoft }; -/// TargetInfo - This class exposes information about the current target. +/// \brief Exposes information about the current target. /// class TargetInfo : public RefCountedBase<TargetInfo> { llvm::Triple Triple; @@ -79,6 +80,7 @@ protected: unsigned char LongLongWidth, LongLongAlign; unsigned char SuitableAlign; unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth; + unsigned short MaxVectorAlign; const char *DescriptionString; const char *UserLabelPrefix; const char *MCountName; @@ -99,7 +101,7 @@ protected: TargetInfo(const std::string &T); public: - /// CreateTargetInfo - Construct a target for the given options. + /// \brief Construct a target for the given options. /// /// \param Opts - The options to use to initialize the target. The target may /// modify the options to canonicalize the target feature information to match @@ -128,11 +130,35 @@ public: LongDouble }; + /// \brief The different kinds of __builtin_va_list types defined by + /// the target implementation. + enum BuiltinVaListKind { + /// typedef char* __builtin_va_list; + CharPtrBuiltinVaList = 0, + + /// typedef void* __builtin_va_list; + VoidPtrBuiltinVaList, + + /// __builtin_va_list as defined by the PNaCl ABI: + /// http://www.chromium.org/nativeclient/pnacl/bitcode-abi#TOC-Machine-Types + PNaClABIBuiltinVaList, + + /// __builtin_va_list as defined by the Power ABI: + /// https://www.power.org + /// /resources/downloads/Power-Arch-32-bit-ABI-supp-1.0-Embedded.pdf + PowerABIBuiltinVaList, + + /// __builtin_va_list as defined by the x86-64 ABI: + /// http://www.x86-64.org/documentation/abi.pdf + X86_64ABIBuiltinVaList + }; + protected: IntType SizeType, IntMaxType, UIntMaxType, PtrDiffType, IntPtrType, WCharType, WIntType, Char16Type, Char32Type, Int64Type, SigAtomicType; - /// Flag whether the Objective-C built-in boolean type should be signed char. + /// \brief Whether Objective-C's built-in boolean type should be signed char. + /// /// Otherwise, when this flag is not set, the normal built-in boolean type is /// used. unsigned UseSignedCharForObjCBool : 1; @@ -144,10 +170,12 @@ protected: /// boundary. unsigned UseBitFieldTypeAlignment : 1; - /// Control whether zero length bitfields (e.g., int : 0;) force alignment of - /// the next bitfield. If the alignment of the zero length bitfield is - /// greater than the member that follows it, `bar', `bar' will be aligned as - /// the type of the zero-length bitfield. + /// \brief Whether zero length bitfields (e.g., int : 0;) force alignment of + /// the next bitfield. + /// + /// If the alignment of the zero length bitfield is greater than the member + /// that follows it, `bar', `bar' will be aligned as the type of the + /// zero-length bitfield. unsigned UseZeroLengthBitfieldAlignment : 1; /// If non-zero, specifies a fixed alignment value for bitfields that follow @@ -170,19 +198,20 @@ public: IntType getSigAtomicType() const { return SigAtomicType; } - /// getTypeWidth - Return the width (in bits) of the specified integer type - /// enum. For example, SignedInt -> getIntWidth(). + /// \brief Return the width (in bits) of the specified integer type enum. + /// + /// For example, SignedInt -> getIntWidth(). unsigned getTypeWidth(IntType T) const; - /// getTypeAlign - Return the alignment (in bits) of the specified integer - /// type enum. For example, SignedInt -> getIntAlign(). + /// \brief Return the alignment (in bits) of the specified integer type enum. + /// + /// For example, SignedInt -> getIntAlign(). unsigned getTypeAlign(IntType T) const; - /// isTypeSigned - Return whether an integer types is signed. Returns true if - /// the type is signed; false otherwise. + /// \brief Returns true if the type is signed; false otherwise. static bool isTypeSigned(IntType T); - /// getPointerWidth - Return the width of pointers on this target, for the + /// \brief Return the width of pointers on this target, for the /// specified address space. uint64_t getPointerWidth(unsigned AddrSpace) const { return AddrSpace == 0 ? PointerWidth : getPointerWidthV(AddrSpace); @@ -191,17 +220,21 @@ public: return AddrSpace == 0 ? PointerAlign : getPointerAlignV(AddrSpace); } - /// getBoolWidth/Align - Return the size of '_Bool' and C++ 'bool' for this - /// target, in bits. + /// \brief Return the size of '_Bool' and C++ 'bool' for this target, in bits. unsigned getBoolWidth() const { return BoolWidth; } + + /// \brief Return the alignment of '_Bool' and C++ 'bool' for this target. unsigned getBoolAlign() const { return BoolAlign; } unsigned getCharWidth() const { return 8; } // FIXME unsigned getCharAlign() const { return 8; } // FIXME - /// getShortWidth/Align - Return the size of 'signed short' and - /// 'unsigned short' for this target, in bits. + /// \brief Return the size of 'signed short' and 'unsigned short' for this + /// target, in bits. unsigned getShortWidth() const { return 16; } // FIXME + + /// \brief Return the alignment of 'signed short' and 'unsigned short' for + /// this target. unsigned getShortAlign() const { return 16; } // FIXME /// getIntWidth/Align - Return the size of 'signed int' and 'unsigned int' for @@ -219,7 +252,7 @@ public: unsigned getLongLongWidth() const { return LongLongWidth; } unsigned getLongLongAlign() const { return LongLongAlign; } - /// getSuitableAlign - Return the alignment that is suitable for storing any + /// \brief Return the alignment that is suitable for storing any /// object with a fundamental alignment requirement. unsigned getSuitableAlign() const { return SuitableAlign; } @@ -261,7 +294,7 @@ public: return *LongDoubleFormat; } - /// getFloatEvalMethod - Return the value for the C99 FLT_EVAL_METHOD macro. + /// \brief Return the value for the C99 FLT_EVAL_METHOD macro. virtual unsigned getFloatEvalMethod() const { return 0; } // getLargeArrayMinWidth/Align - Return the minimum array size that is @@ -269,21 +302,22 @@ public: unsigned getLargeArrayMinWidth() const { return LargeArrayMinWidth; } unsigned getLargeArrayAlign() const { return LargeArrayAlign; } - /// getMaxAtomicPromoteWidth - Return the maximum width lock-free atomic - /// operation which will ever be supported for the given target + /// \brief Return the maximum width lock-free atomic operation which will + /// ever be supported for the given target unsigned getMaxAtomicPromoteWidth() const { return MaxAtomicPromoteWidth; } - /// getMaxAtomicInlineWidth - Return the maximum width lock-free atomic - /// operation which can be inlined given the supported features of the - /// given target. + /// \brief Return the maximum width lock-free atomic operation which can be + /// inlined given the supported features of the given target. unsigned getMaxAtomicInlineWidth() const { return MaxAtomicInlineWidth; } - /// getIntMaxTWidth - Return the size of intmax_t and uintmax_t for this - /// target, in bits. + /// \brief Return the maximum vector alignment supported for the given target. + unsigned getMaxVectorAlign() const { return MaxVectorAlign; } + + /// \brief Return the size of intmax_t and uintmax_t for this target, in bits. unsigned getIntMaxTWidth() const { return getTypeWidth(IntMaxType); } - /// getRegisterWidth - Return the "preferred" register width on this target. + /// \brief Return the "preferred" register width on this target. uint64_t getRegisterWidth() const { // Currently we assume the register width on the target matches the pointer // width, we can introduce a new variable for this if/when some target wants @@ -291,22 +325,24 @@ public: return LongWidth; } - /// getUserLabelPrefix - This returns the default value of the - /// __USER_LABEL_PREFIX__ macro, which is the prefix given to user symbols by - /// default. On most platforms this is "_", but it is "" on some, and "." on - /// others. + /// \brief Returns the default value of the __USER_LABEL_PREFIX__ macro, + /// which is the prefix given to user symbols by default. + /// + /// On most platforms this is "_", but it is "" on some, and "." on others. const char *getUserLabelPrefix() const { return UserLabelPrefix; } - /// MCountName - This returns name of the mcount instrumentation function. + /// \brief Returns the name of the mcount instrumentation function. const char *getMCountName() const { return MCountName; } - /// useSignedCharForObjCBool - Check if the Objective-C built-in boolean - /// type should be signed char. Otherwise, if this returns false, the - /// normal built-in boolean type should also be used for Objective-C. + /// \brief Check if the Objective-C built-in boolean type should be signed + /// char. + /// + /// Otherwise, if this returns false, the normal built-in boolean type + /// should also be used for Objective-C. bool useSignedCharForObjCBool() const { return UseSignedCharForObjCBool; } @@ -314,87 +350,91 @@ public: UseSignedCharForObjCBool = false; } - /// useBitFieldTypeAlignment() - Check whether the alignment of bit-field - /// types is respected when laying out structures. + /// \brief Check whether the alignment of bit-field types is respected + /// when laying out structures. bool useBitFieldTypeAlignment() const { return UseBitFieldTypeAlignment; } - /// useZeroLengthBitfieldAlignment() - Check whether zero length bitfields - /// should force alignment of the next member. + /// \brief Check whether zero length bitfields should force alignment of + /// the next member. bool useZeroLengthBitfieldAlignment() const { return UseZeroLengthBitfieldAlignment; } - /// getZeroLengthBitfieldBoundary() - Get the fixed alignment value in bits - /// for a member that follows a zero length bitfield. + /// \brief Get the fixed alignment value in bits for a member that follows + /// a zero length bitfield. unsigned getZeroLengthBitfieldBoundary() const { return ZeroLengthBitfieldBoundary; } - /// hasAlignMac68kSupport - Check whether this target support '#pragma options - /// align=mac68k'. + /// \brief Check whether this target support '\#pragma options align=mac68k'. bool hasAlignMac68kSupport() const { return HasAlignMac68kSupport; } - /// getTypeName - Return the user string for the specified integer type enum. + /// \brief Return the user string for the specified integer type enum. + /// /// For example, SignedShort -> "short". static const char *getTypeName(IntType T); - /// getTypeConstantSuffix - Return the constant suffix for the specified - /// integer type enum. For example, SignedLong -> "L". + /// \brief Return the constant suffix for the specified integer type enum. + /// + /// For example, SignedLong -> "L". static const char *getTypeConstantSuffix(IntType T); /// \brief Check whether the given real type should use the "fpret" flavor of - /// Obj-C message passing on this target. + /// Objective-C message passing on this target. bool useObjCFPRetForRealType(RealType T) const { return RealTypeUsesObjCFPRet & (1 << T); } /// \brief Check whether _Complex long double should use the "fp2ret" flavor - /// of Obj-C message passing on this target. + /// of Objective-C message passing on this target. bool useObjCFP2RetForComplexLongDouble() const { return ComplexLongDoubleUsesFP2Ret; } ///===---- Other target property query methods --------------------------===// - /// getTargetDefines - Appends the target-specific #define values for this + /// \brief Appends the target-specific \#define values for this /// target set to the specified buffer. virtual void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const = 0; - /// getTargetBuiltins - Return information about target-specific builtins for + /// Return information about target-specific builtins for /// the current primary target, and info about which builtins are non-portable /// across the current set of primary and secondary targets. virtual void getTargetBuiltins(const Builtin::Info *&Records, unsigned &NumRecords) const = 0; - /// isCLZForZeroUndef - The __builtin_clz* and __builtin_ctz* built-in + /// The __builtin_clz* and __builtin_ctz* built-in /// functions are specified to have undefined results for zero inputs, but /// on targets that support these operations in a way that provides /// well-defined results for zero without loss of performance, it is a good /// idea to avoid optimizing based on that undef behavior. virtual bool isCLZForZeroUndef() const { return true; } - /// getVAListDeclaration - Return the declaration to use for - /// __builtin_va_list, which is target-specific. - virtual const char *getVAListDeclaration() const = 0; + /// \brief Returns the kind of __builtin_va_list type that should be used + /// with this target. + virtual BuiltinVaListKind getBuiltinVaListKind() const = 0; - /// isValidClobber - Returns whether the passed in string is - /// a valid clobber in an inline asm statement. This is used by - /// Sema. + /// \brief Returns whether the passed in string is a valid clobber in an + /// inline asm statement. + /// + /// This is used by Sema. bool isValidClobber(StringRef Name) const; - /// isValidGCCRegisterName - Returns whether the passed in string - /// is a valid register name according to GCC. This is used by Sema for - /// inline asm statements. + /// \brief Returns whether the passed in string is a valid register name + /// according to GCC. + /// + /// This is used by Sema for inline asm statements. bool isValidGCCRegisterName(StringRef Name) const; - // getNormalizedGCCRegisterName - Returns the "normalized" GCC register name. - // For example, on x86 it will return "ax" when "eax" is passed in. + /// \brief Returns the "normalized" GCC register name. + /// + /// For example, on x86 it will return "ax" when "eax" is passed in. StringRef getNormalizedGCCRegisterName(StringRef Name) const; struct ConstraintInfo { @@ -421,13 +461,15 @@ public: bool allowsRegister() const { return (Flags & CI_AllowsRegister) != 0; } bool allowsMemory() const { return (Flags & CI_AllowsMemory) != 0; } - /// hasMatchingInput - Return true if this output operand has a matching + /// \brief Return true if this output operand has a matching /// (tied) input operand. bool hasMatchingInput() const { return (Flags & CI_HasMatchingInput) != 0; } - /// hasTiedOperand() - Return true if this input operand is a matching - /// constraint that ties it to an output operand. If this returns true, - /// then getTiedOperand will indicate which output operand this is tied to. + /// \brief Return true if this input operand is a matching + /// constraint that ties it to an output operand. + /// + /// If this returns true then getTiedOperand will indicate which output + /// operand this is tied to. bool hasTiedOperand() const { return TiedOperand != -1; } unsigned getTiedOperand() const { assert(hasTiedOperand() && "Has no tied operand!"); @@ -439,9 +481,10 @@ public: void setAllowsRegister() { Flags |= CI_AllowsRegister; } void setHasMatchingInput() { Flags |= CI_HasMatchingInput; } - /// setTiedOperand - Indicate that this is an input operand that is tied to - /// the specified output operand. Copy over the various constraint - /// information from the output. + /// \brief Indicate that this is an input operand that is tied to + /// the specified output operand. + /// + /// Copy over the various constraint information from the output. void setTiedOperand(unsigned N, ConstraintInfo &Output) { Output.setHasMatchingInput(); Flags = Output.Flags; @@ -471,11 +514,11 @@ public: return std::string(1, *Constraint); } - // Returns a string of target-specific clobbers, in LLVM format. + /// \brief Returns a string of target-specific clobbers, in LLVM format. virtual const char *getClobbers() const = 0; - /// getTriple - Return the target triple of the primary target. + /// \brief Returns the target triple of the primary target. const llvm::Triple &getTriple() const { return Triple; } @@ -494,14 +537,13 @@ public: const unsigned RegNum; }; - /// hasProtectedVisibility - Does this target support "protected" - /// visibility? + /// \brief Does this target support "protected" visibility? /// /// Any target which dynamic libraries will naturally support /// something like "default" (meaning that the symbol is visible /// outside this shared object) and "hidden" (meaning that it isn't) /// visibilities, but "protected" is really an ELF-specific concept - /// with wierd semantics designed around the convenience of dynamic + /// with weird semantics designed around the convenience of dynamic /// linker implementations. Which is not to suggest that there's /// consistent target-independent semantics for "default" visibility /// either; the entire thing is pretty badly mangled. @@ -509,28 +551,29 @@ public: virtual bool useGlobalsForAutomaticVariables() const { return false; } - /// getCFStringSection - Return the section to use for CFString - /// literals, or 0 if no special section is used. + /// \brief Return the section to use for CFString literals, or 0 if no + /// special section is used. virtual const char *getCFStringSection() const { return "__DATA,__cfstring"; } - /// getNSStringSection - Return the section to use for NSString - /// literals, or 0 if no special section is used. + /// \brief Return the section to use for NSString literals, or 0 if no + /// special section is used. virtual const char *getNSStringSection() const { return "__OBJC,__cstring_object,regular,no_dead_strip"; } - /// getNSStringNonFragileABISection - Return the section to use for - /// NSString literals, or 0 if no special section is used (NonFragile ABI). + /// \brief Return the section to use for NSString literals, or 0 if no + /// special section is used (NonFragile ABI). virtual const char *getNSStringNonFragileABISection() const { return "__DATA, __objc_stringobj, regular, no_dead_strip"; } - /// isValidSectionSpecifier - This is an optional hook that targets can - /// implement to perform semantic checking on attribute((section("foo"))) - /// specifiers. In this case, "foo" is passed in to be checked. If the - /// section specifier is invalid, the backend should return a non-empty string + /// \brief An optional hook that targets can implement to perform semantic + /// checking on attribute((section("foo"))) specifiers. + /// + /// In this case, "foo" is passed in to be checked. If the section + /// specifier is invalid, the backend should return a non-empty string /// that indicates the problem. /// /// This hook is a simple quality of implementation feature to catch errors @@ -541,43 +584,44 @@ public: return ""; } - /// setForcedLangOptions - Set forced language options. + /// \brief Set forced language options. + /// /// Apply changes to the target information with respect to certain /// language options which change the target configuration. virtual void setForcedLangOptions(LangOptions &Opts); - /// getDefaultFeatures - Get the default set of target features for the CPU; + /// \brief Get the default set of target features for the CPU; /// this should include all legal feature strings on the target. virtual void getDefaultFeatures(llvm::StringMap<bool> &Features) const { } - /// getABI - Get the ABI in use. + /// \brief Get the ABI currently in use. virtual const char *getABI() const { return ""; } - /// getCXXABI - Get the C++ ABI in use. + /// \brief Get the C++ ABI currently in use. virtual TargetCXXABI getCXXABI() const { return CXXABI; } - /// setCPU - Target the specific CPU. + /// \brief Target the specified CPU. /// - /// \return - False on error (invalid CPU name). + /// \return False on error (invalid CPU name). virtual bool setCPU(const std::string &Name) { return false; } - /// setABI - Use the specific ABI. + /// \brief Use the specified ABI. /// - /// \return - False on error (invalid ABI name). + /// \return False on error (invalid ABI name). virtual bool setABI(const std::string &Name) { return false; } - /// setCXXABI - Use this specific C++ ABI. + /// \brief Use this specified C++ ABI. /// - /// \return - False on error (invalid C++ ABI name). + /// \return False on error (invalid C++ ABI name). bool setCXXABI(const std::string &Name) { static const TargetCXXABI Unknown = static_cast<TargetCXXABI>(-1); TargetCXXABI ABI = llvm::StringSwitch<TargetCXXABI>(Name) @@ -589,27 +633,28 @@ public: return setCXXABI(ABI); } - /// setCXXABI - Set the C++ ABI to be used by this implementation. + /// \brief Set the C++ ABI to be used by this implementation. /// - /// \return - False on error (ABI not valid on this target) + /// \return False on error (ABI not valid on this target) virtual bool setCXXABI(TargetCXXABI ABI) { CXXABI = ABI; return true; } - /// setFeatureEnabled - Enable or disable a specific target feature, + /// \brief Enable or disable a specific target feature; /// the feature name must be valid. /// - /// \return - False on error (invalid feature name). + /// \return False on error (invalid feature name). virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name, bool Enabled) const { return false; } - /// HandleTargetOptions - Perform initialization based on the user configured - /// set of features (e.g., +sse4). The list is guaranteed to have at most one - /// entry per feature. + /// \brief Perform initialization based on the user configured + /// set of features (e.g., +sse4). + /// + /// The list is guaranteed to have at most one entry per feature. /// /// The target may modify the features list, to change which options are /// passed onwards to the backend. @@ -621,19 +666,20 @@ public: return false; } - // getRegParmMax - Returns maximal number of args passed in registers. + // \brief Returns maximal number of args passed in registers. unsigned getRegParmMax() const { assert(RegParmMax < 7 && "RegParmMax value is larger than AST can handle"); return RegParmMax; } - /// isTLSSupported - Whether the target supports thread-local storage. + /// \brief Whether the target supports thread-local storage. bool isTLSSupported() const { return TLSSupported; } - /// hasNoAsmVariants - Return true if {|} are normal characters in the - /// asm string. If this returns false (the default), then {abc|xyz} is syntax + /// \brief Return true if {|} are normal characters in the asm string. + /// + /// If this returns false (the default), then {abc|xyz} is syntax /// that says that when compiling for asm variant #0, "abc" should be /// generated, but when compiling for asm variant #1, "xyz" should be /// generated. @@ -641,14 +687,13 @@ public: return NoAsmVariants; } - /// getEHDataRegisterNumber - Return the register number that - /// __builtin_eh_return_regno would return with the specified argument. + /// \brief Return the register number that __builtin_eh_return_regno would + /// return with the specified argument. virtual int getEHDataRegisterNumber(unsigned RegNo) const { return -1; } - /// getStaticInitSectionSpecifier - Return the section to use for C++ static - /// initialization functions. + /// \brief Return the section to use for C++ static initialization functions. virtual const char *getStaticInitSectionSpecifier() const { return 0; } diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h index f3c206f..15ececd 100644 --- a/include/clang/Basic/TargetOptions.h +++ b/include/clang/Basic/TargetOptions.h @@ -6,6 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Defines the clang::TargetOptions class. +/// +//===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_FRONTEND_TARGETOPTIONS_H #define LLVM_CLANG_FRONTEND_TARGETOPTIONS_H @@ -15,7 +20,7 @@ namespace clang { -/// TargetOptions - Options for controlling the target. +/// \brief Options for controlling the target. class TargetOptions { public: /// If given, the name of the target triple to compile for. If not given the diff --git a/include/clang/Basic/TemplateKinds.h b/include/clang/Basic/TemplateKinds.h index c6ea05b..dda011a 100644 --- a/include/clang/Basic/TemplateKinds.h +++ b/include/clang/Basic/TemplateKinds.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the TemplateNameKind enum. -// +/// +/// \file +/// \brief Defines the clang::TemplateNameKind enum. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_TEMPLATEKINDS_H #define LLVM_CLANG_TEMPLATEKINDS_H diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 2e4d34d..fc03191 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -211,6 +211,8 @@ PUNCTUATOR(greatergreatergreater, ">>>") // KEYCXX0X - This is a C++ keyword introduced to C++ in C++0x // KEYGNU - This is a keyword if GNU extensions are enabled // KEYMS - This is a keyword if Microsoft extensions are enabled +// KEYNOMS - This is a keyword that must never be enabled under +// Microsoft mode // KEYOPENCL - This is a keyword in OpenCL // KEYALTIVEC - This is a keyword in AltiVec // KEYBORLAND - This is a keyword if Borland extensions are enabled @@ -251,6 +253,7 @@ KEYWORD(void , KEYALL) KEYWORD(volatile , KEYALL) KEYWORD(while , KEYALL) KEYWORD(_Alignas , KEYALL) +KEYWORD(_Alignof , KEYALL) KEYWORD(_Atomic , KEYALL) KEYWORD(_Bool , KEYNOCXX) KEYWORD(_Complex , KEYALL) @@ -310,8 +313,8 @@ CXX_KEYWORD_OPERATOR(xor_eq , caretequal) // C++0x keywords KEYWORD(alignas , KEYCXX0X) KEYWORD(alignof , KEYCXX0X) -KEYWORD(char16_t , KEYCXX0X) -KEYWORD(char32_t , KEYCXX0X) +KEYWORD(char16_t , KEYCXX0X|KEYNOMS) +KEYWORD(char32_t , KEYCXX0X|KEYNOMS) KEYWORD(constexpr , KEYCXX0X) KEYWORD(decltype , KEYCXX0X) KEYWORD(noexcept , KEYCXX0X) @@ -342,6 +345,9 @@ KEYWORD(__PRETTY_FUNCTION__ , KEYALL) // GNU Extensions (outside impl-reserved namespace) KEYWORD(typeof , KEYGNU) +// MS Extensions +KEYWORD(L__FUNCTION__ , KEYMS) + // GNU and MS Type Traits KEYWORD(__has_nothrow_assign , KEYCXX) KEYWORD(__has_nothrow_copy , KEYCXX) @@ -486,28 +492,33 @@ ALIAS("__volatile" , volatile , KEYALL) ALIAS("__volatile__" , volatile , KEYALL) // Microsoft extensions which should be disabled in strict conformance mode -KEYWORD(__ptr64 , KEYMS) -KEYWORD(__ptr32 , KEYMS) -KEYWORD(__w64 , KEYMS) -KEYWORD(__uuidof , KEYMS | KEYBORLAND) -KEYWORD(__try , KEYMS | KEYBORLAND) -KEYWORD(__finally , KEYMS | KEYBORLAND) -KEYWORD(__leave , KEYMS | KEYBORLAND) -KEYWORD(__int64 , KEYMS) -KEYWORD(__if_exists , KEYMS) -KEYWORD(__if_not_exists , KEYMS) -ALIAS("__int8" , char , KEYMS) -ALIAS("__int16" , short , KEYMS) -ALIAS("__int32" , int , KEYMS) -ALIAS("_asm" , asm , KEYMS) -ALIAS("_cdecl" , __cdecl , KEYMS | KEYBORLAND) -ALIAS("_fastcall" , __fastcall , KEYMS | KEYBORLAND) -ALIAS("_stdcall" , __stdcall , KEYMS | KEYBORLAND) -ALIAS("_thiscall" , __thiscall , KEYMS) -ALIAS("_uuidof" , __uuidof , KEYMS | KEYBORLAND) -ALIAS("_inline" , inline , KEYMS) -ALIAS("_declspec" , __declspec , KEYMS) -ALIAS("__interface" , struct , KEYMS) +KEYWORD(__ptr64 , KEYMS) +KEYWORD(__ptr32 , KEYMS) +KEYWORD(__w64 , KEYMS) +KEYWORD(__uuidof , KEYMS | KEYBORLAND) +KEYWORD(__try , KEYMS | KEYBORLAND) +KEYWORD(__finally , KEYMS | KEYBORLAND) +KEYWORD(__leave , KEYMS | KEYBORLAND) +KEYWORD(__int64 , KEYMS) +KEYWORD(__if_exists , KEYMS) +KEYWORD(__if_not_exists , KEYMS) +KEYWORD(__single_inheritance , KEYMS) +KEYWORD(__multiple_inheritance , KEYMS) +KEYWORD(__virtual_inheritance , KEYMS) +ALIAS("__int8" , char , KEYMS) +ALIAS("__int16" , short , KEYMS) +ALIAS("__int32" , int , KEYMS) +ALIAS("_asm" , asm , KEYMS) +ALIAS("_alignof" , __alignof , KEYMS) +ALIAS("__builtin_alignof", __alignof , KEYMS) +ALIAS("_cdecl" , __cdecl , KEYMS | KEYBORLAND) +ALIAS("_fastcall" , __fastcall , KEYMS | KEYBORLAND) +ALIAS("_stdcall" , __stdcall , KEYMS | KEYBORLAND) +ALIAS("_thiscall" , __thiscall , KEYMS) +ALIAS("_uuidof" , __uuidof , KEYMS | KEYBORLAND) +ALIAS("_inline" , inline , KEYMS) +ALIAS("_declspec" , __declspec , KEYMS) +ALIAS("__interface" , struct , KEYMS) // Borland Extensions which should be disabled in strict conformance mode. ALIAS("_pascal" , __pascal , KEYBORLAND) @@ -584,6 +595,11 @@ ANNOTATION(pragma_vis) // handles them. ANNOTATION(pragma_pack) +// Annotation for #pragma clang __debug parser_crash... +// The lexer produces these so that they only take effect when the parser +// handles them. +ANNOTATION(pragma_parser_crash) + #undef ANNOTATION #undef TESTING_KEYWORD #undef OBJC2_AT_KEYWORD diff --git a/include/clang/Basic/TokenKinds.h b/include/clang/Basic/TokenKinds.h index 515390a..478add8 100644 --- a/include/clang/Basic/TokenKinds.h +++ b/include/clang/Basic/TokenKinds.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the TokenKind enum and support functions. -// +/// +/// \file +/// \brief Defines the clang::TokenKind enum and support functions. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_TOKENKINDS_H @@ -18,24 +19,23 @@ namespace clang { namespace tok { -/// TokenKind - This provides a simple uniform namespace for tokens from all C -/// languages. +/// \brief Provides a simple uniform namespace for tokens from all C languages. enum TokenKind { #define TOK(X) X, #include "clang/Basic/TokenKinds.def" NUM_TOKENS }; -/// PPKeywordKind - This provides a namespace for preprocessor keywords which -/// start with a '#' at the beginning of the line. +/// \brief Provides a namespace for preprocessor keywords which start with a +/// '#' at the beginning of the line. enum PPKeywordKind { #define PPKEYWORD(X) pp_##X, #include "clang/Basic/TokenKinds.def" NUM_PP_KEYWORDS }; -/// ObjCKeywordKind - This provides a namespace for Objective-C keywords which -/// start with an '@'. +/// \brief Provides a namespace for Objective-C keywords which start with +/// an '@'. enum ObjCKeywordKind { #define OBJC1_AT_KEYWORD(X) objc_##X, #define OBJC2_AT_KEYWORD(X) objc_##X, @@ -43,8 +43,7 @@ enum ObjCKeywordKind { NUM_OBJC_KEYWORDS }; -/// OnOffSwitch - This defines the possible values of an on-off-switch -/// (C99 6.10.6p2). +/// \brief Defines the possible values of an on-off-switch (C99 6.10.6p2). enum OnOffSwitch { OOS_ON, OOS_OFF, OOS_DEFAULT }; diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h index 721f44f..0a5a864 100644 --- a/include/clang/Basic/TypeTraits.h +++ b/include/clang/Basic/TypeTraits.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines enumerations for the type traits support. -// +/// +/// \file +/// \brief Defines enumerations for the type traits support. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_TYPETRAITS_H @@ -16,7 +17,7 @@ namespace clang { - /// UnaryTypeTrait - Names for the unary type traits. + /// \brief Names for the unary type traits. enum UnaryTypeTrait { UTT_HasNothrowAssign, UTT_HasNothrowCopy, @@ -62,7 +63,7 @@ namespace clang { UTT_IsVolatile }; - /// BinaryTypeTrait - Names for the binary type traits. + /// \brief Names for the binary type traits. enum BinaryTypeTrait { BTT_IsBaseOf, BTT_IsConvertible, @@ -72,13 +73,13 @@ namespace clang { BTT_IsTriviallyAssignable }; - /// ArrayTypeTrait - Names for the array type traits. + /// \brief Names for the array type traits. enum ArrayTypeTrait { ATT_ArrayRank, ATT_ArrayExtent }; - /// UnaryExprOrTypeTrait - Names for the "expression or type" traits. + /// \brief Names for the "expression or type" traits. enum UnaryExprOrTypeTrait { UETT_SizeOf, UETT_AlignOf, diff --git a/include/clang/Basic/Version.h b/include/clang/Basic/Version.h index f3f5b5a..3f1b4d8 100644 --- a/include/clang/Basic/Version.h +++ b/include/clang/Basic/Version.h @@ -6,10 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This header defines version macros and version-related utility functions -// for Clang. -// +/// +/// \file +/// \brief Defines version macros and version-related utility functions +/// for Clang. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_VERSION_H @@ -26,8 +27,7 @@ /// \brief Helper macro for CLANG_VERSION_STRING. #define CLANG_MAKE_VERSION_STRING(X,Y,Z) CLANG_MAKE_VERSION_STRING2(X.Y.Z) -/// \brief A string that describes the Clang version number, e.g., -/// "1.0". +/// \brief A string that describes the Clang version number, e.g., "1.0". #define CLANG_VERSION_STRING \ CLANG_MAKE_VERSION_STRING(CLANG_VERSION_MAJOR,CLANG_VERSION_MINOR, \ CLANG_VERSION_PATCHLEVEL) @@ -35,8 +35,7 @@ /// \brief Helper macro for CLANG_VERSION_STRING. #define CLANG_MAKE_VERSION_STRING(X,Y) CLANG_MAKE_VERSION_STRING2(X.Y) -/// \brief A string that describes the Clang version number, e.g., -/// "1.0". +/// \brief A string that describes the Clang version number, e.g., "1.0". #define CLANG_VERSION_STRING \ CLANG_MAKE_VERSION_STRING(CLANG_VERSION_MAJOR,CLANG_VERSION_MINOR) #endif @@ -47,31 +46,34 @@ namespace clang { /// Clang was built. std::string getClangRepositoryPath(); - /// \brief Retrieves the repository path from which LLVM was built. Supports - /// LLVM residing in a separate repository from clang. + /// \brief Retrieves the repository path from which LLVM was built. + /// + /// This supports LLVM residing in a separate repository from clang. std::string getLLVMRepositoryPath(); /// \brief Retrieves the repository revision number (or identifer) from which - /// this Clang was built. + /// this Clang was built. std::string getClangRevision(); /// \brief Retrieves the repository revision number (or identifer) from which - /// LLVM was built. If Clang and LLVM are in the same repository, this returns - /// the same string as getClangRevision. + /// LLVM was built. + /// + /// If Clang and LLVM are in the same repository, this returns the same + /// string as getClangRevision. std::string getLLVMRevision(); /// \brief Retrieves the full repository version that is an amalgamation of - /// the information in getClangRepositoryPath() and getClangRevision(). + /// the information in getClangRepositoryPath() and getClangRevision(). std::string getClangFullRepositoryVersion(); /// \brief Retrieves a string representing the complete clang version, - /// which includes the clang version number, the repository version, - /// and the vendor tag. + /// which includes the clang version number, the repository version, + /// and the vendor tag. std::string getClangFullVersion(); /// \brief Retrieves a string representing the complete clang version suitable - /// for use in the CPP __VERSION__ macro, which includes the clang version - /// number, the repository version, and the vendor tag. + /// for use in the CPP __VERSION__ macro, which includes the clang version + /// number, the repository version, and the vendor tag. std::string getClangFullCPPVersion(); } diff --git a/include/clang/Basic/VersionTuple.h b/include/clang/Basic/VersionTuple.h index 30ef6641..a94f76c 100644 --- a/include/clang/Basic/VersionTuple.h +++ b/include/clang/Basic/VersionTuple.h @@ -6,10 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This header defines the VersionTuple class, which represents a version in -// the form major[.minor[.subminor]]. -// +/// +/// \file +/// \brief Defines the clang::VersionTuple class, which represents a version in +/// the form major[.minor[.subminor]]. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_VERSIONTUPLE_H #define LLVM_CLANG_BASIC_VERSIONTUPLE_H @@ -73,15 +74,18 @@ public: return X.Major == Y.Major && X.Minor == Y.Minor && X.Subminor == Y.Subminor; } - /// \brief Determine if two version numbers are not equivalent. If - /// not provided, minor and subminor version numbers are considered to be + /// \brief Determine if two version numbers are not equivalent. + /// + /// If not provided, minor and subminor version numbers are considered to be /// zero. friend bool operator!=(const VersionTuple &X, const VersionTuple &Y) { return !(X == Y); } - /// \brief Determine whether one version number precedes another. If not - /// provided, minor and subminor version numbers are considered to be zero. + /// \brief Determine whether one version number precedes another. + /// + /// If not provided, minor and subminor version numbers are considered to be + /// zero. friend bool operator<(const VersionTuple &X, const VersionTuple &Y) { if (X.Major != Y.Major) return X.Major < Y.Major; @@ -92,28 +96,39 @@ public: return X.Subminor < Y.Subminor; } - /// \brief Determine whether one version number follows another. If not - /// provided, minor and subminor version numbers are considered to be zero. + /// \brief Determine whether one version number follows another. + /// + /// If not provided, minor and subminor version numbers are considered to be + /// zero. friend bool operator>(const VersionTuple &X, const VersionTuple &Y) { return Y < X; } /// \brief Determine whether one version number precedes or is - /// equivalent to another. If not provided, minor and subminor - /// version numbers are considered to be zero. + /// equivalent to another. + /// + /// If not provided, minor and subminor version numbers are considered to be + /// zero. friend bool operator<=(const VersionTuple &X, const VersionTuple &Y) { return !(Y < X); } /// \brief Determine whether one version number follows or is - /// equivalent to another. If not provided, minor and subminor - /// version numbers are considered to be zero. + /// equivalent to another. + /// + /// If not provided, minor and subminor version numbers are considered to be + /// zero. friend bool operator>=(const VersionTuple &X, const VersionTuple &Y) { return !(X < Y); } - /// \brief Retrieve a string representation of the version number/ + /// \brief Retrieve a string representation of the version number. std::string getAsString() const; + + /// \brief Try to parse the given string as a version number. + /// \returns \c true if the string does not match the regular expression + /// [0-9]+(\.[0-9]+(\.[0-9]+)) + bool tryParse(StringRef string); }; /// \brief Print a version number. diff --git a/include/clang/Basic/Visibility.h b/include/clang/Basic/Visibility.h index 90e288a..e81ad91 100644 --- a/include/clang/Basic/Visibility.h +++ b/include/clang/Basic/Visibility.h @@ -6,20 +6,23 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the Visibility enumeration and various utility -// functions. -// +/// +/// \file +/// \brief Defines the clang::Visibility enumeration and various utility +/// functions. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_VISIBILITY_H #define LLVM_CLANG_BASIC_VISIBILITY_H namespace clang { -/// \link Describes the different kinds of visibility that a -/// declaration may have. Visibility determines how a declaration -/// interacts with the dynamic linker. It may also affect whether the -/// symbol can be found by runtime symbol lookup APIs. +/// \brief Describes the different kinds of visibility that a declaration +/// may have. +/// +/// Visibility determines how a declaration interacts with the dynamic +/// linker. It may also affect whether the symbol can be found by runtime +/// symbol lookup APIs. /// /// Visibility is not described in any language standard and /// (nonetheless) sometimes has odd behavior. Not all platforms diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td index 71a0aa2..451d562 100644 --- a/include/clang/Basic/arm_neon.td +++ b/include/clang/Basic/arm_neon.td @@ -15,6 +15,7 @@ class Op; def OP_NONE : Op; +def OP_UNAVAILABLE : Op; def OP_ADD : Op; def OP_ADDL : Op; def OP_ADDW : Op; diff --git a/include/clang/Driver/Arg.h b/include/clang/Driver/Arg.h index e8625bb..e466cc3 100644 --- a/include/clang/Driver/Arg.h +++ b/include/clang/Driver/Arg.h @@ -6,6 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Defines the clang::driver::Arg class for parsed arguments. +/// +//===----------------------------------------------------------------------===// #ifndef CLANG_DRIVER_ARG_H_ #define CLANG_DRIVER_ARG_H_ @@ -20,7 +25,7 @@ namespace driver { class ArgList; class Option; - /// Arg - A concrete instance of a particular driver option. + /// \brief A concrete instance of a particular driver option. /// /// The Arg class encodes just enough information to be able to /// derive the argument values efficiently. In addition, Arg @@ -32,25 +37,26 @@ namespace driver { void operator=(const Arg &); // DO NOT IMPLEMENT private: - /// The option this argument is an instance of. + /// \brief The option this argument is an instance of. const Option *Opt; - /// The argument this argument was derived from (during tool chain + /// \brief The argument this argument was derived from (during tool chain /// argument translation), if any. const Arg *BaseArg; - /// The index at which this argument appears in the containing + /// \brief The index at which this argument appears in the containing /// ArgList. unsigned Index; - /// Was this argument used to effect compilation; used for generating - /// "argument unused" diagnostics. + /// \brief Was this argument used to effect compilation? + /// + /// This is used for generating "argument unused" diagnostics. mutable unsigned Claimed : 1; - /// Does this argument own its values. + /// \brief Does this argument own its values? mutable unsigned OwnsValues : 1; - /// The argument values, as C strings. + /// \brief The argument values, as C strings. SmallVector<const char *, 2> Values; public: @@ -64,8 +70,9 @@ namespace driver { const Option &getOption() const { return *Opt; } unsigned getIndex() const { return Index; } - /// getBaseArg - Return the base argument which generated this - /// arg; this is either the argument itself or the argument it was + /// \brief Return the base argument which generated this arg. + /// + /// This is either the argument itself or the argument it was /// derived from during tool chain specific argument translation. const Arg &getBaseArg() const { return BaseArg ? *BaseArg : *this; @@ -79,7 +86,7 @@ namespace driver { bool isClaimed() const { return getBaseArg().Claimed; } - /// claim - Set the Arg claimed bit. + /// \brief Set the Arg claimed bit. void claim() const { getBaseArg().Claimed = true; } unsigned getNumValues() const { return Values.size(); } @@ -98,20 +105,21 @@ namespace driver { return false; } - /// render - Append the argument onto the given array as strings. + /// \brief Append the argument onto the given array as strings. void render(const ArgList &Args, ArgStringList &Output) const; - /// renderAsInput - Append the argument, render as an input, onto - /// the given array as strings. The distinction is that some - /// options only render their values when rendered as a input - /// (e.g., Xlinker). + /// \brief Append the argument, render as an input, onto the given + /// array as strings. + /// + /// The distinction is that some options only render their values + /// when rendered as a input (e.g., Xlinker). void renderAsInput(const ArgList &Args, ArgStringList &Output) const; static bool classof(const Arg *) { return true; } void dump() const; - /// getAsString - Return a formatted version of the argument and + /// \brief Return a formatted version of the argument and /// its values, for debugging and diagnostics. std::string getAsString(const ArgList &Args) const; }; diff --git a/include/clang/Driver/ArgList.h b/include/clang/Driver/ArgList.h index 3affb00..b7e490c 100644 --- a/include/clang/Driver/ArgList.h +++ b/include/clang/Driver/ArgList.h @@ -187,6 +187,14 @@ namespace driver { OptSpecifier Id3) const; Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2, OptSpecifier Id3, OptSpecifier Id4) const; + Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2, + OptSpecifier Id3, OptSpecifier Id4, OptSpecifier Id5) const; + Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2, + OptSpecifier Id3, OptSpecifier Id4, OptSpecifier Id5, + OptSpecifier Id6) const; + Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2, + OptSpecifier Id3, OptSpecifier Id4, OptSpecifier Id5, + OptSpecifier Id6, OptSpecifier Id7) const; /// getArgString - Return the input argument string at \arg Index. virtual const char *getArgString(unsigned Index) const = 0; diff --git a/include/clang/Driver/CC1Options.h b/include/clang/Driver/CC1Options.h index 4a8bbe5..e69de29 100644 --- a/include/clang/Driver/CC1Options.h +++ b/include/clang/Driver/CC1Options.h @@ -1,32 +0,0 @@ -//===--- CC1Options.h - Clang CC1 Options Table -----------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef CLANG_DRIVER_CC1OPTIONS_H -#define CLANG_DRIVER_CC1OPTIONS_H - -namespace clang { -namespace driver { - class OptTable; - -namespace cc1options { - enum ID { - OPT_INVALID = 0, // This is not an option ID. -#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ - HELPTEXT, METAVAR) OPT_##ID, -#include "clang/Driver/CC1Options.inc" - LastOption -#undef OPTION - }; -} - - OptTable *createCC1OptTable(); -} -} - -#endif diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 83c988a..6e4d7f2 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -11,8 +11,7 @@ // //===----------------------------------------------------------------------===// -// Include the common option parsing interfaces. -include "OptParser.td" +let Flags = [CC1Option] in { //===----------------------------------------------------------------------===// // Target Options @@ -40,8 +39,6 @@ def analysis_UnoptimizedCFG : Flag<"-unoptimized-cfg">, HelpText<"Generate unoptimized CFGs for all analyses">; def analysis_CFGAddImplicitDtors : Flag<"-cfg-add-implicit-dtors">, HelpText<"Add C++ implicit destructors to CFGs for all analyses">; -def analysis_CFGAddInitializers : Flag<"-cfg-add-initializers">, - HelpText<"Add C++ initializers to CFGs for all analyses">; def analyzer_store : Separate<"-analyzer-store">, HelpText<"Source Code Analysis - Abstract Memory Store Models">; @@ -145,46 +142,12 @@ def fdebug_compilation_dir : Separate<"-fdebug-compilation-dir">, HelpText<"The compilation directory to embed in the debug info.">; def dwarf_debug_flags : Separate<"-dwarf-debug-flags">, HelpText<"The string to embed in the Dwarf debug flags record.">; -def faddress_sanitizer: Flag<"-faddress-sanitizer">, - HelpText<"Enable AddressSanitizer instrumentation (memory error detection)">; -def fthread_sanitizer: Flag<"-fthread-sanitizer">, - HelpText<"Enable ThreadSanitizer instrumentation (race detection)">; def fforbid_guard_variables : Flag<"-fforbid-guard-variables">, HelpText<"Emit an error if a C++ static local initializer would need a guard variable">; -def g : Flag<"-g">, HelpText<"Generate source level debug information">; -def fno_dwarf2_cfi_asm : Flag<"-fno-dwarf2-cfi-asm">, - HelpText<"Don't use the cfi directives">; -def fno_dwarf_directory_asm : Flag<"-fno-dwarf-directory-asm">, - HelpText<"Don't separate directory and filename in .file directives">; -def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">, - HelpText<"Generate runtime checks for undefined behavior.">; -def flimit_debug_info : Flag<"-flimit-debug-info">, - HelpText<"Limit debug information produced to reduce size of debug binary">; -def fno_common : Flag<"-fno-common">, - HelpText<"Compile common globals like normal definitions">; def no_implicit_float : Flag<"-no-implicit-float">, - HelpText<"Don't generate implicit floating point instructions (x86-only)">; -def finstrument_functions : Flag<"-finstrument-functions">, - HelpText<"Generate calls to instrument function entry and exit">; -def fno_limit_debug_info : Flag<"-fno-limit-debug-info">, - HelpText<"Do not limit debug information produced to reduce size of debug binary">; -def fno_merge_all_constants : Flag<"-fno-merge-all-constants">, - HelpText<"Disallow merging of constants.">; -def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, - HelpText<"Do not emit code to make initialization of local statics thread safe">; + HelpText<"Don't generate implicit floating point instructions">; def fdump_vtable_layouts : Flag<"-fdump-vtable-layouts">, HelpText<"Dump the layouts of all vtables that will be emitted in a translation unit">; -def ffunction_sections : Flag<"-ffunction-sections">, - HelpText<"Place each function in its own section (ELF Only)">; -def fdata_sections : Flag<"-fdata-sections">, - HelpText<"Place each data in its own section (ELF Only)">; -def fstrict_enums : Flag<"-fstrict-enums">, - HelpText<"Enable optimizations based on the strict definition of an enum's " - "value range.">; -def ftrap_function_EQ : Joined<"-ftrap-function=">, - HelpText<"Issue call to specified function rather than a trap instruction">; -def funroll_loops : Flag<"-funroll-loops">, - HelpText<"Turn on loop unroller">; def femit_coverage_notes : Flag<"-femit-coverage-notes">, HelpText<"Emit a gcov coverage notes file when compiling.">; def femit_coverage_data: Flag<"-femit-coverage-data">, @@ -215,66 +178,37 @@ def menable_unsafe_fp_math : Flag<"-menable-unsafe-fp-math">, "precision">; def mfloat_abi : Separate<"-mfloat-abi">, HelpText<"The float ABI to use">; -def mno_global_merge : Flag<"-mno-global-merge">, - HelpText<"Disable merging of globals">; def mlimit_float_precision : Separate<"-mlimit-float-precision">, HelpText<"Limit float precision to the given value">; def mno_exec_stack : Flag<"-mnoexecstack">, HelpText<"Mark the file as not needing an executable stack">; def mno_zero_initialized_in_bss : Flag<"-mno-zero-initialized-in-bss">, HelpText<"Do not put zero initialized data in the BSS">; -def momit_leaf_frame_pointer : Flag<"-momit-leaf-frame-pointer">, - HelpText<"Omit frame pointer setup for leaf functions.">; -def msoft_float : Flag<"-msoft-float">, - HelpText<"Use software floating point">; def backend_option : Separate<"-backend-option">, HelpText<"Additional arguments to forward to LLVM backend (during code gen)">; def mregparm : Separate<"-mregparm">, HelpText<"Limit the number of registers available for integer arguments">; -def mrelax_all : Flag<"-mrelax-all">, - HelpText<"(integrated-as) Relax all machine instructions">; def msave_temp_labels : Flag<"-msave-temp-labels">, HelpText<"(integrated-as) Save temporary labels">; -def mrtd: Flag<"-mrtd">, - HelpText<"Make StdCall calling convention the default">; def mrelocation_model : Separate<"-mrelocation-model">, HelpText<"The relocation model to use">; def munwind_tables : Flag<"-munwind-tables">, HelpText<"Generate unwinding tables for all functions">; +def fuse_init_array : Flag<"-fuse-init-array">, + HelpText<"Use .init_array instead of .ctors">; def mconstructor_aliases : Flag<"-mconstructor-aliases">, HelpText<"Emit complete constructors and destructors as aliases when possible">; -def mms_bitfields : Flag<"-mms-bitfields">, - HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard.">; -def mstackrealign : Flag<"-mstackrealign">, - HelpText<"Force realign the stack at entry to every function.">; -def mstack_alignment : Joined<"-mstack-alignment=">, - HelpText<"Set the stack alignment">; def mlink_bitcode_file : Separate<"-mlink-bitcode-file">, HelpText<"Link the given bitcode file before performing optimizations.">; -def O : Joined<"-O">, HelpText<"Optimization level">; -def Os : Flag<"-Os">, HelpText<"Optimize for size">; -def Oz : Flag<"-Oz">, HelpText<"Optimize for size, regardless of performance">; -def pg : Flag<"-pg">, HelpText<"Enable mcount instrumentation">; //===----------------------------------------------------------------------===// // Dependency Output Options //===----------------------------------------------------------------------===// -def dependency_file : Separate<"-dependency-file">, - HelpText<"Filename (or -) to write dependency output to">; -def dependency_dot : Separate<"-dependency-dot">, - HelpText<"Filename to write DOT-formatted header dependencies to">; def sys_header_deps : Flag<"-sys-header-deps">, HelpText<"Include system headers in dependency output">; def header_include_file : Separate<"-header-include-file">, HelpText<"Filename (or -) to write header include output to">; -def H : Flag<"-H">, - HelpText<"Show header includes and nesting depth">; -def MQ : Separate<"-MQ">, HelpText<"Specify target to quote for dependency">; -def MT : Separate<"-MT">, HelpText<"Specify target for dependency">; -def MP : Flag<"-MP">, - HelpText<"Create phony target for each dependency (other than main file)">; -def MG : Flag<"-MG">, HelpText<"Add missing headers to dependency list">; //===----------------------------------------------------------------------===// // Diagnostic Options @@ -288,44 +222,11 @@ def diagnostic_log_file : Separate<"-diagnostic-log-file">, def diagnostic_serialized_file : Separate<"-serialize-diagnostic-file">, MetaVarName<"<filename>">, HelpText<"File for serializing diagnostics in a binary format">; -def fno_show_column : Flag<"-fno-show-column">, - HelpText<"Do not include column number on diagnostics">; -def fshow_column : Flag<"-fshow-column">, - HelpText<"Include column number on diagnostics">; -def fno_show_source_location : Flag<"-fno-show-source-location">, - HelpText<"Do not include source location information with diagnostics">; -def fshow_overloads_EQ : Joined<"-fshow-overloads=">, - HelpText<"Which overload candidates to show when overload resolution fails: " - "best|all; defaults to all">; -def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">, - HelpText<"Do not include source line and caret with diagnostics">; -def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">, - HelpText<"Do not include fixit information in diagnostics">; -def fno_diagnostics_show_note_include_stack : - Flag<"-fno-diagnostics-show-note-include-stack">, - HelpText<"Display include stacks for diagnostic notes">; -def w : Flag<"-w">, HelpText<"Suppress all warnings">; -def pedantic : Flag<"-pedantic">; -def pedantic_errors : Flag<"-pedantic-errors">; - -// This gets all -W options, including -Werror, -W[no-]system-headers, etc. The -// driver has stripped off -Wa,foo etc. The driver has also translated -W to -// -Wextra, so we don't need to worry about it. -def W : Joined<"-W">; - -def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, - HelpText<"Print source range spans in numeric form">; -def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, - HelpText<"Print fix-its in machine parseable form">; -def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, - HelpText<"Print option name with mappable diagnostics">; + def fdiagnostics_format : Separate<"-fdiagnostics-format">, HelpText<"Change diagnostic formatting to match IDE and command line tools">; def fdiagnostics_show_category : Separate<"-fdiagnostics-show-category">, HelpText<"Print diagnostic category">; -def fdiagnostics_show_note_include_stack : - Flag<"-fdiagnostics-show-note-include-stack">, - HelpText<"Display include stacks for diagnostic notes">; def ftabstop : Separate<"-ftabstop">, MetaVarName<"<N>">, HelpText<"Set the tab stop distance.">; def ferror_limit : Separate<"-ferror-limit">, MetaVarName<"<N>">, @@ -338,12 +239,8 @@ def fconstexpr_backtrace_limit : Separate<"-fconstexpr-backtrace-limit">, MetaVa HelpText<"Set the maximum number of entries to print in a constexpr evaluation backtrace (0 = no limit).">; def fmessage_length : Separate<"-fmessage-length">, MetaVarName<"<N>">, HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">; -def fcolor_diagnostics : Flag<"-fcolor-diagnostics">, - HelpText<"Use colors in diagnostics">; def Wno_rewrite_macros : Flag<"-Wno-rewrite-macros">, HelpText<"Silence ObjC rewriting warnings">; -def verify : Flag<"-verify">, - HelpText<"Verify emitted diagnostics and warnings">; //===----------------------------------------------------------------------===// // Frontend Options @@ -370,13 +267,10 @@ def code_completion_patterns : Flag<"-code-completion-patterns">, HelpText<"Include code patterns in code-completion results">; def no_code_completion_globals : Flag<"-no-code-completion-globals">, HelpText<"Do not include global declarations in code-completion results.">; +def code_completion_brief_comments : Flag<"-code-completion-brief-comments">, + HelpText<"Include brief documentation comments in code-completion results.">; def disable_free : Flag<"-disable-free">, HelpText<"Disable freeing of memory on exit">; -def help : Flag<"-help">, - HelpText<"Print this help text">; -def _help : Flag<"--help">, Alias<help>; -def x : Separate<"-x">, HelpText<"Input language type">; -def o : Separate<"-o">, MetaVarName<"<path>">, HelpText<"Specify output file">; def load : Separate<"-load">, MetaVarName<"<dsopath>">, HelpText<"Load the named plugin (dynamic shared object)">; def plugin : Separate<"-plugin">, MetaVarName<"<name>">, @@ -390,15 +284,16 @@ def resource_dir : Separate<"-resource-dir">, HelpText<"The directory which holds the compiler resource files">; def version : Flag<"-version">, HelpText<"Print the compiler version">; -def _version : Flag<"--version">, Alias<version>; +def ast_dump_filter : Separate<"-ast-dump-filter">, + MetaVarName<"<dump_filter>">, + HelpText<"Use with -ast-dump or -ast-print to dump/print only AST declaration" + " nodes having a certain substring in a qualified name. Use" + " -ast-list to list all filterable declaration node names.">; -def Action_Group : OptionGroup<"<action group>">; let Group = Action_Group in { def Eonly : Flag<"-Eonly">, HelpText<"Just run preprocessor, no output (for timings)">; -def E : Flag<"-E">, - HelpText<"Run preprocessor, emit preprocessed file">; def dump_raw_tokens : Flag<"-dump-raw-tokens">, HelpText<"Lex file in raw mode and dump raw tokens">; def analyze : Flag<"-analyze">, @@ -407,8 +302,6 @@ def dump_tokens : Flag<"-dump-tokens">, HelpText<"Run preprocessor, dump internal rep of tokens">; def init_only : Flag<"-init-only">, HelpText<"Only execute frontend initialization">; -def fsyntax_only : Flag<"-fsyntax-only">, - HelpText<"Run parser and perform semantic analysis">; def fixit : Flag<"-fixit">, HelpText<"Apply fix-it advice to the input source">; def fixit_EQ : Joined<"-fixit=">, @@ -420,6 +313,8 @@ def emit_html : Flag<"-emit-html">, HelpText<"Output input source as HTML">; def ast_print : Flag<"-ast-print">, HelpText<"Build ASTs and then pretty-print them">; +def ast_list : Flag<"-ast-list">, + HelpText<"Build ASTs and print the list of declaration node qualified names">; def ast_dump : Flag<"-ast-dump">, HelpText<"Build ASTs and then debug dump them">; def ast_dump_xml : Flag<"-ast-dump-xml">, @@ -434,10 +329,6 @@ def emit_pth : Flag<"-emit-pth">, HelpText<"Generate pre-tokenized header file">; def emit_pch : Flag<"-emit-pch">, HelpText<"Generate pre-compiled header file">; -def S : Flag<"-S">, - HelpText<"Emit native assembly code">; -def emit_llvm : Flag<"-emit-llvm">, - HelpText<"Build ASTs then convert to LLVM, emit .ll file">; def emit_llvm_bc : Flag<"-emit-llvm-bc">, HelpText<"Build ASTs then convert to LLVM, emit .bc file">; def emit_llvm_only : Flag<"-emit-llvm-only">, @@ -448,8 +339,6 @@ def emit_obj : Flag<"-emit-obj">, HelpText<"Emit native object files">; def rewrite_test : Flag<"-rewrite-test">, HelpText<"Rewriter playground">; -def rewrite_objc : Flag<"-rewrite-objc">, - HelpText<"Rewrite ObjC into C (code rewriter example)">; def rewrite_macros : Flag<"-rewrite-macros">, HelpText<"Expand macros without full preprocessing">; def migrate : Flag<"-migrate">, @@ -464,27 +353,11 @@ def arcmt_modify : Flag<"-arcmt-modify">, HelpText<"Apply modifications to files to conform to ARC">; def arcmt_migrate : Flag<"-arcmt-migrate">, HelpText<"Apply modifications and produces temporary files that conform to ARC">; -def arcmt_migrate_report_output : Separate<"-arcmt-migrate-report-output">, - HelpText<"Output path for the plist report">; -def arcmt_migrate_emit_arc_errors : Flag<"-arcmt-migrate-emit-errors">, - HelpText<"Emit ARC errors even if the migrator can fix them">; - -def objcmt_migrate_literals : Flag<"-objcmt-migrate-literals">, - HelpText<"Enable migration to modern ObjC literals">; -def objcmt_migrate_subscripting : Flag<"-objcmt-migrate-subscripting">, - HelpText<"Enable migration to modern ObjC subscripting">; - -def working_directory : JoinedOrSeparate<"-working-directory">, - HelpText<"Resolve file paths relative to the specified directory">; -def working_directory_EQ : Joined<"-working-directory=">, - Alias<working_directory>; def relocatable_pch : Flag<"-relocatable-pch">, HelpText<"Whether to build a relocatable precompiled header">; def print_stats : Flag<"-print-stats">, HelpText<"Print performance metrics and statistics">; -def ftime_report : Flag<"-ftime-report">, - HelpText<"Print the amount of time each phase of compilation takes">; def fdump_record_layouts : Flag<"-fdump-record-layouts">, HelpText<"Dump record layout information">; def fdump_record_layouts_simple : Flag<"-fdump-record-layouts-simple">, @@ -498,11 +371,6 @@ def fixit_recompile : Flag<"-fixit-recompile">, def fixit_to_temp : Flag<"-fixit-to-temporary">, HelpText<"Apply fix-it changes to temporary files">; -// Generic forwarding to LLVM options. This should only be used for debugging -// and experimental features. -def mllvm : Separate<"-mllvm">, - HelpText<"Additional arguments to forward to LLVM's option processing">; - def foverride_record_layout_EQ : Joined<"-foverride-record-layout=">, HelpText<"Override record layouts with those in the given file">; @@ -510,135 +378,31 @@ def foverride_record_layout_EQ : Joined<"-foverride-record-layout=">, // Language Options //===----------------------------------------------------------------------===// -def fno_builtin : Flag<"-fno-builtin">, - HelpText<"Disable implicit builtin knowledge of functions">; -def faltivec : Flag<"-faltivec">, - HelpText<"Enable AltiVec vector initializer syntax">; -def fno_access_control : Flag<"-fno-access-control">, - HelpText<"Disable C++ access control">; -def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">, - HelpText<"Don't assume that C++'s global operator new can't alias any pointer">; -def fgnu_keywords : Flag<"-fgnu-keywords">, - HelpText<"Allow GNU-extension keywords regardless of language standard">; -def fgnu89_inline : Flag<"-fgnu89-inline">, - HelpText<"Use the gnu89 inline semantics">; -def fno_inline : Flag<"-fno-inline">, - HelpText<"Disable use of the inline keyword">; -def fno_inline_functions : Flag<"-fno-inline-functions">, - HelpText<"Disable automatic function inlining">; -def fno_gnu_keywords : Flag<"-fno-gnu-keywords">, - HelpText<"Disallow GNU-extension keywords regardless of language standard">; -def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, - HelpText<"Allow '$' in identifiers">; -def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, - HelpText<"Disallow '$' in identifiers">; -def femit_all_decls : Flag<"-femit-all-decls">, - HelpText<"Emit all declarations, even if unused">; -def fblocks : Flag<"-fblocks">, - HelpText<"Enable the 'blocks' language feature">; def fblocks_runtime_optional : Flag<"-fblocks-runtime-optional">, HelpText<"Weakly link in the blocks runtime">; -def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">; -def fexceptions : Flag<"-fexceptions">, - HelpText<"Enable support for exception handling">; -def fobjc_exceptions : Flag<"-fobjc-exceptions">, - HelpText<"Enable Objective-C exceptions">; -def fcxx_exceptions : Flag<"-fcxx-exceptions">, - HelpText<"Enable C++ exceptions">; def fsjlj_exceptions : Flag<"-fsjlj-exceptions">, HelpText<"Use SjLj style exceptions">; -def ffast_math : Flag<"-ffast-math">, - HelpText<"Enable the *frontend*'s 'fast-math' mode. This has no effect on " - "optimizations, but provides a preprocessor macro __FAST_MATH__ the " - "same as GCC's -ffast-math flag.">; -def ffreestanding : Flag<"-ffreestanding">, - HelpText<"Assert that the compilation takes place in a freestanding environment">; -def fgnu_runtime : Flag<"-fgnu-runtime">, - HelpText<"Generate output compatible with the standard GNU Objective-C runtime">; def fhidden_weak_vtables : Flag<"-fhidden-weak-vtables">, HelpText<"Generate weak vtables and RTTI with hidden visibility">; -def std_EQ : Joined<"-std=">, - HelpText<"Language standard to compile for">; -def stdlib_EQ : Joined<"-stdlib=">, - HelpText<"C++ standard library to use">; -def fmath_errno : Flag<"-fmath-errno">, - HelpText<"Require math functions to indicate errors by setting errno">; -def fms_extensions : Flag<"-fms-extensions">, - HelpText<"Accept some non-standard constructs supported by the Microsoft compiler">; -def fms_compatibility : Flag<"-fms-compatibility">, - HelpText<"Enable Microsoft compatibility mode">; -def fmsc_version : Joined<"-fmsc-version=">, - HelpText<"Version of the Microsoft C/C++ compiler to report in _MSC_VER (0 = don't define it (default))">; -def fborland_extensions : Flag<"-fborland-extensions">, - HelpText<"Accept non-standard constructs supported by the Borland compiler">; def main_file_name : Separate<"-main-file-name">, HelpText<"Main file name to use for debug info">; -def fno_elide_constructors : Flag<"-fno-elide-constructors">, - HelpText<"Disable C++ copy constructor elision">; -def fno_lax_vector_conversions : Flag<"-fno-lax-vector-conversions">, - HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">; -def fno_operator_names : Flag<"-fno-operator-names">, - HelpText<"Do not treat C++ operator name keywords as synonyms for operators">; def fno_signed_char : Flag<"-fno-signed-char">, HelpText<"Char is unsigned">; -def fno_spell_checking : Flag<"-fno-spell-checking">, - HelpText<"Disable spell-checking">; -def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">, - HelpText<"Don't use __cxa_atexit for calling destructors">; def fconstant_string_class : Separate<"-fconstant-string-class">, MetaVarName<"<class name>">, HelpText<"Specify the class to use for constant Objective-C string objects.">; -def fno_constant_cfstrings : Flag<"-fno-constant-cfstrings">, - HelpText<"Enable creation of CodeFoundation-type constant strings">; -def fobjc_arc : Flag<"-fobjc-arc">, - HelpText<"Synthesize retain and release calls for Objective-C pointers">; def fobjc_arc_cxxlib_EQ : Joined<"-fobjc-arc-cxxlib=">, HelpText<"Objective-C++ Automatic Reference Counting standard library kind">; -def fobjc_arc_exceptions : Flag<"-fobjc-arc-exceptions">, - HelpText<"Use EH-safe code when synthesizing retains and releases in -fobjc-arc">; -def fobjc_runtime_has_arc : Flag<"-fobjc-runtime-has-arc">, - HelpText<"The target Objective-C runtime provides ARC entrypoints">; def fobjc_runtime_has_weak : Flag<"-fobjc-runtime-has-weak">, HelpText<"The target Objective-C runtime supports ARC weak operations">; -def fobjc_runtime_has_terminate : Flag<"-fobjc-runtime-has-terminate">, - HelpText<"The target Objective-C runtime provides an objc_terminate entrypoint">; -def fobjc_gc : Flag<"-fobjc-gc">, - HelpText<"Enable Objective-C garbage collection">; -def fobjc_gc_only : Flag<"-fobjc-gc-only">, - HelpText<"Use GC exclusively for Objective-C related memory management">; -def fapple_kext : Flag<"-fapple-kext">, - HelpText<"Use Apple's kernel extensions ABI">; def fobjc_dispatch_method_EQ : Joined<"-fobjc-dispatch-method=">, HelpText<"Objective-C dispatch method to use">; def fobjc_default_synthesize_properties : Flag<"-fobjc-default-synthesize-properties">, HelpText<"enable the default synthesis of Objective-C properties">; -def print_ivar_layout : Flag<"-print-ivar-layout">, - HelpText<"Enable Objective-C Ivar layout bitmap print trace">; -def fobjc_fragile_abi : Flag<"-fobjc-fragile-abi">, - HelpText<"Use Objective-C's fragile ABI">; -def fno_objc_infer_related_result_type : Flag< - "-fno-objc-infer-related-result-type">, - HelpText< - "do not infer Objective-C related result type based on method family">; -def ftrapv : Flag<"-ftrapv">, - HelpText<"Trap on integer overflow">; -def ftrapv_handler : Separate<"-ftrapv-handler">, - MetaVarName<"<function name>">, - HelpText<"Specify the function to be called on overflow.">; -def fwrapv : Flag<"-fwrapv">, - HelpText<"Treat signed integer overflow as two's complement">; def pic_level : Separate<"-pic-level">, HelpText<"Value for __PIC__">; def pie_level : Separate<"-pie-level">, HelpText<"Value for __PIE__">; -def pthread : Flag<"-pthread">, - HelpText<"Support POSIX threads in generated code">; -def fpack_struct : Separate<"-fpack-struct">, - HelpText<"Specify the default maximum struct packing alignment">; -def fpascal_strings : Flag<"-fpascal-strings">, - HelpText<"Recognize and construct Pascal-style string literals">; -def fno_rtti : Flag<"-fno-rtti">, - HelpText<"Disable generation of rtti information">; def fno_validate_pch : Flag<"-fno-validate-pch">, HelpText<"Disable validation of precompiled headers">; def dump_deserialized_pch_decls : Flag<"-dump-deserialized-decls">, @@ -647,44 +411,24 @@ def error_on_deserialized_pch_decl : Separate<"-error-on-deserialized-decl">, HelpText<"Emit error if a specific declaration is deserialized from PCH, for testing">; def error_on_deserialized_pch_decl_EQ : Joined<"-error-on-deserialized-decl=">, Alias<error_on_deserialized_pch_decl>; -def fshort_wchar : Flag<"-fshort-wchar">, - HelpText<"Force wchar_t to be a short unsigned int">; -def fshort_enums : Flag<"-fshort-enums">, - HelpText<"Allocate to an enum type only as many bytes as it needs for the declared range of possible values">; def static_define : Flag<"-static-define">, HelpText<"Should __STATIC__ be defined">; def stack_protector : Separate<"-stack-protector">, HelpText<"Enable stack protectors">; def fvisibility : Separate<"-fvisibility">, HelpText<"Default symbol visibility">; -def fvisibility_inlines_hidden : Flag<"-fvisibility-inlines-hidden">, - HelpText<"Give inline C++ member functions default visibility by default">; def ftemplate_depth : Separate<"-ftemplate-depth">, HelpText<"Maximum depth of recursive template instantiation">; def fconstexpr_depth : Separate<"-fconstexpr-depth">, HelpText<"Maximum depth of recursive constexpr function calls">; -def Wlarge_by_value_copy : Separate<"-Wlarge-by-value-copy">, - HelpText<"Warn if a function definition returns or accepts an object larger " - "in bytes that a given value">; -def Wlarge_by_value_copy_EQ : Joined<"-Wlarge-by-value-copy=">, - Alias<Wlarge_by_value_copy>; -def trigraphs : Flag<"-trigraphs">, - HelpText<"Process trigraph sequences">; -def fwritable_strings : Flag<"-fwritable-strings">, - HelpText<"Store string literals as writable data">; def fconst_strings : Flag<"-fconst-strings">, HelpText<"Use a const qualified type for string literals in C and ObjC">; def fno_const_strings : Flag<"-fno-const-strings">, HelpText<"Don't use a const qualified type for string literals in C and ObjC">; def fno_bitfield_type_align : Flag<"-fno-bitfield-type-align">, HelpText<"Ignore bit-field types when aligning structures">; -def traditional_cpp : Flag<"-traditional-cpp">, - HelpText<"Enable some traditional CPP emulation">; def ffake_address_space_map : Flag<"-ffake-address-space-map">, HelpText<"Use a fake address space map; OpenCL testing purposes only">; -def fdelayed_template_parsing : Flag<"-fdelayed-template-parsing">, - HelpText<"Parse templated function definitions at the end of the " - "translation unit ">; def funknown_anytype : Flag<"-funknown-anytype">, HelpText<"Enable parser support for the __unknown_anytype type; for testing purposes only">; def fdebugger_support : Flag<"-fdebugger-support">, @@ -692,13 +436,11 @@ def fdebugger_support : Flag<"-fdebugger-support">, def fdebugger_cast_result_to_id : Flag<"-fdebugger-cast-result-to-id">, HelpText<"Enable casting unknown expression results to id">; def fdebugger_objc_literal : Flag<"-fdebugger-objc-literal">, - HelpText<"Enable special debugger support for objective-C subscripting and literals">; + HelpText<"Enable special debugger support for Objective-C subscripting and literals">; def fdeprecated_macro : Flag<"-fdeprecated-macro">, HelpText<"Defines the __DEPRECATED macro">; def fno_deprecated_macro : Flag<"-fno-deprecated-macro">, HelpText<"Undefines the __DEPRECATED macro">; -def fapple_pragma_pack : Flag<"-fapple-pragma-pack">, - HelpText<"Enable Apple gcc-compatible #pragma pack handling">; //===----------------------------------------------------------------------===// // Header Search Options @@ -706,48 +448,19 @@ def fapple_pragma_pack : Flag<"-fapple-pragma-pack">, def nostdsysteminc : Flag<"-nostdsysteminc">, HelpText<"Disable standard system #include directories">; -def nostdincxx : Flag<"-nostdinc++">, - HelpText<"Disable standard #include directories for the C++ standard library">; -def nobuiltininc : Flag<"-nobuiltininc">, - HelpText<"Disable builtin #include directories">; -def fmodule_cache_path : Separate<"-fmodule-cache-path">, - MetaVarName<"<directory>">, - HelpText<"Specify the module cache path">; def fmodule_name : Joined<"-fmodule-name=">, MetaVarName<"<name>">, HelpText<"Specify the name of the module to build">; def fdisable_module_hash : Flag<"-fdisable-module-hash">, HelpText<"Disable the module hash">; -def fmodules : Flag<"-fmodules">, - HelpText<"Enable the 'modules' language feature">; - -def F : JoinedOrSeparate<"-F">, MetaVarName<"<directory>">, - HelpText<"Add directory to framework include search path">; -def I : JoinedOrSeparate<"-I">, MetaVarName<"<directory>">, - HelpText<"Add directory to include search path">; -def idirafter : JoinedOrSeparate<"-idirafter">, MetaVarName<"<directory>">, - HelpText<"Add directory to AFTER include search path">; -def index_header_map : Flag<"-index-header-map">, - HelpText<"Make the next included directory (-I or -F) an indexer header map">; -def iquote : JoinedOrSeparate<"-iquote">, MetaVarName<"<directory>">, - HelpText<"Add directory to QUOTE include search path">; def c_isystem : JoinedOrSeparate<"-c-isystem">, MetaVarName<"<directory>">, HelpText<"Add directory to the C SYSTEM include search path">; -def cxx_isystem : JoinedOrSeparate<"-cxx-isystem">, MetaVarName<"<directory>">, - HelpText<"Add directory to the C++ SYSTEM include search path">; def objc_isystem : JoinedOrSeparate<"-objc-isystem">, MetaVarName<"<directory>">, HelpText<"Add directory to the ObjC SYSTEM include search path">; def objcxx_isystem : JoinedOrSeparate<"-objcxx-isystem">, MetaVarName<"<directory>">, HelpText<"Add directory to the ObjC++ SYSTEM include search path">; -def iframework : JoinedOrSeparate<"-iframework">, MetaVarName<"<directory>">, - HelpText<"Add directory to SYSTEM framework search path">; -def isystem : JoinedOrSeparate<"-isystem">, MetaVarName<"<directory>">, - HelpText<"Add directory to SYSTEM include search path">; -def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">,MetaVarName<"<directory>">, - HelpText<"Add directory to SYSTEM include search path, " - "absolute paths are relative to -isysroot">; def internal_isystem : JoinedOrSeparate<"-internal-isystem">, MetaVarName<"<directory>">, HelpText<"Add directory to the internal system include search path; these " @@ -759,29 +472,19 @@ def internal_externc_isystem : JoinedOrSeparate<"-internal-externc-isystem">, "implicit extern \"C\" semantics; these are assumed to not be " "user-provided and are used to model system and standard headers' " "paths.">; -def iprefix : JoinedOrSeparate<"-iprefix">, MetaVarName<"<prefix>">, - HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">; -def iwithprefix : JoinedOrSeparate<"-iwithprefix">, MetaVarName<"<dir>">, - HelpText<"Set directory to SYSTEM include search path with prefix">; -def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">, - MetaVarName<"<dir>">, - HelpText<"Set directory to include search path with prefix">; -def isysroot : JoinedOrSeparate<"-isysroot">, MetaVarName<"<dir>">, - HelpText<"Set the system root directory (usually /)">; -def v : Flag<"-v">, HelpText<"Enable verbose output">; +def isystem_prefix : JoinedOrSeparate<"-isystem-prefix">, + MetaVarName<"<prefix>">, + HelpText<"Treat all #include paths starting with <prefix> as including a " + "system header.">; +def ino_system_prefix : JoinedOrSeparate<"-ino-system-prefix">, + MetaVarName<"<prefix>">, + HelpText<"Treat all #include paths starting with <prefix> as not including a " + "system header.">; //===----------------------------------------------------------------------===// // Preprocessor Options //===----------------------------------------------------------------------===// -def D : JoinedOrSeparate<"-D">, MetaVarName<"<macro>">, - HelpText<"Predefine the specified macro">; -def include_ : JoinedOrSeparate<"-include">, MetaVarName<"<file>">, EnumName<"include">, - HelpText<"Include file before parsing">; -def imacros : JoinedOrSeparate<"-imacros">, MetaVarName<"<file>">, - HelpText<"Include macros from file before parsing">; -def include_pch : Separate<"-include-pch">, MetaVarName<"<file>">, - HelpText<"Include precompiled header file">; def include_pth : Separate<"-include-pth">, MetaVarName<"<file>">, HelpText<"Include file before parsing">; def chain_include : Separate<"-chain-include">, MetaVarName<"<file>">, @@ -791,29 +494,8 @@ def preamble_bytes_EQ : Joined<"-preamble-bytes=">, "covering the first N bytes of the main file">; def token_cache : Separate<"-token-cache">, MetaVarName<"<path>">, HelpText<"Use specified token cache file">; -def U : JoinedOrSeparate<"-U">, MetaVarName<"<macro>">, - HelpText<"Undefine the specified macro">; -def undef : Flag<"-undef">, MetaVarName<"<macro>">, - HelpText<"undef all system defines">; def detailed_preprocessing_record : Flag<"-detailed-preprocessing-record">, HelpText<"include a detailed record of preprocessing actions">; -def mqdsp6_compat : Flag<"-mqdsp6-compat">, - HelpText<"Enable hexagon-qdsp6 backward compatibility">; - -//===----------------------------------------------------------------------===// -// Preprocessed Output Options -//===----------------------------------------------------------------------===// - -def P : Flag<"-P">, - HelpText<"Disable linemarker output in -E mode">; -def C : Flag<"-C">, - HelpText<"Enable comment output in -E mode">; -def CC : Flag<"-CC">, - HelpText<"Enable comment output in -E mode, even from macro expansions">; -def dM : Flag<"-dM">, - HelpText<"Print macro definitions in -E mode instead of normal output">; -def dD : Flag<"-dD">, - HelpText<"Print macro definitions in -E mode in addition to normal output">; //===----------------------------------------------------------------------===// // OpenCL Options @@ -840,3 +522,5 @@ def cl_std_EQ : Joined<"-cl-std=">, def fcuda_is_device : Flag<"-fcuda-is-device">, HelpText<"Generate code for CUDA device">; + +} // let Flags = [CC1Option] diff --git a/include/clang/Driver/CMakeLists.txt b/include/clang/Driver/CMakeLists.txt index abd4cfe..1277d51 100644 --- a/include/clang/Driver/CMakeLists.txt +++ b/include/clang/Driver/CMakeLists.txt @@ -2,10 +2,6 @@ clang_tablegen(Options.inc -gen-opt-parser-defs SOURCE Options.td TARGET ClangDriverOptions) -clang_tablegen(CC1Options.inc -gen-opt-parser-defs - SOURCE CC1Options.td - TARGET ClangCC1Options) - clang_tablegen(CC1AsOptions.inc -gen-opt-parser-defs SOURCE CC1AsOptions.td TARGET ClangCC1AsOptions) diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h index 6f1a221..7a10d56 100644 --- a/include/clang/Driver/Compilation.h +++ b/include/clang/Driver/Compilation.h @@ -76,6 +76,8 @@ public: const DerivedArgList &getArgs() const { return *TranslatedArgs; } + DerivedArgList &getArgs() { return *TranslatedArgs; } + ActionList &getActions() { return Actions; } const ActionList &getActions() const { return Actions; } diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index 0538334..6095055 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -156,6 +156,9 @@ private: /// used where an integrated CPP would). unsigned CCCUseClangCPP : 1; + /// \brief Force use of clang frontend. + unsigned ForcedClangUse : 1; + public: /// Use lazy precompiled headers for PCH support. unsigned CCCUsePCH : 1; @@ -174,7 +177,7 @@ private: /// \brief Cache of all the ToolChains in use by the driver. /// /// This maps from the string representation of a triple to a ToolChain - /// created targetting that triple. The driver owns all the ToolChain objects + /// created targeting that triple. The driver owns all the ToolChain objects /// stored in it, and will clean them up when torn down. mutable llvm::StringMap<ToolChain *> ToolChains; @@ -229,6 +232,9 @@ public: InstalledDir = Value; } + bool shouldForceClangUse() const { return ForcedClangUse; } + void setForcedClangUse(bool V = true) { ForcedClangUse = V; } + /// @} /// @name Primary Functionality /// @{ diff --git a/include/clang/Driver/Makefile b/include/clang/Driver/Makefile index 45bc40f..7d066c7 100644 --- a/include/clang/Driver/Makefile +++ b/include/clang/Driver/Makefile @@ -1,18 +1,14 @@ CLANG_LEVEL := ../../.. -BUILT_SOURCES = Options.inc CC1Options.inc CC1AsOptions.inc +BUILT_SOURCES = Options.inc CC1AsOptions.inc TABLEGEN_INC_FILES_COMMON = 1 include $(CLANG_LEVEL)/Makefile -$(ObjDir)/Options.inc.tmp : Options.td OptParser.td $(CLANG_TBLGEN) $(ObjDir)/.dir +$(ObjDir)/Options.inc.tmp : Options.td CC1Options.td OptParser.td $(CLANG_TBLGEN) $(ObjDir)/.dir $(Echo) "Building Clang Driver Option tables with tblgen" $(Verb) $(ClangTableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $< -$(ObjDir)/CC1Options.inc.tmp : CC1Options.td OptParser.td $(CLANG_TBLGEN) $(ObjDir)/.dir - $(Echo) "Building Clang CC1 Option tables with tblgen" - $(Verb) $(ClangTableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $< - $(ObjDir)/CC1AsOptions.inc.tmp : CC1AsOptions.td OptParser.td $(CLANG_TBLGEN) $(ObjDir)/.dir $(Echo) "Building Clang CC1 Assembler Option tables with tblgen" $(Verb) $(ClangTableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $< diff --git a/include/clang/Driver/ObjCRuntime.h b/include/clang/Driver/ObjCRuntime.h deleted file mode 100644 index 094873a..0000000 --- a/include/clang/Driver/ObjCRuntime.h +++ /dev/null @@ -1,49 +0,0 @@ -//===--- ObjCRuntime.h - Objective C runtime features -----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef CLANG_DRIVER_OBJCRUNTIME_H_ -#define CLANG_DRIVER_OBJCRUNTIME_H_ - -namespace clang { -namespace driver { - -class ObjCRuntime { -public: - enum Kind { GNU, NeXT }; -private: - unsigned RuntimeKind : 1; -public: - void setKind(Kind k) { RuntimeKind = k; } - Kind getKind() const { return static_cast<Kind>(RuntimeKind); } - - /// True if the runtime provides native ARC entrypoints. ARC may - /// still be usable without this if the tool-chain provides a - /// statically-linked runtime support library. - unsigned HasARC : 1; - - /// True if the runtime supports ARC zeroing __weak. - unsigned HasWeak : 1; - - /// \brief True if the runtime supports subscripting methods. - unsigned HasSubscripting : 1; - - /// True if the runtime provides the following entrypoint: - /// void objc_terminate(void); - /// If available, this will be called instead of abort() when an - /// exception is thrown out of an EH cleanup. - unsigned HasTerminate : 1; - - ObjCRuntime() : RuntimeKind(NeXT), HasARC(false), HasWeak(false), - HasSubscripting(false), HasTerminate(false) {} -}; - -} -} - -#endif diff --git a/include/clang/Driver/OptParser.td b/include/clang/Driver/OptParser.td index 25ecbc3..9e6d5b9 100644 --- a/include/clang/Driver/OptParser.td +++ b/include/clang/Driver/OptParser.td @@ -85,6 +85,9 @@ def HelpHidden : OptionFlag; // NoForward - The option should not be implicitly forwarded to other tools. def NoForward : OptionFlag; +// CC1Option - This option should be accepted by clang -cc1. +def CC1Option : OptionFlag; + // Define the option group class. class OptionGroup<string name> { @@ -134,5 +137,5 @@ class MetaVarName<string name> { string MetaVarName = name; } // FIXME: Have generator validate that these appear in correct position (and // aren't duplicated). -def INPUT : Option<"<input>", KIND_INPUT>, Flags<[DriverOption]>; +def INPUT : Option<"<input>", KIND_INPUT>, Flags<[DriverOption,CC1Option]>; def UNKNOWN : Option<"<unknown>", KIND_UNKNOWN>; diff --git a/include/clang/Driver/OptTable.h b/include/clang/Driver/OptTable.h index 3af6f8f..27bd119 100644 --- a/include/clang/Driver/OptTable.h +++ b/include/clang/Driver/OptTable.h @@ -25,7 +25,8 @@ namespace options { RenderAsInput = (1 << 5), RenderJoined = (1 << 6), RenderSeparate = (1 << 7), - Unsupported = (1 << 8) + Unsupported = (1 << 8), + CC1Option = (1 << 9) }; } @@ -34,7 +35,7 @@ namespace options { class InputArgList; class Option; - /// OptTable - Provide access to the Option info table. + /// \brief Provide access to the Option info table. /// /// The OptTable class provides a layer of indirection which allows Option /// instance to be created lazily. In the common case, only a few options will @@ -43,7 +44,7 @@ namespace options { /// parts of the driver still use Option instances where convenient. class OptTable { public: - /// Info - Entry for a single option instance in the option data table. + /// \brief Entry for a single option instance in the option data table. struct Info { const char *Name; const char *HelpText; @@ -56,17 +57,17 @@ namespace options { }; private: - /// The static option information table. + /// \brief The static option information table. const Info *OptionInfos; unsigned NumOptionInfos; - /// The lazily constructed options table, indexed by option::ID - 1. + /// \brief The lazily constructed options table, indexed by option::ID - 1. mutable Option **Options; - /// Prebound input option instance. + /// \brief Prebound input option instance. const Option *TheInputOption; - /// Prebound unknown option instance. + /// \brief Prebound unknown option instance. const Option *TheUnknownOption; /// The index of the first option which can be parsed (i.e., is not a @@ -87,10 +88,10 @@ namespace options { public: ~OptTable(); - /// getNumOptions - Return the total number of option classes. + /// \brief Return the total number of option classes. unsigned getNumOptions() const { return NumOptionInfos; } - /// getOption - Get the given \arg id's Option instance, lazily creating it + /// \brief Get the given Opt's Option instance, lazily creating it /// if necessary. /// /// \return The option, or null for the INVALID option id. @@ -106,72 +107,71 @@ namespace options { return Entry; } - /// getOptionName - Lookup the name of the given option. + /// \brief Lookup the name of the given option. const char *getOptionName(OptSpecifier id) const { return getInfo(id).Name; } - /// getOptionKind - Get the kind of the given option. + /// \brief Get the kind of the given option. unsigned getOptionKind(OptSpecifier id) const { return getInfo(id).Kind; } - /// getOptionGroupID - Get the group id for the given option. + /// \brief Get the group id for the given option. unsigned getOptionGroupID(OptSpecifier id) const { return getInfo(id).GroupID; } - /// isOptionHelpHidden - Should the help for the given option be hidden by - /// default. + /// \brief Should the help for the given option be hidden by default. bool isOptionHelpHidden(OptSpecifier id) const { return getInfo(id).Flags & options::HelpHidden; } - /// getOptionHelpText - Get the help text to use to describe this option. + /// \brief Get the help text to use to describe this option. const char *getOptionHelpText(OptSpecifier id) const { return getInfo(id).HelpText; } - /// getOptionMetaVar - Get the meta-variable name to use when describing + /// \brief Get the meta-variable name to use when describing /// this options values in the help text. const char *getOptionMetaVar(OptSpecifier id) const { return getInfo(id).MetaVar; } - /// ParseOneArg - Parse a single argument; returning the new argument and + /// \brief Parse a single argument; returning the new argument and /// updating Index. /// - /// \param [in] [out] Index - The current parsing position in the argument + /// \param [in,out] Index - The current parsing position in the argument /// string list; on return this will be the index of the next argument /// string to parse. /// - /// \return - The parsed argument, or 0 if the argument is missing values + /// \return The parsed argument, or 0 if the argument is missing values /// (in which case Index still points at the conceptual next argument string /// to parse). Arg *ParseOneArg(const ArgList &Args, unsigned &Index) const; - /// ParseArgs - Parse an list of arguments into an InputArgList. + /// \brief Parse an list of arguments into an InputArgList. /// - /// The resulting InputArgList will reference the strings in [ArgBegin, - /// ArgEnd), and their lifetime should extend past that of the returned + /// The resulting InputArgList will reference the strings in [\p ArgBegin, + /// \p ArgEnd), and their lifetime should extend past that of the returned /// InputArgList. /// /// The only error that can occur in this routine is if an argument is - /// missing values; in this case \arg MissingArgCount will be non-zero. + /// missing values; in this case \p MissingArgCount will be non-zero. /// /// \param ArgBegin - The beginning of the argument vector. /// \param ArgEnd - The end of the argument vector. /// \param MissingArgIndex - On error, the index of the option which could /// not be parsed. /// \param MissingArgCount - On error, the number of missing options. - /// \return - An InputArgList; on error this will contain all the options + /// \return An InputArgList; on error this will contain all the options /// which could be parsed. InputArgList *ParseArgs(const char* const *ArgBegin, const char* const *ArgEnd, unsigned &MissingArgIndex, unsigned &MissingArgCount) const; - /// PrintHelp - Render the help text for an option table. + /// \brief Render the help text for an option table. /// /// \param OS - The stream to write the help text to. /// \param Name - The name to use in the usage line. diff --git a/include/clang/Driver/Option.h b/include/clang/Driver/Option.h index 8243f6d..e6c4e12 100644 --- a/include/clang/Driver/Option.h +++ b/include/clang/Driver/Option.h @@ -91,6 +91,9 @@ namespace driver { /// This option should not be implicitly forwarded. bool NoForward : 1; + /// CC1Option - This option should be accepted by clang -cc1. + bool CC1Option : 1; + protected: Option(OptionClass Kind, OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias); @@ -126,6 +129,9 @@ namespace driver { bool hasNoForward() const { return NoForward; } void setNoForward(bool Value) { NoForward = Value; } + bool isCC1Option() const { return CC1Option; } + void setIsCC1Option(bool Value) { CC1Option = Value; } + bool hasForwardToGCC() const { return !NoForward && !DriverOption && !LinkerInput; } diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index b796771..c7698a2 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -19,6 +19,7 @@ include "OptParser.td" // Meta-group which defines def CompileOnly_Group : OptionGroup<"<CompileOnly group>">; +def Action_Group : OptionGroup<"<action group>">; def I_Group : OptionGroup<"<I group>">, Group<CompileOnly_Group>; def L_Group : OptionGroup<"<L group>">, Group<CompileOnly_Group>; @@ -32,10 +33,13 @@ def d_Group : OptionGroup<"<d group>">; def f_Group : OptionGroup<"<f group>">, Group<CompileOnly_Group>; def f_clang_Group : OptionGroup<"<f (clang-only) group>">, Group<CompileOnly_Group>; def g_Group : OptionGroup<"<g group>">; +def g_flags_Group : OptionGroup<"<g flags group>">; def i_Group : OptionGroup<"<i group>">, Group<CompileOnly_Group>; def clang_i_Group : OptionGroup<"<clang i group>">, Group<i_Group>; def m_Group : OptionGroup<"<m group>">, Group<CompileOnly_Group>; def m_x86_Features_Group : OptionGroup<"<m x86 features group>">, Group<m_Group>; +def m_hexagon_Features_Group : OptionGroup<"<m hexagon features group>">, Group<m_Group>; +def opencl_Group : OptionGroup<"<opencl group>">; def u_Group : OptionGroup<"<u group>">; def pedantic_Group : OptionGroup<"<pedantic group>">, @@ -120,18 +124,19 @@ def ccc_arrmt_modify : Flag<"-ccc-arrmt-modify">, Alias<ccc_arcmt_modify>; def ccc_arcmt_migrate : Separate<"-ccc-arcmt-migrate">, CCCDriverOpt, HelpText<"Apply modifications and produces temporary files that conform to ARC">; def arcmt_migrate_report_output : Separate<"-arcmt-migrate-report-output">, - HelpText<"Output path for the plist report">; + HelpText<"Output path for the plist report">, Flags<[CC1Option]>; def arcmt_migrate_emit_arc_errors : Flag<"-arcmt-migrate-emit-errors">, - HelpText<"Emit ARC errors even if the migrator can fix them">; + HelpText<"Emit ARC errors even if the migrator can fix them">, + Flags<[CC1Option]>; def _migrate : Flag<"--migrate">, Flags<[DriverOption]>, HelpText<"Run the migrator">; def ccc_objcmt_migrate : Separate<"-ccc-objcmt-migrate">, CCCDriverOpt, HelpText<"Apply modifications and produces temporary files to migrate to " "modern ObjC syntax">; -def objcmt_migrate_literals : Flag<"-objcmt-migrate-literals">, +def objcmt_migrate_literals : Flag<"-objcmt-migrate-literals">, Flags<[CC1Option]>, HelpText<"Enable migration to modern ObjC literals">; -def objcmt_migrate_subscripting : Flag<"-objcmt-migrate-subscripting">, +def objcmt_migrate_subscripting : Flag<"-objcmt-migrate-subscripting">, Flags<[CC1Option]>, HelpText<"Enable migration to modern ObjC subscripting">; // Make sure all other -ccc- options are rejected. @@ -146,66 +151,76 @@ def _HASH_HASH_HASH : Flag<"-###">, Flags<[DriverOption]>, def _DASH_DASH : Flag<"--">, Flags<[DriverOption]>; def A : JoinedOrSeparate<"-A">; def B : JoinedOrSeparate<"-B">; -def CC : Flag<"-CC">; -def C : Flag<"-C">; -def D : JoinedOrSeparate<"-D">, Group<CompileOnly_Group>; -def E : Flag<"-E">, Flags<[DriverOption]>, +def CC : Flag<"-CC">, Flags<[CC1Option]>; +def C : Flag<"-C">, Flags<[CC1Option]>; +def D : JoinedOrSeparate<"-D">, Group<CompileOnly_Group>, Flags<[CC1Option]>; +def E : Flag<"-E">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>, HelpText<"Only run the preprocessor">; -def F : JoinedOrSeparate<"-F">, Flags<[RenderJoined]>; +def F : JoinedOrSeparate<"-F">, Flags<[RenderJoined,CC1Option]>, + HelpText<"Add directory to framework include search path">; def G : Separate<"-G">, Flags<[DriverOption]>; -def H : Flag<"-H">; +def H : Flag<"-H">, Flags<[CC1Option]>, + HelpText<"Show header includes and nesting depth">; def I_ : Flag<"-I-">, Group<I_Group>; -def I : JoinedOrSeparate<"-I">, Group<I_Group>; +def I : JoinedOrSeparate<"-I">, Group<I_Group>, Flags<[CC1Option]>, + HelpText<"Add directory to include search path">; def L : JoinedOrSeparate<"-L">, Flags<[RenderJoined]>; def MD : Flag<"-MD">, Group<M_Group>; def MF : JoinedOrSeparate<"-MF">, Group<M_Group>; -def MG : Flag<"-MG">, Group<M_Group>; +def MG : Flag<"-MG">, Group<M_Group>, Flags<[CC1Option]>, + HelpText<"Add missing headers to dependency list">; def MMD : Flag<"-MMD">, Group<M_Group>; def MM : Flag<"-MM">, Group<M_Group>; -def MP : Flag<"-MP">, Group<M_Group>; -def MQ : JoinedOrSeparate<"-MQ">, Group<M_Group>; -def MT : JoinedOrSeparate<"-MT">, Group<M_Group>; +def MP : Flag<"-MP">, Group<M_Group>, Flags<[CC1Option]>, + HelpText<"Create phony target for each dependency (other than main file)">; +def MQ : JoinedOrSeparate<"-MQ">, Group<M_Group>, Flags<[CC1Option]>, + HelpText<"Specify target to quote for dependency">; +def MT : JoinedOrSeparate<"-MT">, Group<M_Group>, Flags<[CC1Option]>, + HelpText<"Specify target for dependency">; def Mach : Flag<"-Mach">; def M : Flag<"-M">, Group<M_Group>; -def O0 : Joined<"-O0">, Group<O_Group>; -def O4 : Joined<"-O4">, Group<O_Group>; +def O0 : Joined<"-O0">, Group<O_Group>, Flags<[CC1Option]>; +def O4 : Joined<"-O4">, Group<O_Group>, Flags<[CC1Option]>; def ObjCXX : Flag<"-ObjC++">, Flags<[DriverOption]>, HelpText<"Treat source input files as Objective-C++ inputs">; def ObjC : Flag<"-ObjC">, Flags<[DriverOption]>, HelpText<"Treat source input files as Objective-C inputs">; -def O : Joined<"-O">, Group<O_Group>; -def P : Flag<"-P">; +def O : Joined<"-O">, Group<O_Group>, Flags<[CC1Option]>; +def P : Flag<"-P">, Flags<[CC1Option]>, + HelpText<"Disable linemarker output in -E mode">; def Qn : Flag<"-Qn">; def Qunused_arguments : Flag<"-Qunused-arguments">, Flags<[DriverOption]>, HelpText<"Don't emit warning for unused driver arguments">; def Q : Flag<"-Q">; def R : Flag<"-R">; -def S : Flag<"-S">, Flags<[DriverOption]>, +def S : Flag<"-S">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>, HelpText<"Only run preprocess and compilation steps">; def Tbss : JoinedOrSeparate<"-Tbss">, Group<T_Group>; def Tdata : JoinedOrSeparate<"-Tdata">, Group<T_Group>; def Ttext : JoinedOrSeparate<"-Ttext">, Group<T_Group>; def T : JoinedOrSeparate<"-T">, Group<T_Group>; -def U : JoinedOrSeparate<"-U">, Group<CompileOnly_Group>; +def U : JoinedOrSeparate<"-U">, Group<CompileOnly_Group>, Flags<[CC1Option]>; def V : JoinedOrSeparate<"-V">, Flags<[DriverOption, Unsupported]>; def Wa_COMMA : CommaJoined<"-Wa,">, HelpText<"Pass the comma separated arguments in <arg> to the assembler">, MetaVarName<"<arg>">; -def Wall : Flag<"-Wall">, Group<W_Group>; -def Wdeprecated : Flag<"-Wdeprecated">, Group<W_Group>; -def Wno_deprecated : Flag<"-Wno-deprecated">, Group<W_Group>; -def Wextra : Flag<"-Wextra">, Group<W_Group>; +def Wall : Flag<"-Wall">, Group<W_Group>, Flags<[CC1Option]>; +def Wdeprecated : Flag<"-Wdeprecated">, Group<W_Group>, Flags<[CC1Option]>; +def Wno_deprecated : Flag<"-Wno-deprecated">, Group<W_Group>, Flags<[CC1Option]>; +def Wextra : Flag<"-Wextra">, Group<W_Group>, Flags<[CC1Option]>; def Wl_COMMA : CommaJoined<"-Wl,">, Flags<[LinkerInput, RenderAsInput]>, HelpText<"Pass the comma separated arguments in <arg> to the linker">, MetaVarName<"<arg>">; -def Wno_nonportable_cfstrings : Joined<"-Wno-nonportable-cfstrings">, Group<W_Group>; -def Wnonportable_cfstrings : Joined<"-Wnonportable-cfstrings">, Group<W_Group>; +def Wno_nonportable_cfstrings : Joined<"-Wno-nonportable-cfstrings">, Group<W_Group>, + Flags<[CC1Option]>; +def Wnonportable_cfstrings : Joined<"-Wnonportable-cfstrings">, Group<W_Group>, + Flags<[CC1Option]>; def Wp_COMMA : CommaJoined<"-Wp,">, HelpText<"Pass the comma separated arguments in <arg> to the preprocessor">, MetaVarName<"<arg>">; -def Wwrite_strings : Flag<"-Wwrite-strings">, Group<W_Group>; -def Wno_write_strings : Flag<"-Wno-write-strings">, Group<W_Group>; -def W_Joined : Joined<"-W">, Group<W_Group>; +def Wwrite_strings : Flag<"-Wwrite-strings">, Group<W_Group>, Flags<[CC1Option]>; +def Wno_write_strings : Flag<"-Wno-write-strings">, Group<W_Group>, Flags<[CC1Option]>; +def W_Joined : Joined<"-W">, Group<W_Group>, Flags<[CC1Option]>; def Xanalyzer : Separate<"-Xanalyzer">, HelpText<"Pass <arg> to the static analyzer">, MetaVarName<"<arg>">; def Xarch__ : JoinedAndSeparate<"-Xarch_">, Flags<[DriverOption]>; @@ -233,20 +248,29 @@ def bind__at__load : Flag<"-bind_at_load">; def bundle__loader : Separate<"-bundle_loader">; def bundle : Flag<"-bundle">; def b : JoinedOrSeparate<"-b">, Flags<[Unsupported]>; +def cl_kernel_arg_info : Flag<"-cl-kernel-arg-info">, Flags<[CC1Option]>, Group<opencl_Group>, +HelpText<"OpenCL only. This option allows the compiler to store information about the arguments of a kernel(s)"> ; def client__name : JoinedOrSeparate<"-client_name">; def combine : Flag<"-combine">, Flags<[DriverOption, Unsupported]>; def compatibility__version : JoinedOrSeparate<"-compatibility_version">; def coverage : Flag<"-coverage">; def cpp_precomp : Flag<"-cpp-precomp">, Group<clang_ignored_f_Group>; def current__version : JoinedOrSeparate<"-current_version">; -def cxx_isystem : JoinedOrSeparate<"-cxx-isystem">, Group<clang_i_Group>; +def cxx_isystem : JoinedOrSeparate<"-cxx-isystem">, Group<clang_i_Group>, + HelpText<"Add directory to the C++ SYSTEM include search path">, Flags<[CC1Option]>, + MetaVarName<"<directory>">; def c : Flag<"-c">, Flags<[DriverOption]>, HelpText<"Only run preprocess, compile, and assemble steps">; def dA : Flag<"-dA">, Group<d_Group>; -def dD : Flag<"-dD">, Group<d_Group>; -def dM : Flag<"-dM">, Group<d_Group>; +def dD : Flag<"-dD">, Group<d_Group>, Flags<[CC1Option]>, + HelpText<"Print macro definitions in -E mode in addition to normal output">; +def dM : Flag<"-dM">, Group<d_Group>, Flags<[CC1Option]>, + HelpText<"Print macro definitions in -E mode instead of normal output">; def dead__strip : Flag<"-dead_strip">; -def dependency_file : Separate<"-dependency-file">; +def dependency_file : Separate<"-dependency-file">, Flags<[CC1Option]>, + HelpText<"Filename (or -) to write dependency output to">; +def dependency_dot : Separate<"-dependency-dot">, Flags<[CC1Option]>, + HelpText<"Filename to write DOT-formatted header dependencies to">; def dumpmachine : Flag<"-dumpmachine">; def dumpspecs : Flag<"-dumpspecs">, Flags<[Unsupported]>; def dumpversion : Flag<"-dumpversion">; @@ -259,7 +283,7 @@ def d_Flag : Flag<"-d">, Group<d_Group>; def d_Joined : Joined<"-d">, Group<d_Group>; def emit_ast : Flag<"-emit-ast">, HelpText<"Emit Clang AST files for source inputs">; -def emit_llvm : Flag<"-emit-llvm">, +def emit_llvm : Flag<"-emit-llvm">, Flags<[CC1Option]>, Group<Action_Group>, HelpText<"Use the LLVM representation for assembler and object files">; def exported__symbols__list : Separate<"-exported_symbols_list">; def e : JoinedOrSeparate<"-e">; @@ -269,13 +293,18 @@ def fPIE : Flag<"-fPIE">, Group<f_Group>; def fno_PIE : Flag<"-fno-PIE">, Group<f_Group>; def faccess_control : Flag<"-faccess-control">, Group<f_Group>; def fallow_unsupported : Flag<"-fallow-unsupported">, Group<f_Group>; -def faltivec : Flag<"-faltivec">, Group<f_Group>; -def fapple_kext : Flag<"-fapple-kext">, Group<f_Group>; -def fapple_pragma_pack : Flag<"-fapple-pragma-pack">, Group<f_Group>; -def faddress_sanitizer : Flag<"-faddress-sanitizer">, Group<f_Group>; -def fno_address_sanitizer : Flag<"-fno-address-sanitizer">, Group<f_Group>; -def fthread_sanitizer : Flag<"-fthread-sanitizer">, Group<f_Group>; -def fno_thread_sanitizer : Flag<"-fno-thread-sanitizer">, Group<f_Group>; +def faltivec : Flag<"-faltivec">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Enable AltiVec vector initializer syntax">; +def fapple_kext : Flag<"-fapple-kext">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Use Apple's kernel extensions ABI">; +def fapple_pragma_pack : Flag<"-fapple-pragma-pack">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Enable Apple gcc-compatible #pragma pack handling">; +def faddress_sanitizer : Flag<"-faddress-sanitizer">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Enable AddressSanitizer instrumentation (memory error detection)">; +def fno_address_sanitizer : Flag<"-fno-address-sanitizer">, Group<f_Group>, Flags<[CC1Option]>; +def fthread_sanitizer : Flag<"-fthread-sanitizer">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Enable ThreadSanitizer instrumentation (race detection)">; +def fno_thread_sanitizer : Flag<"-fno-thread-sanitizer">, Group<f_Group>, Flags<[CC1Option]>; def fasm : Flag<"-fasm">, Group<f_Group>; def fasm_blocks : Flag<"-fasm-blocks">, Group<f_Group>; @@ -286,17 +315,24 @@ def fastcp : Flag<"-fastcp">, Group<f_Group>; def fastf : Flag<"-fastf">, Group<f_Group>; def fast : Flag<"-fast">, Group<f_Group>; def fasynchronous_unwind_tables : Flag<"-fasynchronous-unwind-tables">, Group<f_Group>; -def fblocks : Flag<"-fblocks">, Group<f_Group>; +def fblocks : Flag<"-fblocks">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Enable the 'blocks' language feature">; def fbootclasspath_EQ : Joined<"-fbootclasspath=">, Group<f_Group>; -def fborland_extensions : Flag<"-fborland-extensions">, Group<f_Group>; +def fborland_extensions : Flag<"-fborland-extensions">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Accept non-standard constructs supported by the Borland compiler">; +def fbounds_checking : Flag<"-fbounds-checking">, Group<f_Group>, + HelpText<"Enable run-time bounds checks.">; +def fbounds_checking_EQ : Joined<"-fbounds-checking=">, Flags<[CC1Option]>, + Group<f_Group>; def fbuiltin_strcat : Flag<"-fbuiltin-strcat">, Group<f_Group>; def fbuiltin_strcpy : Flag<"-fbuiltin-strcpy">, Group<f_Group>; def fbuiltin : Flag<"-fbuiltin">, Group<f_Group>; def fcaret_diagnostics : Flag<"-fcaret-diagnostics">, Group<f_Group>; -def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">, - Group<f_Group>, HelpText<"Generate runtime checks for undefined behavior.">; +def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">, Flags<[CC1Option]>, + Group<f_Group>, HelpText<"Generate runtime checks for undefined behavior.">; def fclasspath_EQ : Joined<"-fclasspath=">, Group<f_Group>; -def fcolor_diagnostics : Flag<"-fcolor-diagnostics">, Group<f_Group>; +def fcolor_diagnostics : Flag<"-fcolor-diagnostics">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Use colors in diagnostics">; def fcommon : Flag<"-fcommon">, Group<f_Group>; def fcompile_resource_EQ : Joined<"-fcompile-resource=">, Group<f_Group>; def fconstant_cfstrings : Flag<"-fconstant-cfstrings">, Group<f_Group>; @@ -306,32 +342,53 @@ def fconstexpr_backtrace_limit_EQ : Joined<"-fconstexpr-backtrace-limit=">, Group<f_Group>; def fno_crash_diagnostics : Flag<"-fno-crash-diagnostics">, Group<f_clang_Group>, Flags<[NoArgumentUnused]>; def fcreate_profile : Flag<"-fcreate-profile">, Group<f_Group>; -def fcxx_exceptions: Flag<"-fcxx-exceptions">, Group<f_Group>; +def fcxx_exceptions: Flag<"-fcxx-exceptions">, Group<f_Group>, + HelpText<"Enable C++ exceptions">, Flags<[CC1Option]>; def fcxx_modules : Flag <"-fcxx-modules">, Group<f_Group>, Flags<[NoForward]>; def fdebug_pass_arguments : Flag<"-fdebug-pass-arguments">, Group<f_Group>; def fdebug_pass_structure : Flag<"-fdebug-pass-structure">, Group<f_Group>; def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group<f_clang_Group>; -def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, Group<f_clang_Group>; -def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, Group<f_clang_Group>; -def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group<f_Group>; -def fdiagnostics_show_note_include_stack : Flag<"-fdiagnostics-show-note-include-stack">, Group<f_Group>; +def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, Group<f_clang_Group>, + Flags<[CC1Option]>, HelpText<"Print fix-its in machine parseable form">; +def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, + Group<f_clang_Group>, Flags<[CC1Option]>, + HelpText<"Print source range spans in numeric form">; +def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group<f_Group>, + Flags<[CC1Option]>, HelpText<"Print option name with mappable diagnostics">; +def fdiagnostics_show_name : Flag<"-fdiagnostics-show-name">, Group<f_Group>, + Flags<[CC1Option]>, HelpText<"Print diagnostic name">; +def fdiagnostics_show_note_include_stack : Flag<"-fdiagnostics-show-note-include-stack">, + Group<f_Group>, Flags<[CC1Option]>, HelpText<"Display include stacks for diagnostic notes">; def fdiagnostics_format_EQ : Joined<"-fdiagnostics-format=">, Group<f_clang_Group>; def fdiagnostics_show_category_EQ : Joined<"-fdiagnostics-show-category=">, Group<f_clang_Group>; -def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, Group<f_Group>; +def fdiagnostics_show_template_tree : Flag<"-fdiagnostics-show-template-tree">, + Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Print a template comparison tree for differing templates">; +def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, Group<f_Group>, + HelpText<"Allow '$' in identifiers">, Flags<[CC1Option]>; def fdwarf2_cfi_asm : Flag<"-fdwarf2-cfi-asm">, Group<f_Group>; -def fno_dwarf2_cfi_asm : Flag<"-fno-dwarf2-cfi-asm">, Group<f_Group>; +def fno_dwarf2_cfi_asm : Flag<"-fno-dwarf2-cfi-asm">, Group<f_Group>, Flags<[CC1Option]>; def fdwarf_directory_asm : Flag<"-fdwarf-directory-asm">, Group<f_Group>; -def fno_dwarf_directory_asm : Flag<"-fno-dwarf-directory-asm">, Group<f_Group>; +def fno_dwarf_directory_asm : Flag<"-fno-dwarf-directory-asm">, Group<f_Group>, Flags<[CC1Option]>; def felide_constructors : Flag<"-felide-constructors">, Group<f_Group>; +def fno_elide_type : Flag<"-fno-elide-type">, Group<f_Group>, + Flags<[CC1Option]>, + HelpText<"Do not elide types when printing diagnostics">; def feliminate_unused_debug_symbols : Flag<"-feliminate-unused-debug-symbols">, Group<f_Group>; -def femit_all_decls : Flag<"-femit-all-decls">, Group<f_Group>; +def femit_all_decls : Flag<"-femit-all-decls">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Emit all declarations, even if unused">; def fencoding_EQ : Joined<"-fencoding=">, Group<f_Group>; def ferror_limit_EQ : Joined<"-ferror-limit=">, Group<f_Group>; -def fexceptions : Flag<"-fexceptions">, Group<f_Group>; +def fexceptions : Flag<"-fexceptions">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Enable support for exception handling">; def fextdirs_EQ : Joined<"-fextdirs=">, Group<f_Group>; def fhosted : Flag<"-fhosted">, Group<f_Group>; -def ffast_math : Flag<"-ffast-math">, Group<f_Group>; -def fmath_errno : Flag<"-fmath-errno">, Group<f_Group>; +def ffast_math : Flag<"-ffast-math">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Enable the *frontend*'s 'fast-math' mode. This has no effect on " + "optimizations, but provides a preprocessor macro __FAST_MATH__ the " + "same as GCC's -ffast-math flag.">; +def fmath_errno : Flag<"-fmath-errno">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Require math functions to indicate errors by setting errno">; def fno_math_errno : Flag<"-fno-math-errno">, Group<f_Group>; def fsignaling_math : Flag<"-fsignaling-math">, Group<f_Group>; def fno_signaling_math : Flag<"-fno-signaling-math">, Group<f_Group>; @@ -343,7 +400,7 @@ def fassociative_math : Flag<"-fassociative-math">, Group<f_Group>; def fno_associative_math : Flag<"-fno-associative-math">, Group<f_Group>; def freciprocal_math : Flag<"-freciprocal-math">, Group<f_Group>; def fno_reciprocal_math : Flag<"-fno-reciprocal-math">, Group<f_Group>; -def ffinite_math_only : Flag<"-ffinite-math-only">, Group<f_Group>; +def ffinite_math_only : Flag<"-ffinite-math-only">, Group<f_Group>, Flags<[CC1Option]>; def fno_finite_math_only : Flag<"-fno-finite-math-only">, Group<f_Group>; def fsigned_zeros : Flag<"-fsigned-zeros">, Group<f_Group>; def fno_signed_zeros : Flag<"-fno-signed-zeros">, Group<f_Group>; @@ -352,31 +409,41 @@ def fno_honor_nans : Flag<"-fno-honor-nans">, Group<f_Group>; def fhonor_infinities : Flag<"-fhonor-infinities">, Group<f_Group>; def fno_honor_infinities : Flag<"-fno-honor-infinities">, Group<f_Group>; // Sic. This option was misspelled originally. -def fhonor_infinites : Flag<"-fhonor-infinites">, Group<f_Group>, - Alias<fhonor_infinities>; -def fno_honor_infinites : Flag<"-fno-honor-infinites">, Group<f_Group>, - Alias<fno_honor_infinities>; +def fhonor_infinites : Flag<"-fhonor-infinites">, Alias<fhonor_infinities>; +def fno_honor_infinites : Flag<"-fno-honor-infinites">, Alias<fno_honor_infinities>; def ftrapping_math : Flag<"-ftrapping-math">, Group<f_Group>; def fno_trapping_math : Flag<"-fno-trapping-math">, Group<f_Group>; +def ffp_contract : Joined<"-ffp-contract=">, Group<f_Group>, + Flags<[CC1Option]>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)" + " | on (according to FP_CONTRACT pragma, default) | off (never fuse)">; def ffor_scope : Flag<"-ffor-scope">, Group<f_Group>; def fno_for_scope : Flag<"-fno-for-scope">, Group<f_Group>; -def ffreestanding : Flag<"-ffreestanding">, Group<f_Group>; -def fgnu_keywords : Flag<"-fgnu-keywords">, Group<f_Group>; -def fgnu89_inline : Flag<"-fgnu89-inline">, Group<f_Group>; +def frewrite_includes : Flag<"-frewrite-includes">, Group<f_Group>, + Flags<[CC1Option]>; +def fno_rewrite_includes : Flag<"-fno-rewrite-includes">, Group<f_Group>; + +def ffreestanding : Flag<"-ffreestanding">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Assert that the compilation takes place in a freestanding environment">; +def fgnu_keywords : Flag<"-fgnu-keywords">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Allow GNU-extension keywords regardless of language standard">; +def fgnu89_inline : Flag<"-fgnu89-inline">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Use the gnu89 inline semantics">; def fno_gnu89_inline : Flag<"-fno-gnu89-inline">, Group<f_Group>; -def fgnu_runtime : Flag<"-fgnu-runtime">, Group<f_Group>; -def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">; +def fgnu_runtime : Flag<"-fgnu-runtime">, Group<f_Group>, + HelpText<"Generate output compatible with the standard GNU Objective-C runtime">; +def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">, Flags<[CC1Option]>; def filelist : Separate<"-filelist">, Flags<[LinkerInput]>; def findirect_virtual_calls : Flag<"-findirect-virtual-calls">, Alias<fapple_kext>; def finline_functions : Flag<"-finline-functions">, Group<clang_ignored_f_Group>; def finline : Flag<"-finline">, Group<clang_ignored_f_Group>; -def finstrument_functions : Flag<"-finstrument-functions">, Group<f_Group>; +def finstrument_functions : Flag<"-finstrument-functions">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Generate calls to instrument function entry and exit">; def fkeep_inline_functions : Flag<"-fkeep-inline-functions">, Group<clang_ignored_f_Group>; def flat__namespace : Flag<"-flat_namespace">; def flax_vector_conversions : Flag<"-flax-vector-conversions">, Group<f_Group>; -def flimit_debug_info : Flag<"-flimit-debug-info">, Group<f_Group>, +def flimit_debug_info : Flag<"-flimit-debug-info">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Limit debug information produced to reduce size of debug binary">; def flimited_precision_EQ : Joined<"-flimited-precision=">, Group<f_Group>; def flto : Flag<"-flto">, Group<f_Group>; @@ -385,49 +452,73 @@ def fmacro_backtrace_limit_EQ : Joined<"-fmacro-backtrace-limit=">, Group<f_Group>; def fmerge_all_constants : Flag<"-fmerge-all-constants">, Group<f_Group>; def fmessage_length_EQ : Joined<"-fmessage-length=">, Group<f_Group>; -def fms_extensions : Flag<"-fms-extensions">, Group<f_Group>; -def fms_compatibility : Flag<"-fms-compatibility">, Group<f_Group>; -def fmsc_version : Joined<"-fmsc-version=">, Group<f_Group>; -def fdelayed_template_parsing : Flag<"-fdelayed-template-parsing">, Group<f_Group>; +def fms_extensions : Flag<"-fms-extensions">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Accept some non-standard constructs supported by the Microsoft compiler">; +def fenable_experimental_ms_inline_asm : Flag<"-fenable-experimental-ms-inline-asm">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Enable support for Microsoft style inine assembly">; +def fms_compatibility : Flag<"-fms-compatibility">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Enable Microsoft compatibility mode">; +def fmsc_version : Joined<"-fmsc-version=">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Version of the Microsoft C/C++ compiler to report in _MSC_VER (0 = don't define it (default))">; +def fdelayed_template_parsing : Flag<"-fdelayed-template-parsing">, Group<f_Group>, + HelpText<"Parse templated function definitions at the end of the " + "translation unit ">, Flags<[CC1Option]>; def fmodule_cache_path : Separate<"-fmodule-cache-path">, Group<i_Group>, - Flags<[NoForward]>; -def fmodules : Flag <"-fmodules">, Group<f_Group>, Flags<[NoForward]>; + Flags<[NoForward,CC1Option]>, MetaVarName<"<directory>">, + HelpText<"Specify the module cache path">; +def fmodules : Flag <"-fmodules">, Group<f_Group>, Flags<[NoForward,CC1Option]>, + HelpText<"Enable the 'modules' language feature">; def fmudflapth : Flag<"-fmudflapth">, Group<f_Group>; def fmudflap : Flag<"-fmudflap">, Group<f_Group>; def fnested_functions : Flag<"-fnested-functions">, Group<f_Group>; def fnext_runtime : Flag<"-fnext-runtime">, Group<f_Group>; -def fno_access_control : Flag<"-fno-access-control">, Group<f_Group>; +def fno_access_control : Flag<"-fno-access-control">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Disable C++ access control">; def fno_apple_pragma_pack : Flag<"-fno-apple-pragma-pack">, Group<f_Group>; def fno_asm : Flag<"-fno-asm">, Group<f_Group>; def fno_asynchronous_unwind_tables : Flag<"-fno-asynchronous-unwind-tables">, Group<f_Group>; -def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">, Group<f_Group>; +def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">, Group<f_Group>, + HelpText<"Don't assume that C++'s global operator new can't alias any pointer">, + Flags<[CC1Option]>; def fno_blocks : Flag<"-fno-blocks">, Group<f_Group>; def fno_borland_extensions : Flag<"-fno-borland-extensions">, Group<f_Group>; def fno_builtin_strcat : Flag<"-fno-builtin-strcat">, Group<f_Group>; def fno_builtin_strcpy : Flag<"-fno-builtin-strcpy">, Group<f_Group>; -def fno_builtin : Flag<"-fno-builtin">, Group<f_Group>; -def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">, Group<f_Group>; +def fno_builtin : Flag<"-fno-builtin">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Disable implicit builtin knowledge of functions">; +def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">, Group<f_Group>, + Flags<[CC1Option]>; def fno_color_diagnostics : Flag<"-fno-color-diagnostics">, Group<f_Group>; -def fno_common : Flag<"-fno-common">, Group<f_Group>; -def fno_constant_cfstrings : Flag<"-fno-constant-cfstrings">, Group<f_Group>; +def fno_common : Flag<"-fno-common">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Compile common globals like normal definitions">; +def fno_constant_cfstrings : Flag<"-fno-constant-cfstrings">, Group<f_Group>, + Flags<[CC1Option]>, + HelpText<"Disable creation of CodeFoundation-type constant strings">; def fno_cxx_exceptions: Flag<"-fno-cxx-exceptions">, Group<f_Group>; def fno_cxx_modules : Flag <"-fno-cxx-modules">, Group<f_Group>, Flags<[NoForward]>; -def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">, Group<f_Group>; +def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">, Group<f_Group>, + Flags<[CC1Option]>, HelpText<"Do not include fixit information in diagnostics">; +def fno_diagnostics_show_name : Flag<"-fno-diagnostics-show-name">, Group<f_Group>; def fno_diagnostics_show_option : Flag<"-fno-diagnostics-show-option">, Group<f_Group>; -def fno_diagnostics_show_note_include_stack : Flag<"-fno-diagnostics-show-note-include-stack">, Group<f_Group>; -def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, Group<f_Group>; -def fno_elide_constructors : Flag<"-fno-elide-constructors">, Group<f_Group>; +def fno_diagnostics_show_note_include_stack : Flag<"-fno-diagnostics-show-note-include-stack">, + Flags<[CC1Option]>, Group<f_Group>, HelpText<"Display include stacks for diagnostic notes">; +def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, Group<f_Group>, + HelpText<"Disallow '$' in identifiers">, Flags<[CC1Option]>; +def fno_elide_constructors : Flag<"-fno-elide-constructors">, Group<f_Group>, + HelpText<"Disable C++ copy constructor elision">, Flags<[CC1Option]>; def fno_eliminate_unused_debug_symbols : Flag<"-fno-eliminate-unused-debug-symbols">, Group<f_Group>; def fno_exceptions : Flag<"-fno-exceptions">, Group<f_Group>; -def fno_gnu_keywords : Flag<"-fno-gnu-keywords">, Group<f_Group>; -def fno_inline_functions : Flag<"-fno-inline-functions">, Group<f_Group>; -def fno_inline : Flag<"-fno-inline">, Group<f_Group>; +def fno_gnu_keywords : Flag<"-fno-gnu-keywords">, Group<f_Group>, Flags<[CC1Option]>; +def fno_inline_functions : Flag<"-fno-inline-functions">, Group<f_clang_Group>, Flags<[CC1Option]>; +def fno_inline : Flag<"-fno-inline">, Group<f_clang_Group>, Flags<[CC1Option]>; def fno_keep_inline_functions : Flag<"-fno-keep-inline-functions">, Group<clang_ignored_f_Group>; -def fno_lax_vector_conversions : Flag<"-fno-lax-vector-conversions">, Group<f_Group>; -def fno_limit_debug_info : Flag<"-fno-limit-debug-info">, Group<f_Group>, +def fno_lax_vector_conversions : Flag<"-fno-lax-vector-conversions">, Group<f_Group>, + HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">, Flags<[CC1Option]>; +def fno_limit_debug_info : Flag<"-fno-limit-debug-info">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Do not limit debug information produced to reduce size of debug binary">; -def fno_merge_all_constants : Flag<"-fno-merge-all-constants">, Group<f_Group>; +def fno_merge_all_constants : Flag<"-fno-merge-all-constants">, Group<f_Group>, + Flags<[CC1Option]>, HelpText<"Disallow merging of constants.">; def fno_modules : Flag <"-fno-modules">, Group<f_Group>, Flags<[NoForward]>; def fno_ms_extensions : Flag<"-fno-ms-extensions">, Group<f_Group>; def fno_ms_compatibility : Flag<"-fno-ms-compatibility">, Group<f_Group>; @@ -435,44 +526,62 @@ def fno_delayed_template_parsing : Flag<"-fno-delayed-template-parsing">, Group< def fno_objc_exceptions: Flag<"-fno-objc-exceptions">, Group<f_Group>; def fno_objc_legacy_dispatch : Flag<"-fno-objc-legacy-dispatch">, Group<f_Group>; def fno_omit_frame_pointer : Flag<"-fno-omit-frame-pointer">, Group<f_Group>; -def fno_operator_names : Flag<"-fno-operator-names">, Group<f_Group>; +def fno_operator_names : Flag<"-fno-operator-names">, Group<f_Group>, + HelpText<"Do not treat C++ operator name keywords as synonyms for operators">, + Flags<[CC1Option]>; def fno_pascal_strings : Flag<"-fno-pascal-strings">, Group<f_Group>; -def fno_rtti : Flag<"-fno-rtti">, Group<f_Group>; +def fno_rtti : Flag<"-fno-rtti">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Disable generation of rtti information">; def fno_short_enums : Flag<"-fno-short-enums">, Group<f_Group>; -def fno_show_column : Flag<"-fno-show-column">, Group<f_Group>; -def fno_show_source_location : Flag<"-fno-show-source-location">, Group<f_Group>; -def fno_spell_checking : Flag<"-fno-spell-checking">, Group<f_Group>; +def fno_show_column : Flag<"-fno-show-column">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Do not include column number on diagnostics">; +def fno_show_source_location : Flag<"-fno-show-source-location">, Group<f_Group>, + Flags<[CC1Option]>, HelpText<"Do not include source location information with diagnostics">; +def fno_spell_checking : Flag<"-fno-spell-checking">, Group<f_Group>, + Flags<[CC1Option]>, HelpText<"Disable spell-checking">; def fno_stack_protector : Flag<"-fno-stack-protector">, Group<f_Group>; def fno_strict_aliasing : Flag<"-fno-strict-aliasing">, Group<f_Group>; def fno_strict_enums : Flag<"-fno-strict-enums">, Group<f_Group>; def fno_strict_overflow : Flag<"-fno-strict-overflow">, Group<f_Group>; -def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, Group<f_Group>; -def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">, Group<f_Group>; +def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, Group<f_Group>, + Flags<[CC1Option]>, HelpText<"Do not emit code to make initialization of local statics thread safe">; +def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Don't use __cxa_atexit for calling destructors">; def fno_unit_at_a_time : Flag<"-fno-unit-at-a-time">, Group<f_Group>; def fno_unwind_tables : Flag<"-fno-unwind-tables">, Group<f_Group>; def fno_verbose_asm : Flag<"-fno-verbose-asm">, Group<f_Group>; def fno_working_directory : Flag<"-fno-working-directory">, Group<f_Group>; def fno_wrapv : Flag<"-fno-wrapv">, Group<f_Group>; def fno_zero_initialized_in_bss : Flag<"-fno-zero-initialized-in-bss">, Group<f_Group>; -def fobjc_arc : Flag<"-fobjc-arc">, Group<f_Group>; +def fobjc_arc : Flag<"-fobjc-arc">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Synthesize retain and release calls for Objective-C pointers">; def fno_objc_arc : Flag<"-fno-objc-arc">, Group<f_Group>; -def fobjc_arc_exceptions : Flag<"-fobjc-arc-exceptions">, Group<f_Group>; +def fobjc_arc_exceptions : Flag<"-fobjc-arc-exceptions">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Use EH-safe code when synthesizing retains and releases in -fobjc-arc">; def fno_objc_arc_exceptions : Flag<"-fno-objc-arc-exceptions">, Group<f_Group>; def fobjc_atdefs : Flag<"-fobjc-atdefs">, Group<clang_ignored_f_Group>; def fobjc_call_cxx_cdtors : Flag<"-fobjc-call-cxx-cdtors">, Group<clang_ignored_f_Group>; -def fobjc_exceptions: Flag<"-fobjc-exceptions">, Group<f_Group>; +def fobjc_exceptions: Flag<"-fobjc-exceptions">, Group<f_Group>, + HelpText<"Enable Objective-C exceptions">, Flags<[CC1Option]>; -def fobjc_gc_only : Flag<"-fobjc-gc-only">, Group<f_Group>; -def fobjc_gc : Flag<"-fobjc-gc">, Group<f_Group>; +def fobjc_gc_only : Flag<"-fobjc-gc-only">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Use GC exclusively for Objective-C related memory management">; +def fobjc_gc : Flag<"-fobjc-gc">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Enable Objective-C garbage collection">; def fobjc_legacy_dispatch : Flag<"-fobjc-legacy-dispatch">, Group<f_Group>; def fobjc_new_property : Flag<"-fobjc-new-property">, Group<clang_ignored_f_Group>; def fobjc_infer_related_result_type : Flag<"-fobjc-infer-related-result-type">, Group<f_Group>; def fno_objc_infer_related_result_type : Flag< - "-fno-objc-infer-related-result-type">, Group<f_Group>; + "-fno-objc-infer-related-result-type">, Group<f_Group>, + HelpText< + "do not infer Objective-C related result type based on method family">, + Flags<[CC1Option]>; def fobjc_link_runtime: Flag<"-fobjc-link-runtime">, Group<f_Group>; // Objective-C ABI options. +def fobjc_runtime_EQ : Joined<"-fobjc-runtime=">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Specify the target Objective-C runtime kind and version">; def fobjc_abi_version_EQ : Joined<"-fobjc-abi-version=">, Group<f_Group>; def fobjc_nonfragile_abi_version_EQ : Joined<"-fobjc-nonfragile-abi-version=">, Group<f_Group>; def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">, Group<f_Group>; @@ -490,8 +599,10 @@ def force__load : Separate<"-force_load">; def foutput_class_dir_EQ : Joined<"-foutput-class-dir=">, Group<f_Group>; def fpack_struct : Flag<"-fpack-struct">, Group<f_Group>; def fno_pack_struct : Flag<"-fno-pack-struct">, Group<f_Group>; -def fpack_struct_EQ : Joined<"-fpack-struct=">, Group<f_Group>; -def fpascal_strings : Flag<"-fpascal-strings">, Group<f_Group>; +def fpack_struct_EQ : Joined<"-fpack-struct=">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Specify the default maximum struct packing alignment">; +def fpascal_strings : Flag<"-fpascal-strings">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Recognize and construct Pascal-style string literals">; def fpch_preprocess : Flag<"-fpch-preprocess">, Group<f_Group>; def fpic : Flag<"-fpic">, Group<f_Group>; def fno_pic : Flag<"-fno-pic">, Group<f_Group>; @@ -503,11 +614,15 @@ def framework : Separate<"-framework">, Flags<[LinkerInput]>; def frandom_seed_EQ : Joined<"-frandom-seed=">, Group<clang_ignored_f_Group>; def frtti : Flag<"-frtti">, Group<f_Group>; def fsched_interblock : Flag<"-fsched-interblock">, Group<clang_ignored_f_Group>; -def fshort_enums : Flag<"-fshort-enums">, Group<f_Group>; +def fshort_enums : Flag<"-fshort-enums">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Allocate to an enum type only as many bytes as it needs for the declared range of possible values">; def freorder_blocks : Flag<"-freorder-blocks">, Group<clang_ignored_f_Group>; -def fshort_wchar : Flag<"-fshort-wchar">, Group<f_Group>; -def fshow_overloads_EQ : Joined<"-fshow-overloads=">, Group<f_Group>; -def fshow_column : Flag<"-fshow-column">, Group<f_Group>; +def fshort_wchar : Flag<"-fshort-wchar">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Force wchar_t to be a short unsigned int">; +def fshow_overloads_EQ : Joined<"-fshow-overloads=">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Which overload candidates to show when overload resolution fails: " + "best|all; defaults to all">; +def fshow_column : Flag<"-fshow-column">, Group<f_Group>, Flags<[CC1Option]>; def fshow_source_location : Flag<"-fshow-source-location">, Group<f_Group>; def fspell_checking : Flag<"-fspell-checking">, Group<f_Group>; def fsigned_bitfields : Flag<"-fsigned-bitfields">, Group<f_Group>; @@ -515,17 +630,21 @@ def fsigned_char : Flag<"-fsigned-char">, Group<f_Group>; def fstack_protector_all : Flag<"-fstack-protector-all">, Group<f_Group>; def fstack_protector : Flag<"-fstack-protector">, Group<f_Group>; def fstrict_aliasing : Flag<"-fstrict-aliasing">, Group<f_Group>; -def fstrict_enums : Flag<"-fstrict-enums">, Group<f_Group>; +def fstrict_enums : Flag<"-fstrict-enums">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Enable optimizations based on the strict definition of an enum's " + "value range.">; def fstrict_overflow : Flag<"-fstrict-overflow">, Group<f_Group>; -def fsyntax_only : Flag<"-fsyntax-only">, Flags<[DriverOption]>; +def fsyntax_only : Flag<"-fsyntax-only">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>; def ftabstop_EQ : Joined<"-ftabstop=">, Group<f_Group>; def ftemplate_depth_EQ : Joined<"-ftemplate-depth=">, Group<f_Group>; def ftemplate_depth_ : Joined<"-ftemplate-depth-">, Group<f_Group>; def ftemplate_backtrace_limit_EQ : Joined<"-ftemplate-backtrace-limit=">, Group<f_Group>; def ftest_coverage : Flag<"-ftest-coverage">, Group<f_Group>; -def Wlarge_by_value_copy_def : Flag<"-Wlarge-by-value-copy">; -def Wlarge_by_value_copy_EQ : Joined<"-Wlarge-by-value-copy=">; +def Wlarge_by_value_copy_def : Flag<"-Wlarge-by-value-copy">, + HelpText<"Warn if a function definition returns or accepts an object larger " + "in bytes that a given value">; +def Wlarge_by_value_copy_EQ : Joined<"-Wlarge-by-value-copy=">, Flags<[CC1Option]>; // Just silence warnings about -Wlarger-than, -Wframe-larger-than for now. def Wlarger_than : Separate<"-Wlarger-than">, Group<clang_ignored_f_Group>; @@ -536,68 +655,116 @@ def Wframe_larger_than_EQ : Joined<"-Wframe-larger-than=">, Alias<Wframe_larger_ def fterminated_vtables : Flag<"-fterminated-vtables">, Alias<fapple_kext>; def fthreadsafe_statics : Flag<"-fthreadsafe-statics">, Group<f_Group>; -def ftime_report : Flag<"-ftime-report">, Group<f_Group>; -def ftrapv : Flag<"-ftrapv">, Group<f_Group>; -def ftrapv_handler_EQ : Joined<"-ftrapv-handler=">, Group<f_Group>; -def ftrap_function_EQ : Joined<"-ftrap-function=">, Group<f_Group>, +def ftime_report : Flag<"-ftime-report">, Group<f_Group>, Flags<[CC1Option]>; +def ftlsmodel_EQ : Joined<"-ftls-model=">, Group<f_Group>, Flags<[CC1Option]>; +def ftrapv : Flag<"-ftrapv">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Trap on integer overflow">; +def ftrapv_handler_EQ : Joined<"-ftrapv-handler=">, Group<f_Group>, + MetaVarName<"<function name>">, + HelpText<"Specify the function to be called on overflow.">; +def ftrapv_handler : Separate<"-ftrapv-handler">, Group<f_Group>, Flags<[CC1Option]>; +def ftrap_function_EQ : Joined<"-ftrap-function=">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Issue call to specified function rather than a trap instruction">; def funit_at_a_time : Flag<"-funit-at-a-time">, Group<f_Group>; -def funroll_loops : Flag<"-funroll-loops">, Group<f_Group>; +def funroll_loops : Flag<"-funroll-loops">, Group<f_Group>, + HelpText<"Turn on loop unroller">, Flags<[CC1Option]>; def funsigned_bitfields : Flag<"-funsigned-bitfields">, Group<f_Group>; def funsigned_char : Flag<"-funsigned-char">, Group<f_Group>; def funwind_tables : Flag<"-funwind-tables">, Group<f_Group>; def fuse_cxa_atexit : Flag<"-fuse-cxa-atexit">, Group<f_Group>; def fverbose_asm : Flag<"-fverbose-asm">, Group<f_Group>; def fvisibility_EQ : Joined<"-fvisibility=">, Group<f_Group>; -def fvisibility_inlines_hidden : Flag<"-fvisibility-inlines-hidden">, Group<f_Group>; -def fwrapv : Flag<"-fwrapv">, Group<f_Group>; -def fwritable_strings : Flag<"-fwritable-strings">, Group<f_Group>; +def fvisibility_inlines_hidden : Flag<"-fvisibility-inlines-hidden">, Group<f_Group>, + HelpText<"Give inline C++ member functions default visibility by default">, + Flags<[CC1Option]>; +def fwrapv : Flag<"-fwrapv">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Treat signed integer overflow as two's complement">; +def fwritable_strings : Flag<"-fwritable-strings">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Store string literals as writable data">; def fzero_initialized_in_bss : Flag<"-fzero-initialized-in-bss">, Group<f_Group>; -def ffunction_sections: Flag <"-ffunction-sections">, Group<f_Group>; -def fdata_sections : Flag <"-fdata-sections">, Group<f_Group>; +def ffunction_sections: Flag <"-ffunction-sections">, Group<f_Group>, + Flags<[CC1Option]>, HelpText<"Place each function in its own section (ELF Only)">; +def fdata_sections : Flag <"-fdata-sections">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Place each data in its own section (ELF Only)">; def f : Joined<"-f">, Group<f_Group>; +def g_Flag : Flag<"-g">, Group<g_Group>, + HelpText<"Generate source level debug information">, Flags<[CC1Option]>; +def gline_tables_only : Flag<"-gline-tables-only">, Group<g_Group>, + HelpText<"Emit debug line number tables only">, Flags<[CC1Option]>; def g0 : Flag<"-g0">, Group<g_Group>; +def g1 : Flag<"-g1">, Group<g_Group>; def g2 : Flag<"-g2">, Group<g_Group>; def g3 : Flag<"-g3">, Group<g_Group>; -def gdwarf2 : Flag<"-gdwarf-2">, Group<g_Group>; -def gfull : Flag<"-gfull">, Group<g_Group>; def ggdb : Flag<"-ggdb">, Group<g_Group>; -def gstabs : Flag<"-gstabs">, Group<g_Group>; -def gstabsplus : Flag<"-gstabs+">, Group<g_Group>; -def gstabs1 : Flag<"-gstabs1">, Group<g_Group>; -def gstabs2 : Flag<"-gstabs2">, Group<g_Group>; +def ggdb0 : Flag<"-ggdb0">, Group<g_Group>; +def ggdb1 : Flag<"-ggdb1">, Group<g_Group>; +def ggdb2 : Flag<"-ggdb2">, Group<g_Group>; +def ggdb3 : Flag<"-ggdb3">, Group<g_Group>; +def gdwarf_2 : Flag<"-gdwarf-2">, Group<g_Group>; +def gdwarf_3 : Flag<"-gdwarf-3">, Group<g_Group>; +def gdwarf_4 : Flag<"-gdwarf-4">, Group<g_Group>; +def gfull : Flag<"-gfull">, Group<g_Group>; def gused : Flag<"-gused">, Group<g_Group>; -def g_Flag : Flag<"-g">, Group<g_Group>; +def gstabs : Joined<"-gstabs">, Group<g_Group>, Flags<[Unsupported]>; +def gcoff : Joined<"-gcoff">, Group<g_Group>, Flags<[Unsupported]>; +def gxcoff : Joined<"-gxcoff">, Group<g_Group>, Flags<[Unsupported]>; +def gvms : Joined<"-gvms">, Group<g_Group>, Flags<[Unsupported]>; +def gtoggle : Flag<"-gtoggle">, Group<g_flags_Group>, Flags<[Unsupported]>; +def grecord_gcc_switches : Flag<"-grecord-gcc-switches">, Group<g_flags_Group>; +def gno_record_gcc_switches : Flag<"-gno-record-gcc-switches">, + Group<g_flags_Group>; +def gstrict_dwarf : Flag<"-gstrict-dwarf">, Group<g_flags_Group>; +def gno_strict_dwarf : Flag<"-gno-strict-dwarf">, Group<g_flags_Group>; def headerpad__max__install__names : Joined<"-headerpad_max_install_names">; -def index_header_map : Flag<"-index-header-map">; -def idirafter : JoinedOrSeparate<"-idirafter">, Group<clang_i_Group>; -def iframework : Joined<"-iframework">, Group<clang_i_Group>; -def imacros : JoinedOrSeparate<"-imacros">, Group<clang_i_Group>; +def help : Flag<"-help">, Flags<[CC1Option]>, + HelpText<"Display available options">; +def index_header_map : Flag<"-index-header-map">, Flags<[CC1Option]>, + HelpText<"Make the next included directory (-I or -F) an indexer header map">; +def idirafter : JoinedOrSeparate<"-idirafter">, Group<clang_i_Group>, Flags<[CC1Option]>, + HelpText<"Add directory to AFTER include search path">; +def iframework : Joined<"-iframework">, Group<clang_i_Group>, Flags<[CC1Option]>, + HelpText<"Add directory to SYSTEM framework search path">; +def imacros : JoinedOrSeparate<"-imacros">, Group<clang_i_Group>, Flags<[CC1Option]>, + HelpText<"Include macros from file before parsing">, MetaVarName<"<file>">; def image__base : Separate<"-image_base">; -def include_ : JoinedOrSeparate<"-include">, Group<clang_i_Group>, EnumName<"include">; -def include_pch : Separate<"-include-pch">, Group<clang_i_Group>; +def include_ : JoinedOrSeparate<"-include">, Group<clang_i_Group>, EnumName<"include">, + MetaVarName<"<file>">, HelpText<"Include file before parsing">, Flags<[CC1Option]>; +def include_pch : Separate<"-include-pch">, Group<clang_i_Group>, Flags<[CC1Option]>, + HelpText<"Include precompiled header file">, MetaVarName<"<file>">; def init : Separate<"-init">; def install__name : Separate<"-install_name">; def integrated_as : Flag<"-integrated-as">, Flags<[DriverOption]>; -def iprefix : JoinedOrSeparate<"-iprefix">, Group<clang_i_Group>; -def iquote : JoinedOrSeparate<"-iquote">, Group<clang_i_Group>; -def isysroot : JoinedOrSeparate<"-isysroot">, Group<clang_i_Group>; -def isystem : JoinedOrSeparate<"-isystem">, Group<clang_i_Group>; -def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">, Group<clang_i_Group>; -def iwithprefix : JoinedOrSeparate<"-iwithprefix">, Group<clang_i_Group>; -def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">, Group<clang_i_Group>; +def iprefix : JoinedOrSeparate<"-iprefix">, Group<clang_i_Group>, Flags<[CC1Option]>, + HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">, MetaVarName<"<dir>">; +def iquote : JoinedOrSeparate<"-iquote">, Group<clang_i_Group>, Flags<[CC1Option]>, + HelpText<"Add directory to QUOTE include search path">, MetaVarName<"<directory>">; +def isysroot : JoinedOrSeparate<"-isysroot">, Group<clang_i_Group>, Flags<[CC1Option]>, + HelpText<"Set the system root directory (usually /)">, MetaVarName<"<dir>">; +def isystem : JoinedOrSeparate<"-isystem">, Group<clang_i_Group>, Flags<[CC1Option]>, + HelpText<"Add directory to SYSTEM include search path">, MetaVarName<"<directory>">; +def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">, Group<clang_i_Group>, + HelpText<"Set directory to include search path with prefix">, MetaVarName<"<dir>">, + Flags<[CC1Option]>; +def iwithprefix : JoinedOrSeparate<"-iwithprefix">, Group<clang_i_Group>, Flags<[CC1Option]>, + HelpText<"Set directory to SYSTEM include search path with prefix">, MetaVarName<"<dir>">; +def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">, Group<clang_i_Group>, + HelpText<"Add directory to SYSTEM include search path, " + "absolute paths are relative to -isysroot">, MetaVarName<"<directory>">, + Flags<[CC1Option]>; def i : Joined<"-i">, Group<i_Group>; def keep__private__externs : Flag<"-keep_private_externs">; def l : JoinedOrSeparate<"-l">, Flags<[LinkerInput, RenderJoined]>; def lazy__framework : Separate<"-lazy_framework">, Flags<[LinkerInput]>; def lazy__library : Separate<"-lazy_library">, Flags<[LinkerInput]>; def m32 : Flag<"-m32">, Group<m_Group>, Flags<[DriverOption]>; -def mqdsp6_compat : Flag<"-mqdsp6-compat">, Group<m_Group>, Flags<[DriverOption]>; +def mqdsp6_compat : Flag<"-mqdsp6-compat">, Group<m_Group>, Flags<[DriverOption,CC1Option]>, + HelpText<"Enable hexagon-qdsp6 backward compatibility">; def m3dnowa : Flag<"-m3dnowa">, Group<m_x86_Features_Group>; def m3dnow : Flag<"-m3dnow">, Group<m_x86_Features_Group>; def m64 : Flag<"-m64">, Group<m_Group>, Flags<[DriverOption]>; def mabi_EQ : Joined<"-mabi=">, Group<m_Group>; def march_EQ : Joined<"-march=">, Group<m_Group>; +def maltivec : Flag<"-maltivec">, Alias<faltivec>; def mcmodel_EQ : Joined<"-mcmodel=">, Group<m_Group>; def mconstant_cfstrings : Flag<"-mconstant-cfstrings">, Group<clang_ignored_m_Group>; def mcpu_EQ : Joined<"-mcpu=">, Group<m_Group>; @@ -613,16 +780,21 @@ def mios_version_min_EQ : Joined<"-mios-version-min=">, Alias<miphoneos_version_ def mios_simulator_version_min_EQ : Joined<"-mios-simulator-version-min=">, Group<m_Group>; def mkernel : Flag<"-mkernel">, Group<m_Group>; def mlinker_version_EQ : Joined<"-mlinker-version=">, Flags<[NoForward]>; -def mllvm : Separate<"-mllvm">; +def mllvm : Separate<"-mllvm">, Flags<[CC1Option]>, + HelpText<"Additional arguments to forward to LLVM's option processing">; def mmacosx_version_min_EQ : Joined<"-mmacosx-version-min=">, Group<m_Group>; -def mms_bitfields : Flag<"-mms-bitfields">, Group<m_Group>; -def mstackrealign : Flag<"-mstackrealign">, Group<m_Group>; -def mstack_alignment : Joined<"-mstack-alignment=">, Group<m_Group>; +def mms_bitfields : Flag<"-mms-bitfields">, Group<m_Group>, Flags<[CC1Option]>, + HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard.">; +def mstackrealign : Flag<"-mstackrealign">, Group<m_Group>, Flags<[CC1Option]>, + HelpText<"Force realign the stack at entry to every function.">; +def mstack_alignment : Joined<"-mstack-alignment=">, Group<m_Group>, Flags<[CC1Option]>, + HelpText<"Set the stack alignment">; def mmmx : Flag<"-mmmx">, Group<m_x86_Features_Group>; def mno_3dnowa : Flag<"-mno-3dnowa">, Group<m_x86_Features_Group>; def mno_3dnow : Flag<"-mno-3dnow">, Group<m_x86_Features_Group>; def mno_constant_cfstrings : Flag<"-mno-constant-cfstrings">, Group<m_Group>; -def mno_global_merge : Flag<"-mno-global-merge">, Group<m_Group>; +def mno_global_merge : Flag<"-mno-global-merge">, Group<m_Group>, Flags<[CC1Option]>, + HelpText<"Disable merging of globals">; def mno_mmx : Flag<"-mno-mmx">, Group<m_x86_Features_Group>; def mno_pascal_strings : Flag<"-mno-pascal-strings">, Group<m_Group>; def mno_red_zone : Flag<"-mno-red-zone">, Group<m_Group>; @@ -641,25 +813,35 @@ def mno_ssse3 : Flag<"-mno-ssse3">, Group<m_x86_Features_Group>; def mno_aes : Flag<"-mno-aes">, Group<m_x86_Features_Group>; def mno_avx : Flag<"-mno-avx">, Group<m_x86_Features_Group>; def mno_avx2 : Flag<"-mno-avx2">, Group<m_x86_Features_Group>; +def mno_pclmul : Flag<"-mno-pclmul">, Group<m_x86_Features_Group>; def mno_lzcnt : Flag<"-mno-lzcnt">, Group<m_x86_Features_Group>; +def mno_rdrnd : Flag<"-mno-rdrnd">, Group<m_x86_Features_Group>; def mno_bmi : Flag<"-mno-bmi">, Group<m_x86_Features_Group>; def mno_bmi2 : Flag<"-mno-bmi2">, Group<m_x86_Features_Group>; def mno_popcnt : Flag<"-mno-popcnt">, Group<m_x86_Features_Group>; def mno_fma4 : Flag<"-mno-fma4">, Group<m_x86_Features_Group>; +def mno_fma : Flag<"-mno-fma">, Group<m_x86_Features_Group>; +def mno_xop : Flag<"-mno-xop">, Group<m_x86_Features_Group>; def mno_thumb : Flag<"-mno-thumb">, Group<m_Group>; def marm : Flag<"-marm">, Alias<mno_thumb>; def mno_warn_nonportable_cfstrings : Flag<"-mno-warn-nonportable-cfstrings">, Group<m_Group>; def mno_omit_leaf_frame_pointer : Flag<"-mno-omit-leaf-frame-pointer">, Group<f_Group>; -def momit_leaf_frame_pointer : Flag<"-momit-leaf-frame-pointer">, Group<f_Group>; +def momit_leaf_frame_pointer : Flag<"-momit-leaf-frame-pointer">, Group<f_Group>, + HelpText<"Omit frame pointer setup for leaf functions.">, Flags<[CC1Option]>; def mpascal_strings : Flag<"-mpascal-strings">, Group<m_Group>; def mred_zone : Flag<"-mred-zone">, Group<m_Group>; def mregparm_EQ : Joined<"-mregparm=">, Group<m_Group>; -def mrelax_all : Flag<"-mrelax-all">, Group<m_Group>; -def mrtd: Flag<"-mrtd">, Group<m_Group>; +def mrelax_all : Flag<"-mrelax-all">, Group<m_Group>, Flags<[CC1Option]>, + HelpText<"(integrated-as) Relax all machine instructions">; +def mrtd : Flag<"-mrtd">, Group<m_Group>, Flags<[CC1Option]>, + HelpText<"Make StdCall calling convention the default">; def msmall_data_threshold_EQ : Joined <"-msmall-data-threshold=">, Group<m_Group>; -def msoft_float : Flag<"-msoft-float">, Group<m_Group>; +def msoft_float : Flag<"-msoft-float">, Group<m_Group>, Flags<[CC1Option]>, + HelpText<"Use software floating point">; +def mno_implicit_float : Flag<"-mno-implicit-float">, Group<m_Group>, + HelpText<"Don't generate implicit floating point instructions">; def msse2 : Flag<"-msse2">, Group<m_x86_Features_Group>; def msse3 : Flag<"-msse3">, Group<m_x86_Features_Group>; def msse4a : Flag<"-msse4a">, Group<m_x86_Features_Group>; @@ -671,11 +853,21 @@ def mssse3 : Flag<"-mssse3">, Group<m_x86_Features_Group>; def maes : Flag<"-maes">, Group<m_x86_Features_Group>; def mavx : Flag<"-mavx">, Group<m_x86_Features_Group>; def mavx2 : Flag<"-mavx2">, Group<m_x86_Features_Group>; +def mpclmul : Flag<"-mpclmul">, Group<m_x86_Features_Group>; def mlzcnt : Flag<"-mlzcnt">, Group<m_x86_Features_Group>; +def mrdrnd : Flag<"-mrdrnd">, Group<m_x86_Features_Group>; def mbmi : Flag<"-mbmi">, Group<m_x86_Features_Group>; def mbmi2 : Flag<"-mbmi2">, Group<m_x86_Features_Group>; def mpopcnt : Flag<"-mpopcnt">, Group<m_x86_Features_Group>; def mfma4 : Flag<"-mfma4">, Group<m_x86_Features_Group>; +def mfma : Flag<"-mfma">, Group<m_x86_Features_Group>; +def mxop : Flag<"-mxop">, Group<m_x86_Features_Group>; +def mips16 : Flag<"-mips16">, Group<m_Group>; +def mno_mips16 : Flag<"-mno-mips16">, Group<m_Group>; +def mdsp : Flag<"-mdsp">, Group<m_Group>; +def mno_dsp : Flag<"-mno-dsp">, Group<m_Group>; +def mdspr2 : Flag<"-mdspr2">, Group<m_Group>; +def mno_dspr2 : Flag<"-mno-dspr2">, Group<m_Group>; def mthumb : Flag<"-mthumb">, Group<m_Group>; def mtune_EQ : Joined<"-mtune=">, Group<m_Group>; def multi__module : Flag<"-multi_module">; @@ -689,8 +881,10 @@ def no_canonical_prefixes : Flag<"-no-canonical-prefixes">, Flags<[HelpHidden]>, def no_cpp_precomp : Flag<"-no-cpp-precomp">, Group<clang_ignored_f_Group>; def no_integrated_as : Flag<"-no-integrated-as">, Flags<[DriverOption]>; def no_integrated_cpp : Flag<"-no-integrated-cpp">, Flags<[DriverOption]>; +def no_pedantic : Flag<"-no-pedantic">, Group<pedantic_Group>; def no__dead__strip__inits__and__terms : Flag<"-no_dead_strip_inits_and_terms">; -def nobuiltininc : Flag<"-nobuiltininc">; +def nobuiltininc : Flag<"-nobuiltininc">, Flags<[CC1Option]>, + HelpText<"Disable builtin #include directories">; def nodefaultlibs : Flag<"-nodefaultlibs">; def nofixprebinding : Flag<"-nofixprebinding">; def nolibc : Flag<"-nolibc">; @@ -700,16 +894,17 @@ def noseglinkedit : Flag<"-noseglinkedit">; def nostartfiles : Flag<"-nostartfiles">; def nostdinc : Flag<"-nostdinc">; def nostdlibinc : Flag<"-nostdlibinc">; -def nostdincxx : Flag<"-nostdinc++">; +def nostdincxx : Flag<"-nostdinc++">, Flags<[CC1Option]>, + HelpText<"Disable standard #include directories for the C++ standard library">; def nostdlib : Flag<"-nostdlib">; def object : Flag<"-object">; -def o : JoinedOrSeparate<"-o">, Flags<[DriverOption, RenderAsInput]>, +def o : JoinedOrSeparate<"-o">, Flags<[DriverOption, RenderAsInput, CC1Option]>, HelpText<"Write output to <file>">, MetaVarName<"<file>">; def pagezero__size : JoinedOrSeparate<"-pagezero_size">; def pass_exit_codes : Flag<"-pass-exit-codes">, Flags<[Unsupported]>; -def pedantic_errors : Flag<"-pedantic-errors">, Group<pedantic_Group>; -def pedantic : Flag<"-pedantic">, Group<pedantic_Group>; -def pg : Flag<"-pg">; +def pedantic_errors : Flag<"-pedantic-errors">, Group<pedantic_Group>, Flags<[CC1Option]>; +def pedantic : Flag<"-pedantic">, Group<pedantic_Group>, Flags<[CC1Option]>; +def pg : Flag<"-pg">, HelpText<"Enable mcount instrumentation">, Flags<[CC1Option]>; def pipe : Flag<"-pipe">, HelpText<"Use pipes between commands, when possible">; def prebind__all__twolevel__modules : Flag<"-prebind_all_twolevel_modules">; @@ -717,7 +912,8 @@ def prebind : Flag<"-prebind">; def preload : Flag<"-preload">; def print_file_name_EQ : Joined<"-print-file-name=">, HelpText<"Print the full library path of <file>">, MetaVarName<"<file>">; -def print_ivar_layout : Flag<"-print-ivar-layout">; +def print_ivar_layout : Flag<"-print-ivar-layout">, Flags<[CC1Option]>, + HelpText<"Enable Objective-C Ivar layout bitmap print trace">; def print_libgcc_file_name : Flag<"-print-libgcc-file-name">, HelpText<"Print the library path for \"libgcc.a\"">; def print_multi_directory : Flag<"-print-multi-directory">; @@ -729,13 +925,14 @@ def print_search_dirs : Flag<"-print-search-dirs">, HelpText<"Print the paths used for finding libraries and programs">; def private__bundle : Flag<"-private_bundle">; def pthreads : Flag<"-pthreads">; -def pthread : Flag<"-pthread">; +def pthread : Flag<"-pthread">, Flags<[CC1Option]>, + HelpText<"Support POSIX threads in generated code">; def p : Flag<"-p">; def pie : Flag<"-pie">; def read__only__relocs : Separate<"-read_only_relocs">; def remap : Flag<"-remap">; -def rewrite_objc : Flag<"-rewrite-objc">, Flags<[DriverOption]>, - HelpText<"Rewrite Objective-C source to C++">; +def rewrite_objc : Flag<"-rewrite-objc">, Flags<[DriverOption,CC1Option]>, + HelpText<"Rewrite Objective-C source to C++">, Group<Action_Group>; def rewrite_legacy_objc : Flag<"-rewrite-legacy-objc">, Flags<[DriverOption]>, HelpText<"Rewrite Legacy Objective-C source to C++">; def rdynamic : Flag<"-rdynamic">; @@ -767,8 +964,10 @@ def static_libgcc : Flag<"-static-libgcc">; def static_libstdcxx : Flag<"-static-libstdc++">; def static : Flag<"-static">, Flags<[NoArgumentUnused]>; def std_default_EQ : Joined<"-std-default=">; -def std_EQ : Joined<"-std=">, Group<L_Group>; -def stdlib_EQ : Joined<"-stdlib=">; +def std_EQ : Joined<"-std=">, Flags<[CC1Option]>, Group<L_Group>, + HelpText<"Language standard to compile for">; +def stdlib_EQ : Joined<"-stdlib=">, Flags<[CC1Option]>, + HelpText<"C++ standard library to use">; def sub__library : JoinedOrSeparate<"-sub_library">; def sub__umbrella : JoinedOrSeparate<"-sub_umbrella">; def s : Flag<"-s">; @@ -780,21 +979,24 @@ def gcc_toolchain : Separate<"-gcc-toolchain">, Flags<[DriverOption]>, def ccc_host_triple : Separate<"-ccc-host-triple">, Alias<target>; def time : Flag<"-time">, HelpText<"Time individual commands">; -def traditional_cpp : Flag<"-traditional-cpp">; +def traditional_cpp : Flag<"-traditional-cpp">, Flags<[CC1Option]>, + HelpText<"Enable some traditional CPP emulation">; def traditional : Flag<"-traditional">; -def trigraphs : Flag<"-trigraphs">; +def trigraphs : Flag<"-trigraphs">, Flags<[CC1Option]>, + HelpText<"Process trigraph sequences">; def twolevel__namespace__hints : Flag<"-twolevel_namespace_hints">; def twolevel__namespace : Flag<"-twolevel_namespace">; def t : Flag<"-t">; def umbrella : Separate<"-umbrella">; def undefined : JoinedOrSeparate<"-undefined">, Group<u_Group>; -def undef : Flag<"-undef">, Group<u_Group>; +def undef : Flag<"-undef">, Group<u_Group>, Flags<[CC1Option]>, + HelpText<"undef all system defines">; def unexported__symbols__list : Separate<"-unexported_symbols_list">; def u : JoinedOrSeparate<"-u">, Group<u_Group>; def use_gold_plugin : Flag<"-use-gold-plugin">; -def v : Flag<"-v">, +def v : Flag<"-v">, Flags<[CC1Option]>, HelpText<"Show commands to run and use verbose output">; -def verify : Flag<"-verify">, Flags<[DriverOption]>, +def verify : Flag<"-verify">, Flags<[DriverOption,CC1Option]>, HelpText<"Verify output using a verifier.">; def weak_l : Joined<"-weak-l">, Flags<[LinkerInput]>; def weak__framework : Separate<"-weak_framework">, Flags<[LinkerInput]>; @@ -802,15 +1004,15 @@ def weak__library : Separate<"-weak_library">, Flags<[LinkerInput]>; def weak__reference__mismatches : Separate<"-weak_reference_mismatches">; def whatsloaded : Flag<"-whatsloaded">; def whyload : Flag<"-whyload">; -def w : Flag<"-w">; -def x : JoinedOrSeparate<"-x">, Flags<[DriverOption]>, +def w : Flag<"-w">, HelpText<"Suppress all warnings.">, Flags<[CC1Option]>; +def x : JoinedOrSeparate<"-x">, Flags<[DriverOption,CC1Option]>, HelpText<"Treat subsequent input files as having type <language>">, MetaVarName<"<language>">; def y : Joined<"-y">; -def working_directory : Separate<"-working-directory">, +def working_directory : JoinedOrSeparate<"-working-directory">, Flags<[CC1Option]>, HelpText<"Resolve file paths relative to the specified directory">; -def working_directory_EQ : Joined<"-working-directory=">, +def working_directory_EQ : Joined<"-working-directory=">, Flags<[CC1Option]>, Alias<working_directory>; // Double dash options, which are usually an alias for one of the previous @@ -854,8 +1056,7 @@ def _for_linker : Separate<"--for-linker">, Alias<Xlinker>; def _force_link_EQ : Joined<"--force-link=">, Alias<u>; def _force_link : Separate<"--force-link">, Alias<u>; def _help_hidden : Flag<"--help-hidden">; -def _help : Flag<"--help">, - HelpText<"Display available options">; +def _help : Flag<"--help">, Alias<help>; def _imacros_EQ : Joined<"--imacros=">, Alias<imacros>; def _imacros : Separate<"--imacros">, Alias<imacros>; def _include_barrier : Flag<"--include-barrier">, Alias<I_>; @@ -883,6 +1084,7 @@ def _machine_EQ : Joined<"--machine=">, Alias<m_Joined>; def _machine : Separate<"--machine">, Alias<m_Joined>; def _no_integrated_cpp : Flag<"--no-integrated-cpp">, Alias<no_integrated_cpp>; def _no_line_commands : Flag<"--no-line-commands">, Alias<P>; +def _no_pedantic : Flag<"--no-pedantic">, Alias<no_pedantic>; def _no_standard_includes : Flag<"--no-standard-includes">, Alias<nostdinc>; def _no_standard_libraries : Flag<"--no-standard-libraries">, Alias<nostdlib>; def _no_undefined : Flag<"--no-undefined">, Flags<[LinkerInput]>; @@ -945,12 +1147,14 @@ def _undefine_macro : Separate<"--undefine-macro">, Alias<U>; def _unsigned_char : Flag<"--unsigned-char">, Alias<funsigned_char>; def _user_dependencies : Flag<"--user-dependencies">, Alias<MM>; def _verbose : Flag<"--verbose">, Alias<v>; -def _version : Flag<"--version">; +def _version : Flag<"--version">, Flags<[CC1Option]>; def _warn__EQ : Joined<"--warn-=">, Alias<W_Joined>; def _warn_ : Joined<"--warn-">, Alias<W_Joined>; def _write_dependencies : Flag<"--write-dependencies">, Alias<MD>; def _write_user_dependencies : Flag<"--write-user-dependencies">, Alias<MMD>; def _ : Joined<"--">, Flags<[Unsupported]>; +def mieee_rnd_near : Flag<"-mieee-rnd-near">, Group<m_hexagon_Features_Group>; +def serialize_diags : Separate<"-serialize-diagnostics">, Alias<_serialize_diags>; // Special internal option to handle -Xlinker --no-demangle. def Z_Xlinker__no_demangle : Flag<"-Z-Xlinker-no-demangle">, @@ -965,3 +1169,5 @@ def Z_reserved_lib_stdcxx : Flag<"-Z-reserved-lib-stdc++">, Flags<[LinkerInput, NoArgumentUnused, Unsupported]>, Group<reserved_lib_Group>; def Z_reserved_lib_cckext : Flag<"-Z-reserved-lib-cckext">, Flags<[LinkerInput, NoArgumentUnused, Unsupported]>, Group<reserved_lib_Group>; + +include "CC1Options.td" diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index c35cf67..ab417bb 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -18,6 +18,8 @@ #include <string> namespace clang { + class ObjCRuntime; + namespace driver { class ArgList; class Compilation; @@ -25,7 +27,6 @@ namespace driver { class Driver; class InputArgList; class JobAction; - class ObjCRuntime; class Tool; /// ToolChain - Access to tools for a single platform. @@ -137,6 +138,9 @@ public: /// default. virtual bool IsStrictAliasingDefault() const { return true; } + /// IsMathErrnoDefault - Does this tool chain use -fmath-errno by default. + virtual bool IsMathErrnoDefault() const { return true; } + /// IsObjCDefaultSynthPropertiesDefault - Does this tool chain enable /// -fobjc-default-synthesize-properties by default. virtual bool IsObjCDefaultSynthPropertiesDefault() const { return false; } @@ -145,11 +149,6 @@ public: /// -fobjc-nonfragile-abi by default. virtual bool IsObjCNonFragileABIDefault() const { return false; } - /// IsObjCLegacyDispatchDefault - Does this tool chain set - /// -fobjc-legacy-dispatch by default (this is only used with the non-fragile - /// ABI). - virtual bool IsObjCLegacyDispatchDefault() const { return true; } - /// UseObjCMixedDispatchDefault - When using non-legacy dispatch, should the /// mixed dispatch method be used? virtual bool UseObjCMixedDispatch() const { return false; } @@ -207,11 +206,11 @@ public: virtual std::string ComputeEffectiveClangTriple(const ArgList &Args, types::ID InputType = types::TY_INVALID) const; - /// configureObjCRuntime - Configure the known properties of the - /// Objective-C runtime for this platform. + /// getDefaultObjCRuntime - Return the default Objective-C runtime + /// for this platform. /// /// FIXME: this really belongs on some sort of DeploymentTarget abstraction - virtual void configureObjCRuntime(ObjCRuntime &runtime) const; + virtual ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const; /// hasBlocksRuntime - Given that the user is compiling with /// -fblocks, does this tool chain guarantee the existence of a @@ -227,6 +226,10 @@ public: virtual void AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const; + // addClangTargetOptions - Add options that need to be passed to cc1 for + // this target. + virtual void addClangTargetOptions(ArgStringList &CC1Args) const; + // GetRuntimeLibType - Determine the runtime library type to use with the // given compilation arguments. virtual RuntimeLibType GetRuntimeLibType(const ArgList &Args) const; diff --git a/include/clang/Driver/Types.def b/include/clang/Driver/Types.def index b107dfb..318c55a 100644 --- a/include/clang/Driver/Types.def +++ b/include/clang/Driver/Types.def @@ -40,17 +40,17 @@ // C family source language (with and without preprocessing). TYPE("cpp-output", PP_C, INVALID, "i", "u") -TYPE("c", C, PP_C, 0, "u") -TYPE("cl", CL, PP_C, 0, "u") -TYPE("cuda", CUDA, PP_CXX, 0, "u") +TYPE("c", C, PP_C, "c", "u") +TYPE("cl", CL, PP_C, "cl", "u") +TYPE("cuda", CUDA, PP_CXX, "cpp", "u") TYPE("objective-c-cpp-output", PP_ObjC, INVALID, "mi", "u") TYPE("objc-cpp-output", PP_ObjC_Alias, INVALID, "mi", "u") -TYPE("objective-c", ObjC, PP_ObjC, 0, "u") +TYPE("objective-c", ObjC, PP_ObjC, "m", "u") TYPE("c++-cpp-output", PP_CXX, INVALID, "ii", "u") -TYPE("c++", CXX, PP_CXX, 0, "u") +TYPE("c++", CXX, PP_CXX, "cpp", "u") TYPE("objective-c++-cpp-output", PP_ObjCXX, INVALID, "mii", "u") TYPE("objc++-cpp-output", PP_ObjCXX_Alias, INVALID, "mii", "u") -TYPE("objective-c++", ObjCXX, PP_ObjCXX, 0, "u") +TYPE("objective-c++", ObjCXX, PP_ObjCXX, "mm", "u") // C family input files to precompile. TYPE("c-header-cpp-output", PP_CHeader, INVALID, "i", "p") diff --git a/include/clang/Driver/Types.h b/include/clang/Driver/Types.h index 9187529..3dea471 100644 --- a/include/clang/Driver/Types.h +++ b/include/clang/Driver/Types.h @@ -23,7 +23,7 @@ namespace types { TY_LAST }; - /// getTypeName - Return the name of the type for \arg Id. + /// getTypeName - Return the name of the type for \p Id. const char *getTypeName(ID Id); /// getPreprocessedType - Get the ID of the type for this input when @@ -70,7 +70,7 @@ namespace types { bool isObjC(ID Id); /// lookupTypeForExtension - Lookup the type to use for the file - /// extension \arg Ext. + /// extension \p Ext. ID lookupTypeForExtension(const char *Ext); /// lookupTypeForTypSpecifier - Lookup the type to use for a user @@ -81,7 +81,7 @@ namespace types { /// to be done for this type. unsigned getNumCompilationPhases(ID Id); - /// getCompilationPhase - Return the \args N th compilation phase to + /// getCompilationPhase - Return the \p N th compilation phase to /// be done for this type. phases::ID getCompilationPhase(ID Id, unsigned N); diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h index cef9509..3731478 100644 --- a/include/clang/Frontend/ASTConsumers.h +++ b/include/clang/Frontend/ASTConsumers.h @@ -33,11 +33,15 @@ class TargetOptions; // original C code. The output is intended to be in a format such that // clang could re-parse the output back into the same AST, but the // implementation is still incomplete. -ASTConsumer *CreateASTPrinter(raw_ostream *OS); +ASTConsumer *CreateASTPrinter(raw_ostream *OS, StringRef FilterString); // AST dumper: dumps the raw AST in human-readable form to stderr; this is // intended for debugging. -ASTConsumer *CreateASTDumper(); +ASTConsumer *CreateASTDumper(StringRef FilterString); + +// AST Decl node lister: prints qualified names of all filterable AST Decl +// nodes. +ASTConsumer *CreateASTDeclNodeLister(); // AST XML-dumper: dumps out the AST to stderr in a very detailed XML // format; this is intended for particularly intense debugging. diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 041eabb..144b796 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -19,6 +19,7 @@ #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Lex/ModuleLoader.h" #include "clang/Lex/PreprocessingRecord.h" +#include "clang/AST/ASTContext.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/FileManager.h" @@ -248,7 +249,15 @@ private: std::vector<serialization::DeclID> TopLevelDeclsInPreamble; /// \brief Whether we should be caching code-completion results. - bool ShouldCacheCodeCompletionResults; + bool ShouldCacheCodeCompletionResults : 1; + + /// \brief Whether to include brief documentation within the set of code + /// completions cached. + bool IncludeBriefCommentsInCodeCompletion : 1; + + /// \brief True if non-system source files should be treated as volatile + /// (likely to change while trying to use them). + bool UserFilesAreVolatile : 1; /// \brief The language options used when we load an AST file. LangOptions ASTFileLangOpts; @@ -275,12 +284,11 @@ public: /// \brief A bitmask that indicates which code-completion contexts should /// contain this completion result. /// - /// The bits in the bitmask correspond to the values of - /// CodeCompleteContext::Kind. To map from a completion context kind to a - /// bit, subtract one from the completion context kind and shift 1 by that - /// number of bits. Many completions can occur in several different - /// contexts. - unsigned ShowInContexts; + /// The bits in the bitmask correspond to the values of + /// CodeCompleteContext::Kind. To map from a completion context kind to a + /// bit, shift 1 by that number of bits. Many completions can occur in + /// several different contexts. + uint64_t ShowInContexts; /// \brief The priority given to this code-completion result. unsigned Priority; @@ -396,7 +404,9 @@ private: /// just about any usage. /// Becomes a noop in release mode; only useful for debug mode checking. class ConcurrencyState { +#ifndef NDEBUG void *Mutex; // a llvm::sys::MutexImpl in debug; +#endif public: ConcurrencyState(); @@ -612,7 +622,8 @@ public: /// \brief Create a ASTUnit. Gets ownership of the passed CompilerInvocation. static ASTUnit *create(CompilerInvocation *CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, - bool CaptureDiagnostics = false); + bool CaptureDiagnostics, + bool UserFilesAreVolatile); /// \brief Create a ASTUnit from an AST file. /// @@ -629,7 +640,8 @@ public: RemappedFile *RemappedFiles = 0, unsigned NumRemappedFiles = 0, bool CaptureDiagnostics = false, - bool AllowPCHWithCompilerErrors = false); + bool AllowPCHWithCompilerErrors = false, + bool UserFilesAreVolatile = false); private: /// \brief Helper function for \c LoadFromCompilerInvocation() and @@ -679,6 +691,8 @@ public: bool CaptureDiagnostics = false, bool PrecompilePreamble = false, bool CacheCodeCompletionResults = false, + bool IncludeBriefCommentsInCodeCompletion = false, + bool UserFilesAreVolatile = false, OwningPtr<ASTUnit> *ErrAST = 0); /// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a @@ -698,7 +712,9 @@ public: bool CaptureDiagnostics = false, bool PrecompilePreamble = false, TranslationUnitKind TUKind = TU_Complete, - bool CacheCodeCompletionResults = false); + bool CacheCodeCompletionResults = false, + bool IncludeBriefCommentsInCodeCompletion = false, + bool UserFilesAreVolatile = false); /// LoadFromCommandLine - Create an ASTUnit from a vector of command line /// arguments, which must specify exactly one source file. @@ -730,8 +746,10 @@ public: bool PrecompilePreamble = false, TranslationUnitKind TUKind = TU_Complete, bool CacheCodeCompletionResults = false, + bool IncludeBriefCommentsInCodeCompletion = false, bool AllowPCHWithCompilerErrors = false, bool SkipFunctionBodies = false, + bool UserFilesAreVolatile = false, OwningPtr<ASTUnit> *ErrAST = 0); /// \brief Reparse the source files using the same command-line options that @@ -757,11 +775,15 @@ public: /// \param IncludeCodePatterns Whether to include code patterns (such as a /// for loop) in the code-completion results. /// + /// \param IncludeBriefComments Whether to include brief documentation within + /// the set of code completions returned. + /// /// FIXME: The Diag, LangOpts, SourceMgr, FileMgr, StoredDiagnostics, and /// OwnedBuffers parameters are all disgusting hacks. They will go away. void CodeComplete(StringRef File, unsigned Line, unsigned Column, RemappedFile *RemappedFiles, unsigned NumRemappedFiles, bool IncludeMacros, bool IncludeCodePatterns, + bool IncludeBriefComments, CodeCompleteConsumer &Consumer, DiagnosticsEngine &Diag, LangOptions &LangOpts, SourceManager &SourceMgr, FileManager &FileMgr, diff --git a/include/clang/Frontend/Analyses.def b/include/clang/Frontend/Analyses.def index b5b9394..29ddc9e 100644 --- a/include/clang/Frontend/Analyses.def +++ b/include/clang/Frontend/Analyses.def @@ -47,7 +47,9 @@ ANALYSIS_PURGE(PurgeNone, "none", "Do not purge symbols, bindings, or constrain #endif ANALYSIS_IPA(None, "none", "Perform only intra-procedural analysis") -ANALYSIS_IPA(Inlining, "inlining", "Experimental: Inline callees when their definitions are available") +ANALYSIS_IPA(Inlining, "inlining", "Inline callees when their definitions are available") +ANALYSIS_IPA(DynamicDispatch, "dynamic", "Experimental: Enable inlining of dynamically dispatched methods") +ANALYSIS_IPA(DynamicDispatchBifurcate, "dynamic-bifurcate", "Experimental: Enable inlining of dynamically dispatched methods, bifurcate paths when exact type info is unavailable") #ifndef ANALYSIS_INLINING_MODE #define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) diff --git a/include/clang/Frontend/AnalyzerOptions.h b/include/clang/Frontend/AnalyzerOptions.h index 847bfbd..4e489fe 100644 --- a/include/clang/Frontend/AnalyzerOptions.h +++ b/include/clang/Frontend/AnalyzerOptions.h @@ -96,7 +96,6 @@ public: unsigned VisualizeEGUbi : 1; unsigned UnoptimizedCFG : 1; unsigned CFGAddImplicitDtors : 1; - unsigned CFGAddInitializers : 1; unsigned EagerlyTrimEGraph : 1; unsigned PrintStats : 1; unsigned NoRetryExhausted : 1; @@ -121,7 +120,6 @@ public: VisualizeEGUbi = 0; UnoptimizedCFG = 0; CFGAddImplicitDtors = 0; - CFGAddInitializers = 0; EagerlyTrimEGraph = 0; PrintStats = 0; NoRetryExhausted = 0; diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h index e844f88..3e34093 100644 --- a/include/clang/Frontend/CodeGenOptions.h +++ b/include/clang/Frontend/CodeGenOptions.h @@ -35,84 +35,101 @@ public: Mixed = 2 }; - unsigned AsmVerbose : 1; /// -dA, -fverbose-asm. - unsigned ObjCAutoRefCountExceptions : 1; /// Whether ARC should be EH-safe. - unsigned CUDAIsDevice : 1; /// Set when compiling for CUDA device. - unsigned CXAAtExit : 1; /// Use __cxa_atexit for calling destructors. - unsigned CXXCtorDtorAliases: 1; /// Emit complete ctors/dtors as linker - /// aliases to base ctors when possible. - unsigned DataSections : 1; /// Set when -fdata-sections is enabled - unsigned DebugInfo : 1; /// Should generate debug info (-g). - unsigned LimitDebugInfo : 1; /// Limit generated debug info to reduce size. - unsigned DisableFPElim : 1; /// Set when -fomit-frame-pointer is enabled. - unsigned DisableLLVMOpts : 1; /// Don't run any optimizations, for use in - /// getting .bc files that correspond to the - /// internal state before optimizations are - /// done. - unsigned DisableRedZone : 1; /// Set when -mno-red-zone is enabled. - unsigned DisableTailCalls : 1; /// Do not emit tail calls. - unsigned EmitDeclMetadata : 1; /// Emit special metadata indicating what - /// Decl* various IR entities came from. Only - /// useful when running CodeGen as a - /// subroutine. - unsigned EmitGcovArcs : 1; /// Emit coverage data files, aka. GCDA. - unsigned EmitGcovNotes : 1; /// Emit coverage "notes" files, aka GCNO. - unsigned ForbidGuardVariables : 1; /// Issue errors if C++ guard variables - /// are required - unsigned FunctionSections : 1; /// Set when -ffunction-sections is enabled - unsigned HiddenWeakTemplateVTables : 1; /// Emit weak vtables and RTTI for - /// template classes with hidden visibility - unsigned HiddenWeakVTables : 1; /// Emit weak vtables, RTTI, and thunks with - /// hidden visibility. - unsigned InstrumentFunctions : 1; /// Set when -finstrument-functions is - /// enabled. - unsigned InstrumentForProfiling : 1; /// Set when -pg is enabled - unsigned LessPreciseFPMAD : 1; /// Enable less precise MAD instructions to be - /// generated. - unsigned MergeAllConstants : 1; /// Merge identical constants. - unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled. - unsigned NoDwarf2CFIAsm : 1; /// Set when -fno-dwarf2-cfi-asm is enabled. - unsigned NoDwarfDirectoryAsm : 1; /// Set when -fno-dwarf-directory-asm is - /// enabled. - unsigned NoExecStack : 1; /// Set when -Wa,--noexecstack is enabled. - unsigned NoGlobalMerge : 1; /// Set when -mno-global-merge is enabled. - unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled. - unsigned NoInfsFPMath : 1; /// Assume FP arguments, results not +-Inf. - unsigned NoInline : 1; /// Set when -fno-inline is enabled. Disables - /// use of the inline keyword. - unsigned NoNaNsFPMath : 1; /// Assume FP arguments, results not NaN. - unsigned NoZeroInitializedInBSS : 1; /// -fno-zero-initialized-in-bss - unsigned ObjCDispatchMethod : 2; /// Method of Objective-C dispatch to use. - unsigned ObjCRuntimeHasARC : 1; /// The target runtime supports ARC natively - unsigned ObjCRuntimeHasTerminate : 1; /// The ObjC runtime has objc_terminate - unsigned OmitLeafFramePointer : 1; /// Set when -momit-leaf-frame-pointer is - /// enabled. - unsigned OptimizationLevel : 3; /// The -O[0-4] option specified. - unsigned OptimizeSize : 2; /// If -Os (==1) or -Oz (==2) is specified. - unsigned RelaxAll : 1; /// Relax all machine code instructions. - unsigned RelaxedAliasing : 1; /// Set when -fno-strict-aliasing is enabled. - unsigned SaveTempLabels : 1; /// Save temporary labels. - unsigned SimplifyLibCalls : 1; /// Set when -fbuiltin is enabled. - unsigned SoftFloat : 1; /// -soft-float. - unsigned StrictEnums : 1; /// Optimize based on strict enum definition. - unsigned TimePasses : 1; /// Set when -ftime-report is enabled. - unsigned UnitAtATime : 1; /// Unused. For mirroring GCC optimization - /// selection. - unsigned UnrollLoops : 1; /// Control whether loops are unrolled. - unsigned UnsafeFPMath : 1; /// Allow unsafe floating point optzns. - unsigned UnwindTables : 1; /// Emit unwind tables. + enum DebugInfoKind { + NoDebugInfo, // Don't generate debug info. + DebugLineTablesOnly, // Emit only debug info necessary for generating + // line number tables (-gline-tables-only). + LimitedDebugInfo, // Limit generated debug info to reduce size + // (-flimit-debug-info). + FullDebugInfo // Generate complete debug info. + }; + + enum TLSModel { + GeneralDynamicTLSModel, + LocalDynamicTLSModel, + InitialExecTLSModel, + LocalExecTLSModel + }; + + unsigned AsmVerbose : 1; ///< -dA, -fverbose-asm. + unsigned ObjCAutoRefCountExceptions : 1; ///< Whether ARC should be EH-safe. + unsigned CUDAIsDevice : 1; ///< Set when compiling for CUDA device. + unsigned CXAAtExit : 1; ///< Use __cxa_atexit for calling destructors. + unsigned CXXCtorDtorAliases: 1; ///< Emit complete ctors/dtors as linker + ///< aliases to base ctors when possible. + unsigned DataSections : 1; ///< Set when -fdata-sections is enabled. + unsigned DisableFPElim : 1; ///< Set when -fomit-frame-pointer is enabled. + unsigned DisableLLVMOpts : 1; ///< Don't run any optimizations, for use in + ///< getting .bc files that correspond to the + ///< internal state before optimizations are + ///< done. + unsigned DisableRedZone : 1; ///< Set when -mno-red-zone is enabled. + unsigned DisableTailCalls : 1; ///< Do not emit tail calls. + unsigned EmitDeclMetadata : 1; ///< Emit special metadata indicating what + ///< Decl* various IR entities came from. Only + ///< useful when running CodeGen as a + ///< subroutine. + unsigned EmitGcovArcs : 1; ///< Emit coverage data files, aka. GCDA. + unsigned EmitGcovNotes : 1; ///< Emit coverage "notes" files, aka GCNO. + unsigned EmitOpenCLArgMetadata : 1; ///< Emit OpenCL kernel arg metadata. + unsigned EmitMicrosoftInlineAsm : 1; ///< Enable emission of MS-style inline + ///< assembly. + unsigned ForbidGuardVariables : 1; ///< Issue errors if C++ guard variables + ///< are required. + unsigned FunctionSections : 1; ///< Set when -ffunction-sections is enabled. + unsigned HiddenWeakTemplateVTables : 1; ///< Emit weak vtables and RTTI for + ///< template classes with hidden visibility + unsigned HiddenWeakVTables : 1; ///< Emit weak vtables, RTTI, and thunks with + ///< hidden visibility. + unsigned InstrumentFunctions : 1; ///< Set when -finstrument-functions is + ///< enabled. + unsigned InstrumentForProfiling : 1; ///< Set when -pg is enabled. + unsigned LessPreciseFPMAD : 1; ///< Enable less precise MAD instructions to + ///< be generated. + unsigned MergeAllConstants : 1; ///< Merge identical constants. + unsigned NoCommon : 1; ///< Set when -fno-common or C++ is enabled. + unsigned NoDwarf2CFIAsm : 1; ///< Set when -fno-dwarf2-cfi-asm is enabled. + unsigned NoDwarfDirectoryAsm : 1; ///< Set when -fno-dwarf-directory-asm is + ///< enabled. + unsigned NoExecStack : 1; ///< Set when -Wa,--noexecstack is enabled. + unsigned NoGlobalMerge : 1; ///< Set when -mno-global-merge is enabled. + unsigned NoImplicitFloat : 1; ///< Set when -mno-implicit-float is enabled. + unsigned NoInfsFPMath : 1; ///< Assume FP arguments, results not +-Inf. + unsigned NoInline : 1; ///< Set when -fno-inline is enabled. Disables + ///< use of the inline keyword. + unsigned NoNaNsFPMath : 1; ///< Assume FP arguments, results not NaN. + unsigned NoZeroInitializedInBSS : 1; ///< -fno-zero-initialized-in-bss. + unsigned ObjCDispatchMethod : 2; ///< Method of Objective-C dispatch to use. + unsigned OmitLeafFramePointer : 1; ///< Set when -momit-leaf-frame-pointer is + ///< enabled. + unsigned OptimizationLevel : 3; ///< The -O[0-4] option specified. + unsigned OptimizeSize : 2; ///< If -Os (==1) or -Oz (==2) is specified. + unsigned RelaxAll : 1; ///< Relax all machine code instructions. + unsigned RelaxedAliasing : 1; ///< Set when -fno-strict-aliasing is enabled. + unsigned SaveTempLabels : 1; ///< Save temporary labels. + unsigned SimplifyLibCalls : 1; ///< Set when -fbuiltin is enabled. + unsigned SoftFloat : 1; ///< -soft-float. + unsigned StrictEnums : 1; ///< Optimize based on strict enum definition. + unsigned TimePasses : 1; ///< Set when -ftime-report is enabled. + unsigned UnitAtATime : 1; ///< Unused. For mirroring GCC optimization + ///< selection. + unsigned UnrollLoops : 1; ///< Control whether loops are unrolled. + unsigned UnsafeFPMath : 1; ///< Allow unsafe floating point optzns. + unsigned UnwindTables : 1; ///< Emit unwind tables. /// Attempt to use register sized accesses to bit-fields in structures, when /// possible. unsigned UseRegisterSizedBitfieldAccess : 1; - unsigned VerifyModule : 1; /// Control whether the module should be run - /// through the LLVM Verifier. + unsigned VerifyModule : 1; ///< Control whether the module should be run + ///< through the LLVM Verifier. - unsigned StackRealignment : 1; /// Control whether to permit stack - /// realignment. - unsigned StackAlignment; /// Overrides default stack alignment, - /// if not 0. + unsigned StackRealignment : 1; ///< Control whether to permit stack + ///< realignment. + unsigned UseInitArray : 1; ///< Control whether to use .init_array or + ///< .ctors. + unsigned StackAlignment; ///< Overrides default stack alignment, + ///< if not 0. /// The code model to use (-mcmodel). std::string CodeModel; @@ -127,6 +144,9 @@ public: /// The string to embed in debug information as the current working directory. std::string DebugCompilationDir; + /// The kind of generated debug info. + DebugInfoKind DebugInfo; + /// The string to embed in the debug information for the compile unit, if /// non-empty. std::string DwarfDebugFlags; @@ -162,6 +182,12 @@ public: /// or 0 if unspecified. unsigned NumRegisterParameters; + /// The run-time penalty for bounds checking, or 0 to disable. + unsigned char BoundsChecking; + + /// The default TLS model to use. + TLSModel DefaultTLSModel; + public: CodeGenOptions() { AsmVerbose = 0; @@ -169,8 +195,6 @@ public: CXAAtExit = 1; CXXCtorDtorAliases = 0; DataSections = 0; - DebugInfo = 0; - LimitDebugInfo = 0; DisableFPElim = 0; DisableLLVMOpts = 0; DisableRedZone = 0; @@ -178,6 +202,8 @@ public: EmitDeclMetadata = 0; EmitGcovArcs = 0; EmitGcovNotes = 0; + EmitOpenCLArgMetadata = 0; + EmitMicrosoftInlineAsm = 0; ForbidGuardVariables = 0; FunctionSections = 0; HiddenWeakTemplateVTables = 0; @@ -196,8 +222,6 @@ public: NumRegisterParameters = 0; ObjCAutoRefCountExceptions = 0; ObjCDispatchMethod = Legacy; - ObjCRuntimeHasARC = 0; - ObjCRuntimeHasTerminate = 0; OmitLeafFramePointer = 0; OptimizationLevel = 0; OptimizeSize = 0; @@ -216,9 +240,13 @@ public: VerifyModule = 1; StackRealignment = 0; StackAlignment = 0; + BoundsChecking = 0; + UseInitArray = 0; + DebugInfo = NoDebugInfo; Inlining = NoInlining; RelocationModel = "pic"; + DefaultTLSModel = GeneralDynamicTLSModel; } ObjCDispatchMethodKind getObjCDispatchMethod() const { diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 1bb7695..b28e103 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -560,8 +560,7 @@ public: static CodeCompleteConsumer * createCodeCompletionConsumer(Preprocessor &PP, const std::string &Filename, unsigned Line, unsigned Column, - bool ShowMacros, - bool ShowCodePatterns, bool ShowGlobals, + const CodeCompleteOptions &Opts, raw_ostream &OS); /// \brief Create the Sema object to be used for parsing. diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h index 0d2260a..d6fe003 100644 --- a/include/clang/Frontend/CompilerInvocation.h +++ b/include/clang/Frontend/CompilerInvocation.h @@ -38,10 +38,13 @@ namespace driver { class ArgList; } -/// CompilerInvocation - Fill out Opts based on the options given in Args. +/// \brief Fill out Opts based on the options given in Args. +/// /// Args must have been created from the OptTable returned by -/// createCC1OptTable(). When errors are encountered, return false and, -/// if Diags is non-null, report the error(s). +/// createCC1OptTable(). +/// +/// When errors are encountered, return false and, if Diags is non-null, +/// report the error(s). bool ParseDiagnosticArgs(DiagnosticOptions &Opts, driver::ArgList &Args, DiagnosticsEngine *Diags = 0); @@ -58,8 +61,7 @@ public: const LangOptions *getLangOpts() const { return LangOpts.getPtr(); } }; -/// CompilerInvocation - Helper class for holding the data necessary to invoke -/// the compiler. +/// \brief Helper class for holding the data necessary to invoke the compiler. /// /// This class is designed to represent an abstract "invocation" of the /// compiler, including data such as the include paths, the code generation @@ -85,10 +87,10 @@ class CompilerInvocation : public CompilerInvocationBase { /// Options controlling the frontend itself. FrontendOptions FrontendOpts; - /// Options controlling the #include directive. + /// Options controlling the \#include directive. HeaderSearchOptions HeaderSearchOpts; - /// Options controlling the preprocessor (aside from #include handling). + /// Options controlling the preprocessor (aside from \#include handling). PreprocessorOptions PreprocessorOpts; /// Options controlling preprocessed output. @@ -103,10 +105,10 @@ public: /// @name Utility Methods /// @{ - /// CreateFromArgs - Create a compiler invocation from a list of input - /// options. Returns true on success. + /// \brief Create a compiler invocation from a list of input options. + /// \returns true on success. /// - /// \param Res [out] - The resulting invocation. + /// \param [out] Res - The resulting invocation. /// \param ArgBegin - The first element in the argument vector. /// \param ArgEnd - The last element in the argument vector. /// \param Diags - The diagnostic engine to use for errors. @@ -115,7 +117,7 @@ public: const char* const *ArgEnd, DiagnosticsEngine &Diags); - /// GetBuiltinIncludePath - Get the directory where the compiler headers + /// \brief Get the directory where the compiler headers /// reside, relative to the compiler binary (found by the passed in /// arguments). /// @@ -125,24 +127,14 @@ public: /// executable), for finding the builtin compiler path. static std::string GetResourcesPath(const char *Argv0, void *MainAddr); - /// toArgs - Convert the CompilerInvocation to a list of strings suitable for + /// \brief Convert the CompilerInvocation to a list of strings suitable for /// passing to CreateFromArgs. - void toArgs(std::vector<std::string> &Res); - - /// setLangDefaults - Set language defaults for the given input language and - /// language standard in this CompilerInvocation. - /// - /// \param IK - The input language. - /// \param LangStd - The input language standard. - void setLangDefaults(InputKind IK, - LangStandard::Kind LangStd = LangStandard::lang_unspecified) { - setLangDefaults(*getLangOpts(), IK, LangStd); - } + void toArgs(std::vector<std::string> &Res) const; - /// setLangDefaults - Set language defaults for the given input language and + /// \brief Set language defaults for the given input language and /// language standard in the given LangOptions object. /// - /// \param LangOpts - The LangOptions object to set up. + /// \param Opts - The LangOptions object to set up. /// \param IK - The input language. /// \param LangStd - The input language standard. static void setLangDefaults(LangOptions &Opts, InputKind IK, diff --git a/include/clang/Frontend/DiagnosticOptions.h b/include/clang/Frontend/DiagnosticOptions.h index 1c6ba6a..8dec37c 100644 --- a/include/clang/Frontend/DiagnosticOptions.h +++ b/include/clang/Frontend/DiagnosticOptions.h @@ -47,6 +47,9 @@ public: /// diagnostics, indicated by markers in the /// input source file. + unsigned ElideType: 1; /// Elide identical types in template diffing + unsigned ShowTemplateTree: 1; /// Print a template tree when diffing + unsigned ErrorLimit; /// Limit # errors emitted. unsigned MacroBacktraceLimit; /// Limit depth of macro expansion backtrace. unsigned TemplateBacktraceLimit; /// Limit depth of instantiation backtrace. diff --git a/include/clang/Frontend/DiagnosticRenderer.h b/include/clang/Frontend/DiagnosticRenderer.h index 5ad88a8..09d7ecb 100644 --- a/include/clang/Frontend/DiagnosticRenderer.h +++ b/include/clang/Frontend/DiagnosticRenderer.h @@ -43,7 +43,6 @@ typedef llvm::PointerUnion<const Diagnostic *, /// class. class DiagnosticRenderer { protected: - const SourceManager &SM; const LangOptions &LangOpts; const DiagnosticOptions &DiagOpts; @@ -66,8 +65,7 @@ protected: /// which change the amount of information displayed. DiagnosticsEngine::Level LastLevel; - DiagnosticRenderer(const SourceManager &SM, - const LangOptions &LangOpts, + DiagnosticRenderer(const LangOptions &LangOpts, const DiagnosticOptions &DiagOpts); virtual ~DiagnosticRenderer(); @@ -76,20 +74,24 @@ protected: DiagnosticsEngine::Level Level, StringRef Message, ArrayRef<CharSourceRange> Ranges, + const SourceManager *SM, DiagOrStoredDiag Info) = 0; virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, - ArrayRef<CharSourceRange> Ranges) = 0; + ArrayRef<CharSourceRange> Ranges, + const SourceManager &SM) = 0; virtual void emitBasicNote(StringRef Message) = 0; virtual void emitCodeContext(SourceLocation Loc, DiagnosticsEngine::Level Level, SmallVectorImpl<CharSourceRange>& Ranges, - ArrayRef<FixItHint> Hints) = 0; + ArrayRef<FixItHint> Hints, + const SourceManager &SM) = 0; - virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc) = 0; + virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, + const SourceManager &SM) = 0; virtual void beginDiagnostic(DiagOrStoredDiag D, DiagnosticsEngine::Level Level) {} @@ -98,12 +100,14 @@ protected: private: - void emitIncludeStack(SourceLocation Loc, DiagnosticsEngine::Level Level); - void emitIncludeStackRecursively(SourceLocation Loc); + void emitIncludeStack(SourceLocation Loc, DiagnosticsEngine::Level Level, + const SourceManager &SM); + void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM); void emitMacroExpansionsAndCarets(SourceLocation Loc, DiagnosticsEngine::Level Level, SmallVectorImpl<CharSourceRange>& Ranges, ArrayRef<FixItHint> Hints, + const SourceManager &SM, unsigned &MacroDepth, unsigned OnMacroInst = 0); public: @@ -119,9 +123,12 @@ public: /// \param Message The diagnostic message to emit. /// \param Ranges The underlined ranges for this code snippet. /// \param FixItHints The FixIt hints active for this diagnostic. + /// \param SM The SourceManager; will be null if the diagnostic came from the + /// frontend, thus \param Loc will be invalid. void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> FixItHints, + const SourceManager *SM, DiagOrStoredDiag D = (Diagnostic *)0); void emitStoredDiagnostic(StoredDiagnostic &Diag); @@ -131,19 +138,20 @@ public: /// notes. It is up to subclasses to further define the behavior. class DiagnosticNoteRenderer : public DiagnosticRenderer { public: - DiagnosticNoteRenderer(const SourceManager &SM, - const LangOptions &LangOpts, + DiagnosticNoteRenderer(const LangOptions &LangOpts, const DiagnosticOptions &DiagOpts) - : DiagnosticRenderer(SM, LangOpts, DiagOpts) {} + : DiagnosticRenderer(LangOpts, DiagOpts) {} virtual ~DiagnosticNoteRenderer(); virtual void emitBasicNote(StringRef Message); virtual void emitIncludeLocation(SourceLocation Loc, - PresumedLoc PLoc); + PresumedLoc PLoc, + const SourceManager &SM); - virtual void emitNote(SourceLocation Loc, StringRef Message) = 0; + virtual void emitNote(SourceLocation Loc, StringRef Message, + const SourceManager *SM) = 0; }; } // end clang namespace #endif diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h index 6839028..c0056de 100644 --- a/include/clang/Frontend/FrontendAction.h +++ b/include/clang/Frontend/FrontendAction.h @@ -188,7 +188,7 @@ public: bool BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input); /// Execute - Set the source managers main input file, and run the action. - void Execute(); + bool Execute(); /// EndSourceFile - Perform any per-file post processing, deallocate per-file /// objects, and run statistics and output file cleanup code. diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h index 8f7fe87..477ac45 100644 --- a/include/clang/Frontend/FrontendActions.h +++ b/include/clang/Frontend/FrontendActions.h @@ -50,6 +50,12 @@ protected: StringRef InFile); }; +class ASTDeclListAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile); +}; + class ASTDumpXMLAction : public ASTFrontendAction { protected: virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index 888388c..ce1cd9b 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H #include "clang/Frontend/CommandLineSourceLoc.h" +#include "clang/Sema/CodeCompleteOptions.h" #include "llvm/ADT/StringRef.h" #include <string> #include <vector> @@ -19,6 +20,7 @@ namespace clang { namespace frontend { enum ActionKind { + ASTDeclList, ///< Parse ASTs and list Decl nodes. ASTDump, ///< Parse ASTs and dump them. ASTDumpXML, ///< Parse ASTs and dump them in XML. ASTPrint, ///< Parse ASTs and print them. @@ -42,7 +44,7 @@ namespace frontend { PrintDeclContext, ///< Print DeclContext and their Decls. PrintPreamble, ///< Print the "preamble" of the input file PrintPreprocessedInput, ///< -E mode. - RewriteMacros, ///< Expand macros but not #includes. + RewriteMacros, ///< Expand macros but not \#includes. RewriteObjC, ///< ObjC->C Rewriter. RewriteTest, ///< Rewriter playground RunAnalysis, ///< Run one or more source code analyses. @@ -84,7 +86,7 @@ struct FrontendInputFile { FrontendInputFile(StringRef File, InputKind Kind, bool IsSystem = false) : File(File.str()), Kind(Kind), IsSystem(IsSystem) { } }; - + /// FrontendOptions - Options for controlling the behavior of the frontend. class FrontendOptions { public: @@ -93,12 +95,6 @@ public: /// instruct the AST writer to create /// relocatable PCH files. unsigned ShowHelp : 1; ///< Show the -help text. - unsigned ShowMacrosInCodeCompletion : 1; ///< Show macros in code completion - /// results. - unsigned ShowCodePatternsInCodeCompletion : 1; ///< Show code patterns in code - /// completion results. - unsigned ShowGlobalSymbolsInCodeCompletion : 1; ///< Show top-level decls in - /// code completion results. unsigned ShowStats : 1; ///< Show frontend performance /// metrics and statistics. unsigned ShowTimers : 1; ///< Show timers for individual @@ -116,6 +112,8 @@ public: /// not need them (e.g. with code /// completion). + CodeCompleteOptions CodeCompleteOpts; + enum { ARCMT_None, ARCMT_Check, @@ -144,6 +142,9 @@ public: /// If given, the new suffix for fix-it rewritten files. std::string FixItSuffix; + /// If given, filter dumped AST Decl nodes by this substring. + std::string ASTDumpFilter; + /// If given, enable code completion at the provided location. ParsedSourceLocation CodeCompletionAt; @@ -183,9 +184,6 @@ public: ActionName = ""; RelocatablePCH = 0; ShowHelp = 0; - ShowMacrosInCodeCompletion = 0; - ShowCodePatternsInCodeCompletion = 0; - ShowGlobalSymbolsInCodeCompletion = 1; ShowStats = 0; ShowTimers = 0; ShowVersion = 0; diff --git a/include/clang/Frontend/HeaderSearchOptions.h b/include/clang/Frontend/HeaderSearchOptions.h index 687f439..ebc8f26 100644 --- a/include/clang/Frontend/HeaderSearchOptions.h +++ b/include/clang/Frontend/HeaderSearchOptions.h @@ -17,12 +17,12 @@ namespace clang { namespace frontend { /// IncludeDirGroup - Identifiers the group a include entry belongs to, which - /// represents its relative positive in the search list. A #include of a "" + /// represents its relative positive in the search list. A \#include of a "" /// path starts at the -iquote group, then searches the Angled group, then /// searches the system group, etc. enum IncludeDirGroup { - Quoted = 0, ///< '#include ""' paths, added by'gcc -iquote'. - Angled, ///< Paths for '#include <>' added by '-I'. + Quoted = 0, ///< '\#include ""' paths, added by 'gcc -iquote'. + Angled, ///< Paths for '\#include <>' added by '-I'. IndexHeaderMap, ///< Like Angled, but marks header maps used when /// building frameworks. System, ///< Like Angled, but marks system directories. @@ -69,6 +69,18 @@ public: IsInternal(isInternal), ImplicitExternC(implicitExternC) {} }; + struct SystemHeaderPrefix { + /// A prefix to be matched against paths in \#include directives. + std::string Prefix; + + /// True if paths beginning with this prefix should be treated as system + /// headers. + bool IsSystemHeader; + + SystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) + : Prefix(Prefix), IsSystemHeader(IsSystemHeader) {} + }; + /// If non-empty, the directory to use as a "virtual system root" for include /// paths. std::string Sysroot; @@ -76,6 +88,9 @@ public: /// User specified include entries. std::vector<Entry> UserEntries; + /// User-specified system header prefixes. + std::vector<SystemHeaderPrefix> SystemHeaderPrefixes; + /// The directory which holds the compiler resource files (builtin includes, /// etc.). std::string ResourceDir; @@ -117,6 +132,13 @@ public: UserEntries.push_back(Entry(Path, Group, IsUserSupplied, IsFramework, IgnoreSysRoot, IsInternal, ImplicitExternC)); } + + /// AddSystemHeaderPrefix - Override whether \#include directives naming a + /// path starting with \arg Prefix should be considered as naming a system + /// header. + void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) { + SystemHeaderPrefixes.push_back(SystemHeaderPrefix(Prefix, IsSystemHeader)); + } }; } // end namespace clang diff --git a/include/clang/Frontend/LangStandards.def b/include/clang/Frontend/LangStandards.def index 4bcff4a..a604d4b 100644 --- a/include/clang/Frontend/LangStandards.def +++ b/include/clang/Frontend/LangStandards.def @@ -111,6 +111,12 @@ LANGSTANDARD(gnucxx11, "gnu++11", LANGSTANDARD(opencl, "cl", "OpenCL 1.0", BCPLComment | C99 | Digraphs | HexFloat) +LANGSTANDARD(opencl11, "CL1.1", + "OpenCL 1.1", + BCPLComment | C99 | Digraphs | HexFloat) +LANGSTANDARD(opencl12, "CL1.2", + "OpenCL 1.2", + BCPLComment | C99 | Digraphs | HexFloat) // CUDA LANGSTANDARD(cuda, "cuda", diff --git a/include/clang/Frontend/PreprocessorOutputOptions.h b/include/clang/Frontend/PreprocessorOutputOptions.h index 1eda0d4..9793aa6 100644 --- a/include/clang/Frontend/PreprocessorOutputOptions.h +++ b/include/clang/Frontend/PreprocessorOutputOptions.h @@ -18,9 +18,10 @@ class PreprocessorOutputOptions { public: unsigned ShowCPP : 1; ///< Print normal preprocessed output. unsigned ShowComments : 1; ///< Show comments. - unsigned ShowLineMarkers : 1; ///< Show #line markers. + unsigned ShowLineMarkers : 1; ///< Show \#line markers. unsigned ShowMacroComments : 1; ///< Show comments, even in macros. unsigned ShowMacros : 1; ///< Print macro definitions. + unsigned RewriteIncludes : 1; ///< Preprocess include directives only. public: PreprocessorOutputOptions() { @@ -29,6 +30,7 @@ public: ShowLineMarkers = 1; ShowMacroComments = 0; ShowMacros = 0; + RewriteIncludes = 0; } }; diff --git a/include/clang/Frontend/TextDiagnostic.h b/include/clang/Frontend/TextDiagnostic.h index 314003b..c869c08 100644 --- a/include/clang/Frontend/TextDiagnostic.h +++ b/include/clang/Frontend/TextDiagnostic.h @@ -39,7 +39,6 @@ class TextDiagnostic : public DiagnosticRenderer { public: TextDiagnostic(raw_ostream &OS, - const SourceManager &SM, const LangOptions &LangOpts, const DiagnosticOptions &DiagOpts); @@ -60,7 +59,7 @@ public: /// /// This is a static helper to handle the line wrapping, colorizing, and /// rendering of a diagnostic message to a particular ostream. It is - /// publically visible so that clients which do not have sufficient state to + /// publicly visible so that clients which do not have sufficient state to /// build a complete TextDiagnostic object can still get consistent /// formatting of their diagnostic messages. /// @@ -83,39 +82,46 @@ protected: DiagnosticsEngine::Level Level, StringRef Message, ArrayRef<CharSourceRange> Ranges, + const SourceManager *SM, DiagOrStoredDiag D); virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, - ArrayRef<CharSourceRange> Ranges); + ArrayRef<CharSourceRange> Ranges, + const SourceManager &SM); virtual void emitCodeContext(SourceLocation Loc, DiagnosticsEngine::Level Level, SmallVectorImpl<CharSourceRange>& Ranges, - ArrayRef<FixItHint> Hints) { - emitSnippetAndCaret(Loc, Level, Ranges, Hints); + ArrayRef<FixItHint> Hints, + const SourceManager &SM) { + emitSnippetAndCaret(Loc, Level, Ranges, Hints, SM); } virtual void emitBasicNote(StringRef Message); - virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc); + virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, + const SourceManager &SM); private: void emitSnippetAndCaret(SourceLocation Loc, DiagnosticsEngine::Level Level, SmallVectorImpl<CharSourceRange>& Ranges, - ArrayRef<FixItHint> Hints); + ArrayRef<FixItHint> Hints, + const SourceManager &SM); void emitSnippet(StringRef SourceLine); void highlightRange(const CharSourceRange &R, unsigned LineNo, FileID FID, const SourceColumnMap &map, - std::string &CaretLine); + std::string &CaretLine, + const SourceManager &SM); std::string buildFixItInsertionLine(unsigned LineNo, const SourceColumnMap &map, - ArrayRef<FixItHint> Hints); - void emitParseableFixits(ArrayRef<FixItHint> Hints); + ArrayRef<FixItHint> Hints, + const SourceManager &SM); + void emitParseableFixits(ArrayRef<FixItHint> Hints, const SourceManager &SM); }; } // end namespace clang diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h index 9b6ac24..23cf521 100644 --- a/include/clang/Frontend/TextDiagnosticPrinter.h +++ b/include/clang/Frontend/TextDiagnosticPrinter.h @@ -26,9 +26,7 @@ class TextDiagnostic; class TextDiagnosticPrinter : public DiagnosticConsumer { raw_ostream &OS; - const LangOptions *LangOpts; const DiagnosticOptions *DiagOpts; - const SourceManager *SM; /// \brief Handle to the currently active text diagnostic emitter. OwningPtr<TextDiagnostic> TextDiag; diff --git a/include/clang/Frontend/VerifyDiagnosticConsumer.h b/include/clang/Frontend/VerifyDiagnosticConsumer.h index 2fc6ccc..a74589e 100644 --- a/include/clang/Frontend/VerifyDiagnosticConsumer.h +++ b/include/clang/Frontend/VerifyDiagnosticConsumer.h @@ -11,12 +11,18 @@ #define LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICSCLIENT_H #include "clang/Basic/Diagnostic.h" +#include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/STLExtras.h" +#include <climits> namespace clang { class DiagnosticsEngine; class TextDiagnosticBuffer; +class FileEntry; /// VerifyDiagnosticConsumer - Create a diagnostic client which will use /// markers in the input source to check that all the emitted diagnostics match @@ -35,18 +41,58 @@ class TextDiagnosticBuffer; /// /// Here's an example: /// +/// \code /// int A = B; // expected-error {{use of undeclared identifier 'B'}} +/// \endcode /// /// You can place as many diagnostics on one line as you wish. To make the code /// more readable, you can use slash-newline to separate out the diagnostics. /// +/// Alternatively, it is possible to specify the line on which the diagnostic +/// should appear by appending "@<line>" to "expected-<type>", for example: +/// +/// \code +/// #warning some text +/// // expected-warning@10 {{some text}} +/// \endcode +/// +/// The line number may be absolute (as above), or relative to the current +/// line by prefixing the number with either '+' or '-'. +/// /// The simple syntax above allows each specification to match exactly one /// error. You can use the extended syntax to customize this. The extended -/// syntax is "expected-<type> <n> {{diag text}}", where <type> is one of -/// "error", "warning" or "note", and <n> is a positive integer. This allows the -/// diagnostic to appear as many times as specified. Example: +/// syntax is "expected-<type> <n> {{diag text}}", where \<type> is one of +/// "error", "warning" or "note", and \<n> is a positive integer. This allows +/// the diagnostic to appear as many times as specified. Example: /// +/// \code /// void f(); // expected-note 2 {{previous declaration is here}} +/// \endcode +/// +/// Where the diagnostic is expected to occur a minimum number of times, this +/// can be specified by appending a '+' to the number. Example: +/// +/// \code +/// void f(); // expected-note 0+ {{previous declaration is here}} +/// void g(); // expected-note 1+ {{previous declaration is here}} +/// \endcode +/// +/// In the first example, the diagnostic becomes optional, i.e. it will be +/// swallowed if it occurs, but will not generate an error if it does not +/// occur. In the second example, the diagnostic must occur at least once. +/// As a short-hand, "one or more" can be specified simply by '+'. Example: +/// +/// \code +/// void g(); // expected-note + {{previous declaration is here}} +/// \endcode +/// +/// A range can also be specified by "<n>-<m>". Example: +/// +/// \code +/// void f(); // expected-note 0-1 {{previous declaration is here}} +/// \endcode +/// +/// In this example, the diagnostic may appear only once, if at all. /// /// Regex matching mode may be selected by appending '-re' to type. Example: /// @@ -62,20 +108,85 @@ class TextDiagnosticBuffer; /// // expected-error-re {{variable has has type 'struct (.*)'}} /// // expected-error-re {{variable has has type 'struct[[:space:]](.*)'}} /// -class VerifyDiagnosticConsumer: public DiagnosticConsumer { +class VerifyDiagnosticConsumer: public DiagnosticConsumer, + public CommentHandler { public: + /// Directive - Abstract class representing a parsed verify directive. + /// + class Directive { + public: + static Directive *create(bool RegexKind, SourceLocation DirectiveLoc, + SourceLocation DiagnosticLoc, + StringRef Text, unsigned Min, unsigned Max); + public: + /// Constant representing n or more matches. + static const unsigned MaxCount = UINT_MAX; + + SourceLocation DirectiveLoc; + SourceLocation DiagnosticLoc; + const std::string Text; + unsigned Min, Max; + + virtual ~Directive() { } + + // Returns true if directive text is valid. + // Otherwise returns false and populates E. + virtual bool isValid(std::string &Error) = 0; + + // Returns true on match. + virtual bool match(StringRef S) = 0; + + protected: + Directive(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc, + StringRef Text, unsigned Min, unsigned Max) + : DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc), + Text(Text), Min(Min), Max(Max) { + assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!"); + assert(!DiagnosticLoc.isInvalid() && "DiagnosticLoc is invalid!"); + } + + private: + Directive(const Directive&); // DO NOT IMPLEMENT + void operator=(const Directive&); // DO NOT IMPLEMENT + }; + + typedef std::vector<Directive*> DirectiveList; + + /// ExpectedData - owns directive objects and deletes on destructor. + /// + struct ExpectedData { + DirectiveList Errors; + DirectiveList Warnings; + DirectiveList Notes; + + ~ExpectedData() { + llvm::DeleteContainerPointers(Errors); + llvm::DeleteContainerPointers(Warnings); + llvm::DeleteContainerPointers(Notes); + } + }; + +#ifndef NDEBUG + typedef llvm::DenseSet<FileID> FilesWithDiagnosticsSet; + typedef llvm::SmallPtrSet<const FileEntry *, 4> FilesParsedForDirectivesSet; +#endif + +private: DiagnosticsEngine &Diags; DiagnosticConsumer *PrimaryClient; bool OwnsPrimaryClient; OwningPtr<TextDiagnosticBuffer> Buffer; - Preprocessor *CurrentPreprocessor; - -private: - FileID FirstErrorFID; // FileID of first diagnostic + const Preprocessor *CurrentPreprocessor; + unsigned ActiveSourceFiles; +#ifndef NDEBUG + FilesWithDiagnosticsSet FilesWithDiagnostics; + FilesParsedForDirectivesSet FilesParsedForDirectives; +#endif + ExpectedData ED; void CheckDiagnostics(); public: - /// Create a new verifying diagnostic client, which will issue errors to \arg + /// Create a new verifying diagnostic client, which will issue errors to /// the currently-attached diagnostic client when a diagnostic does not match /// what is expected (as indicated in the source file). VerifyDiagnosticConsumer(DiagnosticsEngine &Diags); @@ -86,6 +197,15 @@ public: virtual void EndSourceFile(); + /// \brief Manually register a file as parsed. + inline void appendParsedFile(const FileEntry *File) { +#ifndef NDEBUG + FilesParsedForDirectives.insert(File); +#endif + } + + virtual bool HandleComment(Preprocessor &PP, SourceRange Comment); + virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info); diff --git a/include/clang/Lex/CodeCompletionHandler.h b/include/clang/Lex/CodeCompletionHandler.h index d876776..91c3b78 100644 --- a/include/clang/Lex/CodeCompletionHandler.h +++ b/include/clang/Lex/CodeCompletionHandler.h @@ -43,11 +43,11 @@ public: /// where the name of a macro is expected. /// /// \param IsDefinition Whether this is the definition of a macro, e.g., - /// in a #define. + /// in a \#define. virtual void CodeCompleteMacroName(bool IsDefinition) { } /// \brief Callback invoked when performing code completion in a preprocessor - /// expression, such as the condition of an #if or #elif directive. + /// expression, such as the condition of an \#if or \#elif directive. virtual void CodeCompletePreprocessorExpression() { } /// \brief Callback invoked when performing code completion inside a @@ -62,7 +62,7 @@ public: /// \brief Callback invoked when performing code completion in a part of the /// file where we expect natural language, e.g., a comment, string, or - /// #error directive. + /// \#error directive. virtual void CodeCompleteNaturalLanguage() { } }; diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h index 95f0d27..d773fc6 100644 --- a/include/clang/Lex/DirectoryLookup.h +++ b/include/clang/Lex/DirectoryLookup.h @@ -25,7 +25,7 @@ class HeaderSearch; class Module; /// DirectoryLookup - This class represents one entry in the search list that -/// specifies the search order for directories in #include directives. It +/// specifies the search order for directories in \#include directives. It /// represents either a directory, a framework, or a headermap. /// class DirectoryLookup { @@ -146,14 +146,14 @@ public: /// part of a known module, this will be set to the module that should /// be imported instead of preprocessing/parsing the file found. /// - /// \param InUserSpecifiedSystemHeader [out] If the file is found, set to true - /// if the file is located in a framework that has been user-specified to be - /// treated as a system framework. + /// \param [out] InUserSpecifiedSystemFramework If the file is found, + /// set to true if the file is located in a framework that has been + /// user-specified to be treated as a system framework. const FileEntry *LookupFile(StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, Module **SuggestedModule, - bool &InUserSpecifiedSystemHeader) const; + bool &InUserSpecifiedSystemFramework) const; private: const FileEntry *DoFrameworkLookup( diff --git a/include/clang/Lex/HeaderMap.h b/include/clang/Lex/HeaderMap.h index 08bc5b6..107408d 100644 --- a/include/clang/Lex/HeaderMap.h +++ b/include/clang/Lex/HeaderMap.h @@ -26,7 +26,7 @@ namespace clang { struct HMapHeader; /// This class represents an Apple concept known as a 'header map'. To the -/// #include file resolution process, it basically acts like a directory of +/// \#include file resolution process, it basically acts like a directory of /// symlinks to files. Its advantages are that it is dense and more efficient /// to create and process than a directory of symlinks. class HeaderMap { diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 5128ce6..8e9491f 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -16,6 +16,7 @@ #include "clang/Lex/DirectoryLookup.h" #include "clang/Lex/ModuleMap.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/Allocator.h" @@ -30,18 +31,18 @@ class FileEntry; class FileManager; class IdentifierInfo; -/// HeaderFileInfo - The preprocessor keeps track of this information for each -/// file that is #included. +/// \brief The preprocessor keeps track of this information for each +/// file that is \#included. struct HeaderFileInfo { - /// isImport - True if this is a #import'd or #pragma once file. + /// \brief True if this is a \#import'd or \#pragma once file. unsigned isImport : 1; - /// isPragmaOnce - True if this is #pragma once file. + /// \brief True if this is a \#pragma once file. unsigned isPragmaOnce : 1; /// DirInfo - Keep track of whether this is a system header, and if so, /// whether it is C++ clean or not. This can be set by the include paths or - /// by #pragma gcc system_header. This is an instance of + /// by \#pragma gcc system_header. This is an instance of /// SrcMgr::CharacteristicKind. unsigned DirInfo : 2; @@ -61,8 +62,7 @@ struct HeaderFileInfo { /// those framework headers. unsigned IndexHeaderMapHeader : 1; - /// NumIncludes - This is the number of times the file has been included - /// already. + /// \brief The number of times the file has been included already. unsigned short NumIncludes; /// \brief The ID number of the controlling macro. @@ -72,8 +72,8 @@ struct HeaderFileInfo { /// external storage. unsigned ControllingMacroID; - /// ControllingMacro - If this file has a #ifndef XXX (or equivalent) guard - /// that protects the entire contents of the file, this is the identifier + /// If this file has a \#ifndef XXX (or equivalent) guard that + /// protects the entire contents of the file, this is the identifier /// for the macro that controls whether or not it has any effect. /// /// Note: Most clients should use getControllingMacro() to access @@ -117,8 +117,8 @@ public: virtual HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) = 0; }; -/// HeaderSearch - This class encapsulates the information needed to find the -/// file referenced by a #include or #include_next, (sub-)framework lookup, etc. +/// \brief Encapsulates the information needed to find the file referenced +/// by a \#include or \#include_next, (sub-)framework lookup, etc. class HeaderSearch { /// This structure is used to record entries in our framework cache. struct FrameworkCacheEntry { @@ -133,8 +133,8 @@ class HeaderSearch { FileManager &FileMgr; DiagnosticsEngine &Diags; - /// #include search path information. Requests for #include "x" search the - /// directory of the #including file first, then each directory in SearchDirs + /// \#include search path information. Requests for \#include "x" search the + /// directory of the \#including file first, then each directory in SearchDirs /// consecutively. Requests for <x> search the current dir first, then each /// directory in SearchDirs, starting at AngledDirIdx, consecutively. If /// NoCurDirSearch is true, then the check for the file in the current @@ -144,24 +144,32 @@ class HeaderSearch { unsigned SystemDirIdx; bool NoCurDirSearch; + /// \brief \#include prefixes for which the 'system header' property is + /// overridden. + /// + /// For a \#include "x" or \#include \<x> directive, the last string in this + /// list which is a prefix of 'x' determines whether the file is treated as + /// a system header. + std::vector<std::pair<std::string, bool> > SystemHeaderPrefixes; + /// \brief The path to the module cache. std::string ModuleCachePath; - /// FileInfo - This contains all of the preprocessor-specific data about files - /// that are included. The vector is indexed by the FileEntry's UID. - /// + /// \brief All of the preprocessor-specific data about files that are + /// included, indexed by the FileEntry's UID. std::vector<HeaderFileInfo> FileInfo; - /// LookupFileCache - This is keeps track of each lookup performed by - /// LookupFile. The first part of the value is the starting index in - /// SearchDirs that the cached search was performed from. If there is a hit - /// and this value doesn't match the current query, the cache has to be - /// ignored. The second value is the entry in SearchDirs that satisfied the - /// query. + /// \brief Keeps track of each lookup performed by LookupFile. + /// + /// The first part of the value is the starting index in SearchDirs + /// that the cached search was performed from. If there is a hit and + /// this value doesn't match the current query, the cache has to be + /// ignored. The second value is the entry in SearchDirs that satisfied + /// the query. llvm::StringMap<std::pair<unsigned, unsigned>, llvm::BumpPtrAllocator> LookupFileCache; - /// FrameworkMap - This is a collection mapping a framework or subframework + /// \brief Collection mapping a framework or subframework /// name like "Carbon" to the Carbon.framework directory. llvm::StringMap<FrameworkCacheEntry, llvm::BumpPtrAllocator> FrameworkMap; @@ -212,8 +220,7 @@ public: FileManager &getFileMgr() const { return FileMgr; } - /// SetSearchPaths - Interface for setting the file search paths. - /// + /// \brief Interface for setting the file search paths. void SetSearchPaths(const std::vector<DirectoryLookup> &dirs, unsigned angledDirIdx, unsigned systemDirIdx, bool noCurDirSearch) { @@ -226,7 +233,7 @@ public: //LookupFileCache.clear(); } - /// AddSearchPath - Add an additional search path. + /// \brief Add an additional search path. void AddSearchPath(const DirectoryLookup &dir, bool isAngled) { unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx; SearchDirs.insert(SearchDirs.begin() + idx, dir); @@ -235,12 +242,18 @@ public: SystemDirIdx++; } - /// HasIncludeAliasMap - Checks whether the map exists or not + /// \brief Set the list of system header prefixes. + void SetSystemHeaderPrefixes(ArrayRef<std::pair<std::string, bool> > P) { + SystemHeaderPrefixes.assign(P.begin(), P.end()); + } + + /// \brief Checks whether the map exists or not. bool HasIncludeAliasMap() const { return IncludeAliases; } - /// AddIncludeAlias - Map the source include name to the dest include name. + /// \brief Map the source include name to the dest include name. + /// /// The Source should include the angle brackets or quotes, the dest /// should not. This allows for distinction between <> and "" headers. void AddIncludeAlias(StringRef Source, StringRef Dest) { @@ -271,7 +284,7 @@ public: /// \brief Retrieve the path to the module cache. StringRef getModuleCachePath() const { return ModuleCachePath; } - /// ClearFileInfo - Forget everything we know about headers so far. + /// \brief Forget everything we know about headers so far. void ClearFileInfo() { FileInfo.clear(); } @@ -293,7 +306,7 @@ public: /// already known. void setTarget(const TargetInfo &Target); - /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file, + /// \brief Given a "foo" or \<foo> reference, look up the indicated file, /// return null on failure. /// /// \returns If successful, this returns 'UsedDir', the DirectoryLookup member @@ -302,9 +315,9 @@ public: /// \param isAngled indicates whether the file reference is a <> reference. /// /// \param CurDir If non-null, the file was found in the specified directory - /// search location. This is used to implement #include_next. + /// search location. This is used to implement \#include_next. /// - /// \param CurFileEnt If non-null, indicates where the #including file is, in + /// \param CurFileEnt If non-null, indicates where the \#including file is, in /// case a relative search is needed. /// /// \param SearchPath If non-null, will be set to the search path relative @@ -327,73 +340,76 @@ public: Module **SuggestedModule, bool SkipCache = false); - /// LookupSubframeworkHeader - Look up a subframework for the specified - /// #include file. For example, if #include'ing <HIToolbox/HIToolbox.h> from - /// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox - /// is a subframework within Carbon.framework. If so, return the FileEntry - /// for the designated file, otherwise return null. + /// \brief Look up a subframework for the specified \#include file. + /// + /// For example, if \#include'ing <HIToolbox/HIToolbox.h> from + /// within ".../Carbon.framework/Headers/Carbon.h", check to see if + /// HIToolbox is a subframework within Carbon.framework. If so, return + /// the FileEntry for the designated file, otherwise return null. const FileEntry *LookupSubframeworkHeader( StringRef Filename, const FileEntry *RelativeFileEnt, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath); - /// LookupFrameworkCache - Look up the specified framework name in our - /// framework cache, returning the DirectoryEntry it is in if we know, - /// otherwise, return null. + /// \brief Look up the specified framework name in our framework cache. + /// \returns The DirectoryEntry it is in if we know, null otherwise. FrameworkCacheEntry &LookupFrameworkCache(StringRef FWName) { return FrameworkMap.GetOrCreateValue(FWName).getValue(); } - /// ShouldEnterIncludeFile - Mark the specified file as a target of of a - /// #include, #include_next, or #import directive. Return false if #including - /// the file will have no effect or true if we should include it. + /// \brief Mark the specified file as a target of of a \#include, + /// \#include_next, or \#import directive. + /// + /// \return false if \#including the file will have no effect or true + /// if we should include it. bool ShouldEnterIncludeFile(const FileEntry *File, bool isImport); - /// getFileDirFlavor - Return whether the specified file is a normal header, + /// \brief Return whether the specified file is a normal header, /// a system header, or a C++ friendly system header. SrcMgr::CharacteristicKind getFileDirFlavor(const FileEntry *File) { return (SrcMgr::CharacteristicKind)getFileInfo(File).DirInfo; } - /// MarkFileIncludeOnce - Mark the specified file as a "once only" file, e.g. - /// due to #pragma once. + /// \brief Mark the specified file as a "once only" file, e.g. due to + /// \#pragma once. void MarkFileIncludeOnce(const FileEntry *File) { HeaderFileInfo &FI = getFileInfo(File); FI.isImport = true; FI.isPragmaOnce = true; } - /// MarkFileSystemHeader - Mark the specified file as a system header, e.g. - /// due to #pragma GCC system_header. + /// \brief Mark the specified file as a system header, e.g. due to + /// \#pragma GCC system_header. void MarkFileSystemHeader(const FileEntry *File) { getFileInfo(File).DirInfo = SrcMgr::C_System; } - /// IncrementIncludeCount - Increment the count for the number of times the - /// specified FileEntry has been entered. + /// \brief Increment the count for the number of times the specified + /// FileEntry has been entered. void IncrementIncludeCount(const FileEntry *File) { ++getFileInfo(File).NumIncludes; } - /// SetFileControllingMacro - Mark the specified file as having a controlling - /// macro. This is used by the multiple-include optimization to eliminate - /// no-op #includes. + /// \brief Mark the specified file as having a controlling macro. + /// + /// This is used by the multiple-include optimization to eliminate + /// no-op \#includes. void SetFileControllingMacro(const FileEntry *File, const IdentifierInfo *ControllingMacro) { getFileInfo(File).ControllingMacro = ControllingMacro; } /// \brief Determine whether this file is intended to be safe from - /// multiple inclusions, e.g., it has #pragma once or a controlling + /// multiple inclusions, e.g., it has \#pragma once or a controlling /// macro. /// - /// This routine does not consider the effect of #import + /// This routine does not consider the effect of \#import bool isFileMultipleIncludeGuarded(const FileEntry *File); /// CreateHeaderMap - This method returns a HeaderMap for the specified - /// FileEntry, uniquing them through the the 'HeaderMaps' datastructure. + /// FileEntry, uniquing them through the 'HeaderMaps' datastructure. const HeaderMap *CreateHeaderMap(const FileEntry *FE); /// \brief Retrieve the name of the module file that should be used to @@ -408,7 +424,7 @@ public: /// \brief Retrieve the name of the module file that should be used to /// load a module with the given name. /// - /// \param Module The module whose module file name will be returned. + /// \param ModuleName The module whose module file name will be returned. /// /// \returns The name of the module file that corresponds to this module, /// or an empty string if this module does not correspond to any module file. @@ -445,8 +461,6 @@ public: /// /// \param File The module map file. /// - /// \param OnlyModule If non-NULL, this will receive the - /// /// \returns true if an error occurred, false otherwise. bool loadModuleMapFile(const FileEntry *File); @@ -480,8 +494,7 @@ public: // Used by ASTReader. void setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID); - /// getFileInfo - Return the HeaderFileInfo structure for the specified - /// FileEntry. + /// \brief Return the HeaderFileInfo structure for the specified FileEntry. const HeaderFileInfo &getFileInfo(const FileEntry *FE) const { return const_cast<HeaderSearch*>(this)->getFileInfo(FE); } @@ -552,8 +565,7 @@ private: /// named directory. LoadModuleMapResult loadModuleMapFile(const DirectoryEntry *Dir); - /// getFileInfo - Return the HeaderFileInfo structure for the specified - /// FileEntry. + /// \brief Return the HeaderFileInfo structure for the specified FileEntry. HeaderFileInfo &getFileInfo(const FileEntry *FE); }; diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index 04bcead..ca233de 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -97,14 +97,14 @@ public: Lexer(FileID FID, const llvm::MemoryBuffer *InputBuffer, Preprocessor &PP); /// Lexer constructor - Create a new raw lexer object. This object is only - /// suitable for calls to 'LexRawToken'. This lexer assumes that the text - /// range will outlive it, so it doesn't take ownership of it. + /// suitable for calls to 'LexFromRawLexer'. This lexer assumes that the + /// text range will outlive it, so it doesn't take ownership of it. Lexer(SourceLocation FileLoc, const LangOptions &LangOpts, const char *BufStart, const char *BufPtr, const char *BufEnd); /// Lexer constructor - Create a new raw lexer object. This object is only - /// suitable for calls to 'LexRawToken'. This lexer assumes that the text - /// range will outlive it, so it doesn't take ownership of it. + /// suitable for calls to 'LexFromRawLexer'. This lexer assumes that the + /// text range will outlive it, so it doesn't take ownership of it. Lexer(FileID FID, const llvm::MemoryBuffer *InputBuffer, const SourceManager &SM, const LangOptions &LangOpts); @@ -200,7 +200,7 @@ public: /// ReadToEndOfLine - Read the rest of the current preprocessor line as an /// uninterpreted string. This switches the lexer out of directive mode. - std::string ReadToEndOfLine(); + void ReadToEndOfLine(SmallVectorImpl<char> *Result = 0); /// Diag - Forwarding function for diagnostics. This translate a source @@ -335,6 +335,28 @@ public: /// /// Returns a null range if a part of the range resides inside a macro /// expansion or the range does not reside on the same FileID. + /// + /// This function is trying to deal with macros and return a range based on + /// file locations. The cases where it can successfully handle macros are: + /// + /// -begin or end range lies at the start or end of a macro expansion, in + /// which case the location will be set to the expansion point, e.g: + /// \#define M 1 2 + /// a M + /// If you have a range [a, 2] (where 2 came from the macro), the function + /// will return a range for "a M" + /// if you have range [a, 1], the function will fail because the range + /// overlaps with only a part of the macro + /// + /// -The macro is a function macro and the range can be mapped to the macro + /// arguments, e.g: + /// \#define M 1 2 + /// \#define FM(x) x + /// FM(a b M) + /// if you have range [b, 2], the function will return the file range "b M" + /// inside the macro arguments. + /// if you have range [a, 2], the function will return the file range + /// "FM(a b M)" since the range includes all of the macro expansion. static CharSourceRange makeFileCharRange(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts); @@ -519,6 +541,9 @@ public: const LangOptions &LangOpts, bool SkipTrailingWhitespaceAndNewLine); + /// \brief Returns true if the given character could appear in an identifier. + static bool isIdentifierBodyChar(char c, const LangOptions &LangOpts); + private: /// getCharAndSizeSlowNoWarn - Same as getCharAndSizeSlow, but never emits a diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index 7e7f82f..bbce62d 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -232,6 +232,7 @@ private: void init(const Token *StringToks, unsigned NumStringToks); bool CopyStringFragment(StringRef Fragment); bool DiagnoseBadString(const Token& Tok); + void DiagnoseLexingError(SourceLocation Loc); }; } // end namespace clang diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index 8775d39..cbd201f 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -22,7 +22,7 @@ namespace clang { class Preprocessor; -/// MacroInfo - Each identifier that is #define'd has an instance of this class +/// MacroInfo - Each identifier that is \#define'd has an instance of this class /// associated with it, used to implement macro expansion. class MacroInfo { //===--------------------------------------------------------------------===// @@ -35,7 +35,7 @@ class MacroInfo { /// Arguments - The list of arguments for a function-like macro. This can be /// empty, for, e.g. "#define X()". In a C99-style variadic macro, this - /// includes the __VA_ARGS__ identifier on the list. + /// includes the \c __VA_ARGS__ identifier on the list. IdentifierInfo **ArgumentList; unsigned NumArguments; @@ -45,15 +45,14 @@ class MacroInfo { /// If invalid, this macro has not been explicitly given any visibility. SourceLocation VisibilityLocation; - /// ReplacementTokens - This is the list of tokens that the macro is defined - /// to. + /// \brief This is the list of tokens that the macro is defined to. SmallVector<Token, 8> ReplacementTokens; /// \brief Length in characters of the macro definition. mutable unsigned DefinitionLength; mutable bool IsDefinitionLengthCached : 1; - /// IsFunctionLike - True if this macro is a function-like macro, false if it + /// \brief True if this macro is a function-like macro, false if it /// is an object-like macro. bool IsFunctionLike : 1; @@ -71,7 +70,7 @@ class MacroInfo { /// it has not yet been redefined or undefined. bool IsBuiltinMacro : 1; - /// IsFromAST - True if this macro was loaded from an AST file. + /// \brief True if this macro was loaded from an AST file. bool IsFromAST : 1; /// \brief Whether this macro changed after it was loaded from an AST file. @@ -82,8 +81,8 @@ private: // State that changes as the macro is used. /// IsDisabled - True if we have started an expansion of this macro already. - /// This disbles recursive expansion, which would be quite bad for things like - /// #define A A. + /// This disables recursive expansion, which would be quite bad for things + /// like \#define A A. bool IsDisabled : 1; /// IsUsed - True if this macro is either defined in the main file and has diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index 4ebb1d4..fe5abdf 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -126,7 +126,7 @@ public: /// \brief Retrieve a module with the given name. /// - /// \param The name of the module to look up. + /// \param Name The name of the module to look up. /// /// \returns The named module, if known; otherwise, returns null. Module *findModule(StringRef Name); @@ -134,7 +134,7 @@ public: /// \brief Retrieve a module with the given name using lexical name lookup, /// starting at the given context. /// - /// \param The name of the module to look up. + /// \param Name The name of the module to look up. /// /// \param Context The module context, from which we will perform lexical /// name lookup. @@ -145,7 +145,7 @@ public: /// \brief Retrieve a module with the given name within the given context, /// using direct (qualified) name lookup. /// - /// \param The name of the module to look up. + /// \param Name The name of the module to look up. /// /// \param Context The module for which we will look for a submodule. If /// null, we will look for a top-level module. diff --git a/include/clang/Lex/MultipleIncludeOpt.h b/include/clang/Lex/MultipleIncludeOpt.h index 95b00df..a2a5a77 100644 --- a/include/clang/Lex/MultipleIncludeOpt.h +++ b/include/clang/Lex/MultipleIncludeOpt.h @@ -6,8 +6,9 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the MultipleIncludeOpt interface. +/// +/// \file +/// \brief Defines the MultipleIncludeOpt interface. // //===----------------------------------------------------------------------===// @@ -17,17 +18,18 @@ namespace clang { class IdentifierInfo; -/// MultipleIncludeOpt - This class implements the simple state machine that the -/// Lexer class uses to detect files subject to the 'multiple-include' -/// optimization. The public methods in this class are triggered by various +/// \brief Implements the simple state machine that the Lexer class uses to +/// detect files subject to the 'multiple-include' optimization. +/// +/// The public methods in this class are triggered by various /// events that occur when a file is lexed, and after the entire file is lexed, /// information about which macro (if any) controls the header is returned. class MultipleIncludeOpt { /// ReadAnyTokens - This is set to false when a file is first opened and true /// any time a token is returned to the client or a (non-multiple-include) - /// directive is parsed. When the final #endif is parsed this is reset back - /// to false, that way any tokens before the first #ifdef or after the last - /// #endif can be easily detected. + /// directive is parsed. When the final \#endif is parsed this is reset back + /// to false, that way any tokens before the first \#ifdef or after the last + /// \#endif can be easily detected. bool ReadAnyTokens; /// ReadAnyTokens - This is set to false when a file is first opened and true @@ -56,7 +58,7 @@ public: TheMacro = 0; } - /// getHasReadAnyTokensVal - This is used for the #ifndef hande-shake at the + /// getHasReadAnyTokensVal - This is used for the \#ifndef hande-shake at the /// top of the file when reading preprocessor directives. Otherwise, reading /// the "ifndef x" would count as reading tokens. bool getHasReadAnyTokensVal() const { return ReadAnyTokens; } @@ -68,14 +70,13 @@ public: /// buffer, this method is called to disable the MIOpt if needed. void ExpandedMacro() { DidMacroExpansion = true; } - /// EnterTopLevelIFNDEF - When entering a top-level #ifndef directive (or the - /// "#if !defined" equivalent) without any preceding tokens, this method is - /// called. + /// \brief Called when entering a top-level \#ifndef directive (or the + /// "\#if !defined" equivalent) without any preceding tokens. /// /// Note, we don't care about the input value of 'ReadAnyTokens'. The caller /// ensures that this is only called if there are no tokens read before the - /// #ifndef. The caller is required to do this, because reading the #if line - /// obviously reads in in tokens. + /// \#ifndef. The caller is required to do this, because reading the \#if + /// line obviously reads in in tokens. void EnterTopLevelIFNDEF(const IdentifierInfo *M) { // If the macro is already set, this is after the top-level #endif. if (TheMacro) @@ -93,16 +94,14 @@ public: TheMacro = M; } - /// EnterTopLevelConditional - This is invoked when a top level conditional - /// (except #ifndef) is found. + /// \brief Invoked when a top level conditional (except \#ifndef) is found. void EnterTopLevelConditional() { - /// If a conditional directive (except #ifndef) is found at the top level, - /// there is a chunk of the file not guarded by the controlling macro. + // If a conditional directive (except #ifndef) is found at the top level, + // there is a chunk of the file not guarded by the controlling macro. Invalidate(); } - /// ExitTopLevelConditional - This method is called when the lexer exits the - /// top-level conditional. + /// \brief Called when the lexer exits the top-level conditional. void ExitTopLevelConditional() { // If we have a macro, that means the top of the file was ok. Set our state // back to "not having read any tokens" so we can detect anything after the @@ -114,8 +113,8 @@ public: ReadAnyTokens = false; } - /// GetControllingMacroAtEndOfFile - Once the entire file has been lexed, if - /// there is a controlling macro, return it. + /// \brief Once the entire file has been lexed, if there is a controlling + /// macro, return it. const IdentifierInfo *GetControllingMacroAtEndOfFile() const { // If we haven't read any tokens after the #endif, return the controlling // macro if it's valid (if it isn't, it will be null). diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h index 33558c8..962b4df 100644 --- a/include/clang/Lex/PPCallbacks.h +++ b/include/clang/Lex/PPCallbacks.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the PPCallbacks interface. -// +/// +/// \file +/// \brief Defines the PPCallbacks interface. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_LEX_PPCALLBACKS_H @@ -26,9 +27,10 @@ namespace clang { class IdentifierInfo; class MacroInfo; -/// PPCallbacks - This interface provides a way to observe the actions of the -/// preprocessor as it does its thing. Clients can define their hooks here to -/// implement preprocessor level tools. +/// \brief This interface provides a way to observe the actions of the +/// preprocessor as it does its thing. +/// +/// Clients can define their hooks here to implement preprocessor level tools. class PPCallbacks { public: virtual ~PPCallbacks(); @@ -37,29 +39,29 @@ public: EnterFile, ExitFile, SystemHeaderPragma, RenameFile }; - /// FileChanged - This callback is invoked whenever a source file is - /// entered or exited. The SourceLocation indicates the new location, and - /// EnteringFile indicates whether this is because we are entering a new - /// #include'd file (when true) or whether we're exiting one because we ran - /// off the end (when false). + /// \brief Callback invoked whenever a source file is entered or exited. /// - /// \param PrevFID the file that was exited if \arg Reason is ExitFile. + /// \param Loc Indicates the new location. + /// \param PrevFID the file that was exited if \p Reason is ExitFile. virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType, FileID PrevFID = FileID()) { } - /// FileSkipped - This callback is invoked whenever a source file is - /// skipped as the result of header guard optimization. ParentFile - /// is the file that #includes the skipped file. FilenameTok is the - /// token in ParentFile that indicates the skipped file. + /// \brief Callback invoked whenever a source file is skipped as the result + /// of header guard optimization. + /// + /// \param ParentFile The file that \#included the skipped file. + /// + /// \param FilenameTok The token in ParentFile that indicates the + /// skipped file. virtual void FileSkipped(const FileEntry &ParentFile, const Token &FilenameTok, SrcMgr::CharacteristicKind FileType) { } - /// FileNotFound - This callback is invoked whenever an inclusion directive - /// results in a file-not-found error. + /// \brief Callback invoked whenever an inclusion directive results in a + /// file-not-found error. /// /// \param FileName The name of the file being included, as written in the /// source code. @@ -75,8 +77,8 @@ public: return false; } - /// \brief This callback is invoked whenever an inclusion directive of - /// any kind (\c #include, \c #import, etc.) has been processed, regardless + /// \brief Callback invoked whenever an inclusion directive of + /// any kind (\c \#include, \c \#import, etc.) has been processed, regardless /// of whether the inclusion will actually result in an inclusion. /// /// \param HashLoc The location of the '#' that starts the inclusion @@ -118,119 +120,116 @@ public: StringRef RelativePath) { } - /// EndOfMainFile - This callback is invoked when the end of the main file is - /// reach, no subsequent callbacks will be made. + /// \brief Callback invoked when the end of the main file is reached. + /// + /// No subsequent callbacks will be made. virtual void EndOfMainFile() { } - /// Ident - This callback is invoked when a #ident or #sccs directive is read. + /// \brief Callback invoked when a \#ident or \#sccs directive is read. /// \param Loc The location of the directive. /// \param str The text of the directive. /// virtual void Ident(SourceLocation Loc, const std::string &str) { } - /// PragmaComment - This callback is invoked when a #pragma comment directive - /// is read. - /// + /// \brief Callback invoked when a \#pragma comment directive is read. virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, const std::string &Str) { } - /// PragmaMessage - This callback is invoked when a #pragma message directive - /// is read. + /// \brief Callback invoked when a \#pragma message directive is read. /// \param Loc The location of the message directive. - /// \param str The text of the message directive. - /// + /// \param Str The text of the message directive. virtual void PragmaMessage(SourceLocation Loc, StringRef Str) { } - /// PragmaDiagnosticPush - This callback is invoked when a - /// #pragma gcc dianostic push directive is read. + /// \brief Callback invoked when a \#pragma gcc dianostic push directive + /// is read. virtual void PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) { } - /// PragmaDiagnosticPop - This callback is invoked when a - /// #pragma gcc dianostic pop directive is read. + /// \brief Callback invoked when a \#pragma gcc dianostic pop directive + /// is read. virtual void PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) { } - /// PragmaDiagnostic - This callback is invoked when a - /// #pragma gcc dianostic directive is read. + /// \brief Callback invoked when a \#pragma gcc dianostic directive is read. virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, diag::Mapping mapping, StringRef Str) { } - /// MacroExpands - This is called by - /// Preprocessor::HandleMacroExpandedIdentifier when a macro invocation is - /// found. + /// \brief Called by Preprocessor::HandleMacroExpandedIdentifier when a + /// macro invocation is found. virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI, SourceRange Range) { } - /// MacroDefined - This hook is called whenever a macro definition is seen. + /// \brief Hook called whenever a macro definition is seen. virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) { } - /// MacroUndefined - This hook is called whenever a macro #undef is seen. + /// \brief Hook called whenever a macro \#undef is seen. + /// /// MI is released immediately following this callback. virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) { } - /// Defined - This hook is called whenever the 'defined' operator is seen. + /// \brief Hook called whenever the 'defined' operator is seen. virtual void Defined(const Token &MacroNameTok) { } - /// SourceRangeSkipped - This hook is called when a source range is skipped. + /// \brief Hook called when a source range is skipped. /// \param Range The SourceRange that was skipped. The range begins at the - /// #if/#else directive and ends after the #endif/#else directive. + /// \#if/\#else directive and ends after the \#endif/\#else directive. virtual void SourceRangeSkipped(SourceRange Range) { } - /// If -- This hook is called whenever an #if is seen. + /// \brief Hook called whenever an \#if is seen. /// \param Loc the source location of the directive. /// \param ConditionRange The SourceRange of the expression being tested. + /// // FIXME: better to pass in a list (or tree!) of Tokens. virtual void If(SourceLocation Loc, SourceRange ConditionRange) { } - /// Elif -- This hook is called whenever an #elif is seen. + /// \brief Hook called whenever an \#elif is seen. /// \param Loc the source location of the directive. /// \param ConditionRange The SourceRange of the expression being tested. - /// \param IfLoc the source location of the #if/#ifdef/#ifndef directive. + /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive. // FIXME: better to pass in a list (or tree!) of Tokens. virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, SourceLocation IfLoc) { } - /// Ifdef -- This hook is called whenever an #ifdef is seen. + /// \brief Hook called whenever an \#ifdef is seen. /// \param Loc the source location of the directive. - /// \param II Information on the token being tested. + /// \param MacroNameTok Information on the token being tested. virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok) { } - /// Ifndef -- This hook is called whenever an #ifndef is seen. + /// \brief Hook called whenever an \#ifndef is seen. /// \param Loc the source location of the directive. - /// \param II Information on the token being tested. + /// \param MacroNameTok Information on the token being tested. virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok) { } - /// Else -- This hook is called whenever an #else is seen. + /// \brief Hook called whenever an \#else is seen. /// \param Loc the source location of the directive. - /// \param IfLoc the source location of the #if/#ifdef/#ifndef directive. + /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive. virtual void Else(SourceLocation Loc, SourceLocation IfLoc) { } - /// Endif -- This hook is called whenever an #endif is seen. + /// \brief Hook called whenever an \#endif is seen. /// \param Loc the source location of the directive. - /// \param IfLoc the source location of the #if/#ifdef/#ifndef directive. + /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive. virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) { } }; -/// PPChainedCallbacks - Simple wrapper class for chaining callbacks. +/// \brief Simple wrapper class for chaining callbacks. class PPChainedCallbacks : public PPCallbacks { virtual void anchor(); PPCallbacks *First, *Second; @@ -342,38 +341,38 @@ public: Second->SourceRangeSkipped(Range); } - /// If -- This hook is called whenever an #if is seen. + /// \brief Hook called whenever an \#if is seen. virtual void If(SourceLocation Loc, SourceRange ConditionRange) { First->If(Loc, ConditionRange); Second->If(Loc, ConditionRange); } - /// Elif -- This hook is called whenever an #if is seen. + /// \brief Hook called whenever an \#if is seen. virtual void Elif(SourceLocation Loc, SourceRange ConditionRange, SourceLocation IfLoc) { First->Elif(Loc, ConditionRange, IfLoc); Second->Elif(Loc, ConditionRange, IfLoc); } - /// Ifdef -- This hook is called whenever an #ifdef is seen. + /// \brief Hook called whenever an \#ifdef is seen. virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok) { First->Ifdef(Loc, MacroNameTok); Second->Ifdef(Loc, MacroNameTok); } - /// Ifndef -- This hook is called whenever an #ifndef is seen. + /// \brief Hook called whenever an \#ifndef is seen. virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok) { First->Ifndef(Loc, MacroNameTok); Second->Ifndef(Loc, MacroNameTok); } - /// Else -- This hook is called whenever an #else is seen. + /// \brief Hook called whenever an \#else is seen. virtual void Else(SourceLocation Loc, SourceLocation IfLoc) { First->Else(Loc, IfLoc); Second->Else(Loc, IfLoc); } - /// Endif -- This hook is called whenever an #endif is seen. + /// \brief Hook called whenever an \#endif is seen. virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) { First->Endif(Loc, IfLoc); Second->Endif(Loc, IfLoc); diff --git a/include/clang/Lex/Pragma.h b/include/clang/Lex/Pragma.h index 4868811..087448f 100644 --- a/include/clang/Lex/Pragma.h +++ b/include/clang/Lex/Pragma.h @@ -26,12 +26,12 @@ namespace clang { class PragmaNamespace; /** - * \brief Describes how the pragma was introduced, e.g., with #pragma, + * \brief Describes how the pragma was introduced, e.g., with \#pragma, * _Pragma, or __pragma. */ enum PragmaIntroducerKind { /** - * \brief The pragma was introduced via #pragma. + * \brief The pragma was introduced via \#pragma. */ PIK_HashPragma, @@ -54,7 +54,7 @@ namespace clang { /// pragmas the handler with a null identifier is invoked, if it exists. /// /// Note that the PragmaNamespace class can be used to subdivide pragmas, e.g. -/// we treat "#pragma STDC" and "#pragma GCC" as namespaces that contain other +/// we treat "\#pragma STDC" and "\#pragma GCC" as namespaces that contain other /// pragmas. class PragmaHandler { std::string Name; @@ -84,8 +84,8 @@ public: /// PragmaNamespace - This PragmaHandler subdivides the namespace of pragmas, /// allowing hierarchical pragmas to be defined. Common examples of namespaces -/// are "#pragma GCC", "#pragma STDC", and "#pragma omp", but any namespaces may -/// be (potentially recursively) defined. +/// are "\#pragma GCC", "\#pragma STDC", and "\#pragma omp", but any namespaces +/// may be (potentially recursively) defined. class PragmaNamespace : public PragmaHandler { /// Handlers - This is a map of the handlers in this namespace with their name /// as key. diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h index 45e3a5d..fb3e081 100644 --- a/include/clang/Lex/PreprocessingRecord.h +++ b/include/clang/Lex/PreprocessingRecord.h @@ -59,8 +59,8 @@ namespace clang { /// \brief A macro definition. MacroDefinitionKind, - /// \brief An inclusion directive, such as \c #include, \c - /// #import, or \c #include_next. + /// \brief An inclusion directive, such as \c \#include, \c + /// \#import, or \c \#include_next. InclusionDirectiveKind, /// @} @@ -197,19 +197,19 @@ namespace clang { }; /// \brief Record the location of an inclusion directive, such as an - /// \c #include or \c #import statement. + /// \c \#include or \c \#import statement. class InclusionDirective : public PreprocessingDirective { public: /// \brief The kind of inclusion directives known to the /// preprocessor. enum InclusionKind { - /// \brief An \c #include directive. + /// \brief An \c \#include directive. Include, - /// \brief An Objective-C \c #import directive. + /// \brief An Objective-C \c \#import directive. Import, - /// \brief A GNU \c #include_next directive. + /// \brief A GNU \c \#include_next directive. IncludeNext, - /// \brief A Clang \c #__include_macros directive. + /// \brief A Clang \c \#__include_macros directive. IncludeMacros }; @@ -551,7 +551,7 @@ namespace clang { /// /// Can be used to avoid implicit deserializations of preallocated /// preprocessed entities if we only care about entities of a specific file - /// and not from files #included in the range given at + /// and not from files \#included in the range given at /// \see getPreprocessedEntitiesInRange. bool isEntityInFileID(iterator PPEI, FileID FID); @@ -565,7 +565,7 @@ namespace clang { } /// \brief Returns true if the given range intersects with a conditional - /// directive. if a #if/#endif block is fully contained within the range, + /// directive. if a \#if/\#endif block is fully contained within the range, /// this function will return false. bool rangeIntersectsConditionalDirective(SourceRange Range) const; diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 055008f..02e3f1e 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -58,7 +58,7 @@ class ModuleLoader; /// Preprocessor - This object engages in a tight little dance with the lexer to /// efficiently preprocess tokens. Lexers know only about tokens within a /// single source file, and don't know anything about preprocessor-level issues -/// like the #include stack, token expansion, etc. +/// like the \#include stack, token expansion, etc. /// class Preprocessor : public RefCountedBase<Preprocessor> { DiagnosticsEngine *Diags; @@ -103,7 +103,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> { unsigned CounterValue; // Next __COUNTER__ value. enum { - /// MaxIncludeStackDepth - Maximum depth of #includes. + /// MaxIncludeStackDepth - Maximum depth of \#includes. MaxAllowedIncludeStackDepth = 200 }; @@ -121,9 +121,19 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// DisableMacroExpansion - True if macro expansion is disabled. bool DisableMacroExpansion : 1; + /// MacroExpansionInDirectivesOverride - Temporarily disables + /// DisableMacroExpansion (i.e. enables expansion) when parsing preprocessor + /// directives. + bool MacroExpansionInDirectivesOverride : 1; + + class ResetMacroExpansionHelper; + /// \brief Whether we have already loaded macros from the external source. mutable bool ReadMacrosFromExternalSource : 1; + /// \brief True if pragmas are enabled. + bool PragmasEnabled : 1; + /// \brief True if we are pre-expanding macro arguments. bool InMacroArgPreExpansion; @@ -165,11 +175,12 @@ class Preprocessor : public RefCountedBase<Preprocessor> { unsigned CodeCompletionOffset; /// \brief The location for the code-completion point. This gets instantiated - /// when the CodeCompletionFile gets #include'ed for preprocessing. + /// when the CodeCompletionFile gets \#include'ed for preprocessing. SourceLocation CodeCompletionLoc; /// \brief The start location for the file of the code-completion point. - /// This gets instantiated when the CodeCompletionFile gets #include'ed + /// + /// This gets instantiated when the CodeCompletionFile gets \#include'ed /// for preprocessing. SourceLocation CodeCompletionFileLoc; @@ -215,7 +226,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// CurLookup - The DirectoryLookup structure used to find the current /// FileEntry, if CurLexer is non-null and if applicable. This allows us to - /// implement #include_next and find directory-specific properties. + /// implement \#include_next and find directory-specific properties. const DirectoryLookup *CurDirLookup; /// CurTokenLexer - This is the current macro we are expanding, if we are @@ -232,7 +243,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> { } CurLexerKind; /// IncludeMacroStack - This keeps track of the stack of files currently - /// #included, and macros currently being expanded from, not counting + /// \#included, and macros currently being expanded from, not counting /// CurLexer/CurTokenLexer. struct IncludeStackInfo { enum CurLexerKind CurLexerKind; @@ -251,9 +262,18 @@ class Preprocessor : public RefCountedBase<Preprocessor> { std::vector<IncludeStackInfo> IncludeMacroStack; /// Callbacks - These are actions invoked when some preprocessor activity is - /// encountered (e.g. a file is #included, etc). + /// encountered (e.g. a file is \#included, etc). PPCallbacks *Callbacks; + struct MacroExpandsInfo { + Token Tok; + MacroInfo *MI; + SourceRange Range; + MacroExpandsInfo(Token Tok, MacroInfo *MI, SourceRange Range) + : Tok(Tok), MI(MI), Range(Range) { } + }; + SmallVector<MacroExpandsInfo, 2> DelayedMacroExpandsCallbacks; + /// Macros - For each IdentifierInfo with 'HasMacro' set, we keep a mapping /// to the actual definition of the macro. llvm::DenseMap<IdentifierInfo*, MacroInfo*> Macros; @@ -400,6 +420,9 @@ public: bool getCommentRetentionState() const { return KeepComments; } + void setPragmasEnabled(bool Enabled) { PragmasEnabled = Enabled; } + bool getPragmasEnabled() const { return PragmasEnabled; } + void SetSuppressIncludeNotFoundError(bool Suppress) { SuppressIncludeNotFoundError = Suppress; } @@ -434,8 +457,8 @@ public: Callbacks = C; } - /// getMacroInfo - Given an identifier, return the MacroInfo it is #defined to - /// or null if it isn't #define'd. + /// \brief Given an identifier, return the MacroInfo it is \#defined to + /// or null if it isn't \#define'd. MacroInfo *getMacroInfo(IdentifierInfo *II) const { if (!II->hasMacroDefinition()) return 0; @@ -443,8 +466,7 @@ public: return getInfoForMacro(II); } - /// setMacroInfo - Specify a macro for this identifier. - /// + /// \brief Specify a macro for this identifier. void setMacroInfo(IdentifierInfo *II, MacroInfo *MI, bool LoadedFromAST = false); @@ -488,12 +510,12 @@ public: } /// \brief Add the specified comment handler to the preprocessor. - void AddCommentHandler(CommentHandler *Handler); + void addCommentHandler(CommentHandler *Handler); /// \brief Remove the specified comment handler. /// /// It is an error to remove a handler that has not been registered. - void RemoveCommentHandler(CommentHandler *Handler); + void removeCommentHandler(CommentHandler *Handler); /// \brief Set the code completion handler to the given object. void setCodeCompletionHandler(CodeCompletionHandler &Handler) { @@ -634,6 +656,12 @@ public: while (Result.getKind() == tok::comment); } + /// Disables macro expansion everywhere except for preprocessor directives. + void SetMacroExpansionOnlyInDirectives() { + DisableMacroExpansion = true; + MacroExpansionInDirectivesOverride = true; + } + /// LookAhead - This peeks ahead N tokens and returns that token without /// consuming any tokens. LookAhead(0) returns the next token that would be /// returned by Lex(), LookAhead(1) returns the token after it, etc. This @@ -752,25 +780,24 @@ public: getDiagnostics().setSuppressAllDiagnostics(true); } - /// \brief The location of the currently-active #pragma clang + /// \brief The location of the currently-active \#pragma clang /// arc_cf_code_audited begin. Returns an invalid location if there /// is no such pragma active. SourceLocation getPragmaARCCFCodeAuditedLoc() const { return PragmaARCCFCodeAuditedLoc; } - /// \brief Set the location of the currently-active #pragma clang + /// \brief Set the location of the currently-active \#pragma clang /// arc_cf_code_audited begin. An invalid location ends the pragma. void setPragmaARCCFCodeAuditedLoc(SourceLocation Loc) { PragmaARCCFCodeAuditedLoc = Loc; } - /// \brief Instruct the preprocessor to skip part of the main - /// the main source file. + /// \brief Instruct the preprocessor to skip part of the main source file. /// - /// \brief Bytes The number of bytes in the preamble to skip. + /// \param Bytes The number of bytes in the preamble to skip. /// - /// \brief StartOfLine Whether skipping these bytes puts the lexer at the + /// \param StartOfLine Whether skipping these bytes puts the lexer at the /// start of a line. void setSkipMainFilePreamble(unsigned Bytes, bool StartOfLine) { SkipMainFilePreamble.first = Bytes; @@ -1035,24 +1062,27 @@ public: /// \brief Retrieves the module that we're currently building, if any. Module *getCurrentModule(); - /// AllocateMacroInfo - Allocate a new MacroInfo object with the provide - /// SourceLocation. + /// \brief Allocate a new MacroInfo object with the provided SourceLocation. MacroInfo *AllocateMacroInfo(SourceLocation L); - /// CloneMacroInfo - Allocate a new MacroInfo object which is clone of MI. + /// \brief Allocate a new MacroInfo object which is clone of \p MI. MacroInfo *CloneMacroInfo(const MacroInfo &MI); - /// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully - /// checked and spelled filename, e.g. as an operand of #include. This returns - /// true if the input filename was in <>'s or false if it were in ""'s. The - /// caller is expected to provide a buffer that is large enough to hold the - /// spelling of the filename, but is also expected to handle the case when - /// this method decides to use a different buffer. + /// \brief Turn the specified lexer token into a fully checked and spelled + /// filename, e.g. as an operand of \#include. + /// + /// The caller is expected to provide a buffer that is large enough to hold + /// the spelling of the filename, but is also expected to handle the case + /// when this method decides to use a different buffer. + /// + /// \returns true if the input filename was in <>'s or false if it was + /// in ""'s. bool GetIncludeFilenameSpelling(SourceLocation Loc,StringRef &Filename); - /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file, - /// return null on failure. isAngled indicates whether the file reference is - /// for system #include's or not (i.e. using <> instead of ""). + /// \brief Given a "foo" or \<foo> reference, look up the indicated file. + /// + /// Returns null on failure. \p isAngled indicates whether the file + /// reference is for system \#include's or not (i.e. using <> instead of ""). const FileEntry *LookupFile(StringRef Filename, bool isAngled, const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir, @@ -1063,18 +1093,19 @@ public: /// GetCurLookup - The DirectoryLookup structure used to find the current /// FileEntry, if CurLexer is non-null and if applicable. This allows us to - /// implement #include_next and find directory-specific properties. + /// implement \#include_next and find directory-specific properties. const DirectoryLookup *GetCurDirLookup() { return CurDirLookup; } - /// isInPrimaryFile - Return true if we're in the top-level file, not in a - /// #include. + /// \brief Return true if we're in the top-level file, not in a \#include. bool isInPrimaryFile() const; - /// ConcatenateIncludeName - Handle cases where the #include name is expanded + /// ConcatenateIncludeName - Handle cases where the \#include name is expanded /// from a macro as multiple tokens, which need to be glued together. This /// occurs for code like: - /// #define FOO <a/b.h> - /// #include FOO + /// \code + /// \#define FOO <a/b.h> + /// \#include FOO + /// \endcode /// because in this case, "<a/b.h>" is returned as 7 tokens, not one. /// /// This code concatenates and consumes tokens up to the '>' token. It @@ -1109,15 +1140,16 @@ private: IncludeMacroStack.pop_back(); } - /// AllocateMacroInfo - Allocate a new MacroInfo object. + /// \brief Allocate a new MacroInfo object. MacroInfo *AllocateMacroInfo(); - /// ReleaseMacroInfo - Release the specified MacroInfo. This memory will - /// be reused for allocating new MacroInfo objects. + /// \brief Release the specified MacroInfo for re-use. + /// + /// This memory will be reused for allocating new MacroInfo objects. void ReleaseMacroInfo(MacroInfo* MI); /// ReadMacroName - Lex and validate a macro name, which occurs after a - /// #define or #undef. This emits a diagnostic, sets the token kind to eod, + /// \#define or \#undef. This emits a diagnostic, sets the token kind to eod, /// and discards the rest of the macro line if the macro name is invalid. void ReadMacroName(Token &MacroNameTok, char isDefineUndef = 0); @@ -1128,20 +1160,19 @@ private: /// Return true if an error occurs parsing the arg list. bool ReadMacroDefinitionArgList(MacroInfo *MI, Token& LastTok); - /// SkipExcludedConditionalBlock - We just read a #if or related directive and - /// decided that the subsequent tokens are in the #if'd out portion of the - /// file. Lex the rest of the file, until we see an #endif. If + /// We just read a \#if or related directive and decided that the + /// subsequent tokens are in the \#if'd out portion of the + /// file. Lex the rest of the file, until we see an \#endif. If \p /// FoundNonSkipPortion is true, then we have already emitted code for part of - /// this #if directive, so #else/#elif blocks should never be entered. If - /// FoundElse is false, then #else directives are ok, if not, then we have - /// already seen one so a #else directive is a duplicate. When this returns, + /// this \#if directive, so \#else/\#elif blocks should never be entered. If + /// \p FoundElse is false, then \#else directives are ok, if not, then we have + /// already seen one so a \#else directive is a duplicate. When this returns, /// the caller can lex the first valid token. void SkipExcludedConditionalBlock(SourceLocation IfTokenLoc, bool FoundNonSkipPortion, bool FoundElse, SourceLocation ElseLoc = SourceLocation()); - /// PTHSkipExcludedConditionalBlock - A fast PTH version of - /// SkipExcludedConditionalBlock. + /// \brief A fast PTH version of SkipExcludedConditionalBlock. void PTHSkipExcludedConditionalBlock(); /// EvaluateDirectiveExpression - Evaluate an integer constant expression that @@ -1150,11 +1181,10 @@ private: bool EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro); /// RegisterBuiltinPragmas - Install the standard preprocessor pragmas: - /// #pragma GCC poison/system_header/dependency and #pragma once. + /// \#pragma GCC poison/system_header/dependency and \#pragma once. void RegisterBuiltinPragmas(); - /// RegisterBuiltinMacros - Register builtin macros, such as __LINE__ with the - /// identifier table. + /// \brief Register builtin macros such as __LINE__ with the identifier table. void RegisterBuiltinMacros(); /// HandleMacroExpandedIdentifier - If an identifier token is read that is to diff --git a/include/clang/Lex/PreprocessorLexer.h b/include/clang/Lex/PreprocessorLexer.h index b551cd4..8a0b3cf 100644 --- a/include/clang/Lex/PreprocessorLexer.h +++ b/include/clang/Lex/PreprocessorLexer.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the PreprocessorLexer interface. -// +/// +/// \file +/// \brief Defines the PreprocessorLexer interface. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_PreprocessorLexer_H @@ -38,16 +39,17 @@ protected: // Context-specific lexing flags set by the preprocessor. //===--------------------------------------------------------------------===// - /// ParsingPreprocessorDirective - This is true when parsing #XXX. This turns - /// '\n' into a tok::eod token. + /// \brief True when parsing \#XXX; turns '\\n' into a tok::eod token. bool ParsingPreprocessorDirective; - /// ParsingFilename - True after #include: this turns <xx> into a - /// tok::angle_string_literal token. + /// \brief True after \#include; turns \<xx> into a tok::angle_string_literal + /// token. bool ParsingFilename; - /// LexingRawMode - True if in raw mode: This flag disables interpretation of - /// tokens and is a far faster mode to lex in than non-raw-mode. This flag: + /// \brief True if in raw mode. + /// + /// Raw mode disables interpretation of tokens and is a far faster mode to + /// lex in than non-raw-mode. This flag: /// 1. If EOF of the current lexer is found, the include stack isn't popped. /// 2. Identifier information is not looked up for identifier tokens. As an /// effect of this, implicit macro expansion is naturally disabled. @@ -59,11 +61,11 @@ protected: /// Note that in raw mode that the PP pointer may be null. bool LexingRawMode; - /// MIOpt - This is a state machine that detects the #ifndef-wrapping a file + /// \brief A state machine that detects the \#ifndef-wrapping a file /// idiom for the multiple-include optimization. MultipleIncludeOpt MIOpt; - /// ConditionalStack - Information about the set of #if/#ifdef/#ifndef blocks + /// \brief Information about the set of \#if/\#ifdef/\#ifndef blocks /// we are currently in. SmallVector<PPConditionalInfo, 4> ConditionalStack; @@ -83,16 +85,15 @@ protected: virtual void IndirectLex(Token& Result) = 0; - /// getSourceLocation - Return the source location for the next observable - /// location. + /// \brief Return the source location for the next observable location. virtual SourceLocation getSourceLocation() = 0; //===--------------------------------------------------------------------===// // #if directive handling. - /// pushConditionalLevel - When we enter a #if directive, this keeps track of - /// what we are currently in for diagnostic emission (e.g. #if with missing - /// #endif). + /// pushConditionalLevel - When we enter a \#if directive, this keeps track of + /// what we are currently in for diagnostic emission (e.g. \#if with missing + /// \#endif). void pushConditionalLevel(SourceLocation DirectiveStart, bool WasSkipping, bool FoundNonSkip, bool FoundElse) { PPConditionalInfo CI; @@ -116,8 +117,8 @@ protected: return false; } - /// peekConditionalLevel - Return the top of the conditional stack. This - /// requires that there be a conditional active. + /// \brief Return the top of the conditional stack. + /// \pre This requires that there be a conditional active. PPConditionalInfo &peekConditionalLevel() { assert(!ConditionalStack.empty() && "No conditionals active!"); return ConditionalStack.back(); @@ -130,21 +131,23 @@ public: //===--------------------------------------------------------------------===// // Misc. lexing methods. - /// LexIncludeFilename - After the preprocessor has parsed a #include, lex and - /// (potentially) macro expand the filename. If the sequence parsed is not - /// lexically legal, emit a diagnostic and return a result EOD token. + /// \brief After the preprocessor has parsed a \#include, lex and + /// (potentially) macro expand the filename. + /// + /// If the sequence parsed is not lexically legal, emit a diagnostic and + /// return a result EOD token. void LexIncludeFilename(Token &Result); - /// setParsingPreprocessorDirective - Inform the lexer whether or not - /// we are currently lexing a preprocessor directive. + /// \brief Inform the lexer whether or not we are currently lexing a + /// preprocessor directive. void setParsingPreprocessorDirective(bool f) { ParsingPreprocessorDirective = f; } - /// isLexingRawMode - Return true if this lexer is in raw mode or not. + /// \brief Return true if this lexer is in raw mode or not. bool isLexingRawMode() const { return LexingRawMode; } - /// getPP - Return the preprocessor object for this lexer. + /// \brief Return the preprocessor object for this lexer. Preprocessor *getPP() const { return PP; } FileID getFileID() const { @@ -163,7 +166,7 @@ public: const FileEntry *getFileEntry() const; /// \brief Iterator that traverses the current stack of preprocessor - /// conditional directives (#if/#ifdef/#ifndef). + /// conditional directives (\#if/\#ifdef/\#ifndef). typedef SmallVectorImpl<PPConditionalInfo>::const_iterator conditional_iterator; diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h index a88f607..9c5a023 100644 --- a/include/clang/Lex/Token.h +++ b/include/clang/Lex/Token.h @@ -87,7 +87,7 @@ public: bool is(tok::TokenKind K) const { return Kind == (unsigned) K; } bool isNot(tok::TokenKind K) const { return Kind != (unsigned) K; } - /// isAnyIdentifier - Return true if this is a raw identifier (when lexing + /// \brief Return true if this is a raw identifier (when lexing /// in raw mode) or a non-keyword identifier (when lexing in non-raw mode). bool isAnyIdentifier() const { return is(tok::identifier) || is(tok::raw_identifier); @@ -112,7 +112,7 @@ public: return false; } - /// getLocation - Return a source location identifier for the specified + /// \brief Return a source location identifier for the specified /// offset in the current file. SourceLocation getLocation() const { return Loc; } unsigned getLength() const { @@ -139,8 +139,8 @@ public: return isAnnotation() ? getAnnotationEndLoc() : getLocation(); } - /// getAnnotationRange - SourceRange of the group of tokens that this - /// annotation token represents. + /// \brief SourceRange of the group of tokens that this annotation token + /// represents. SourceRange getAnnotationRange() const { return SourceRange(getLocation(), getAnnotationEndLoc()); } @@ -153,8 +153,7 @@ public: return tok::getTokenName( (tok::TokenKind) Kind); } - /// startToken - Reset all flags to cleared. - /// + /// \brief Reset all flags to cleared. void startToken() { Kind = tok::unknown; Flags = 0; @@ -208,24 +207,25 @@ public: PtrData = val; } - /// setFlag - Set the specified flag. + /// \brief Set the specified flag. void setFlag(TokenFlags Flag) { Flags |= Flag; } - /// clearFlag - Unset the specified flag. + /// \brief Unset the specified flag. void clearFlag(TokenFlags Flag) { Flags &= ~Flag; } - /// getFlags - Return the internal represtation of the flags. - /// Only intended for low-level operations such as writing tokens to - // disk. + /// \brief Return the internal represtation of the flags. + /// + /// This is only intended for low-level operations such as writing tokens to + /// disk. unsigned getFlags() const { return Flags; } - /// setFlagValue - Set a flag to either true or false. + /// \brief Set a flag to either true or false. void setFlagValue(TokenFlags Flag, bool Val) { if (Val) setFlag(Flag); @@ -237,25 +237,23 @@ public: /// bool isAtStartOfLine() const { return (Flags & StartOfLine) ? true : false; } - /// hasLeadingSpace - Return true if this token has whitespace before it. + /// \brief Return true if this token has whitespace before it. /// bool hasLeadingSpace() const { return (Flags & LeadingSpace) ? true : false; } - /// isExpandDisabled - Return true if this identifier token should never + /// \brief Return true if this identifier token should never /// be expanded in the future, due to C99 6.10.3.4p2. bool isExpandDisabled() const { return (Flags & DisableExpand) ? true : false; } - /// isObjCAtKeyword - Return true if we have an ObjC keyword identifier. + /// \brief Return true if we have an ObjC keyword identifier. bool isObjCAtKeyword(tok::ObjCKeywordKind objcKey) const; - /// getObjCKeywordID - Return the ObjC keyword kind. + /// \brief Return the ObjC keyword kind. tok::ObjCKeywordKind getObjCKeywordID() const; - /// needsCleaning - Return true if this token has trigraphs or escaped - /// newlines in it. - /// + /// \brief Return true if this token has trigraphs or escaped newlines in it. bool needsCleaning() const { return (Flags & NeedsCleaning) ? true : false; } /// \brief Return true if this token has an empty macro before it. @@ -269,23 +267,22 @@ public: bool hasUDSuffix() const { return (Flags & HasUDSuffix) ? true : false; } }; -/// PPConditionalInfo - Information about the conditional stack (#if directives) +/// \brief Information about the conditional stack (\#if directives) /// currently active. struct PPConditionalInfo { - /// IfLoc - Location where the conditional started. - /// + /// \brief Location where the conditional started. SourceLocation IfLoc; - /// WasSkipping - True if this was contained in a skipping directive, e.g. - /// in a "#if 0" block. + /// \brief True if this was contained in a skipping directive, e.g., + /// in a "\#if 0" block. bool WasSkipping; - /// FoundNonSkip - True if we have emitted tokens already, and now we're in - /// an #else block or something. Only useful in Skipping blocks. + /// \brief True if we have emitted tokens already, and now we're in + /// an \#else block or something. Only useful in Skipping blocks. bool FoundNonSkip; - /// FoundElse - True if we've seen a #else in this block. If so, - /// #elif/#else directives are not allowed. + /// \brief True if we've seen a \#else in this block. If so, + /// \#elif/\#else directives are not allowed. bool FoundElse; }; diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 0ae5dc8..353b59e 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -23,14 +23,20 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/SaveAndRestore.h" #include <stack> namespace clang { class PragmaHandler; class Scope; + class BalancedDelimiterTracker; class DeclGroupRef; class DiagnosticBuilder; class Parser; + class ParsingDeclRAIIObject; + class ParsingDeclSpec; + class ParsingDeclarator; + class ParsingFieldDeclarator; class PragmaUnusedHandler; class ColonProtectionRAIIObject; class InMessageExpressionRAIIObject; @@ -79,7 +85,9 @@ class Parser : public CodeCompletionHandler { friend class ColonProtectionRAIIObject; friend class InMessageExpressionRAIIObject; friend class PoisonSEHIdentifiersRAIIObject; + friend class ObjCDeclContextSwitch; friend class ParenBraceBracketBalancer; + friend class BalancedDelimiterTracker; Preprocessor &PP; @@ -94,7 +102,7 @@ class Parser : public CodeCompletionHandler { SourceLocation PrevTokLocation; unsigned short ParenCount, BracketCount, BraceCount; - + /// Actions - These are the callbacks we invoke as we parse various constructs /// in the file. Sema &Actions; @@ -165,6 +173,7 @@ class Parser : public CodeCompletionHandler { OwningPtr<PragmaHandler> RedefineExtnameHandler; OwningPtr<PragmaHandler> FPContractHandler; OwningPtr<PragmaHandler> OpenCLExtensionHandler; + OwningPtr<CommentHandler> CommentSemaHandler; /// Whether the '>' token acts as an operator or not. This will be /// true except when we are parsing an expression within a C++ @@ -197,6 +206,13 @@ class Parser : public CodeCompletionHandler { IdentifierInfo *getSEHExceptKeyword(); + /// True if we are within an Objective-C container while parsing C-like decls. + /// + /// This is necessary because Sema thinks we have left the container + /// to parse the C-like decls, meaning Actions.getObjCDeclContext() will + /// be NULL. + bool ParsingInObjCContainer; + bool SkipFunctionBodies; public: @@ -207,6 +223,7 @@ public: const TargetInfo &getTargetInfo() const { return PP.getTargetInfo(); } Preprocessor &getPreprocessor() const { return PP; } Sema &getActions() const { return Actions; } + AttributeFactory &getAttrFactory() { return AttrFactory; } const Token &getCurToken() const { return Tok; } Scope *getCurScope() const { return Actions.getCurScope(); } @@ -434,78 +451,6 @@ private: return PP.LookAhead(0); } - /// \brief RAII class that helps handle the parsing of an open/close delimiter - /// pair, such as braces { ... } or parentheses ( ... ). - class BalancedDelimiterTracker { - Parser& P; - tok::TokenKind Kind, Close; - SourceLocation (Parser::*Consumer)(); - SourceLocation LOpen, LClose; - - unsigned short &getDepth() { - switch (Kind) { - case tok::l_brace: return P.BraceCount; - case tok::l_square: return P.BracketCount; - case tok::l_paren: return P.ParenCount; - default: llvm_unreachable("Wrong token kind"); - } - } - - enum { MaxDepth = 256 }; - - bool diagnoseOverflow(); - bool diagnoseMissingClose(); - - public: - BalancedDelimiterTracker(Parser& p, tok::TokenKind k) : P(p), Kind(k) { - switch (Kind) { - default: llvm_unreachable("Unexpected balanced token"); - case tok::l_brace: - Close = tok::r_brace; - Consumer = &Parser::ConsumeBrace; - break; - case tok::l_paren: - Close = tok::r_paren; - Consumer = &Parser::ConsumeParen; - break; - - case tok::l_square: - Close = tok::r_square; - Consumer = &Parser::ConsumeBracket; - break; - } - } - - SourceLocation getOpenLocation() const { return LOpen; } - SourceLocation getCloseLocation() const { return LClose; } - SourceRange getRange() const { return SourceRange(LOpen, LClose); } - - bool consumeOpen() { - if (!P.Tok.is(Kind)) - return true; - - if (getDepth() < MaxDepth) { - LOpen = (P.*Consumer)(); - return false; - } - - return diagnoseOverflow(); - } - - bool expectAndConsume(unsigned DiagID, - const char *Msg = "", - tok::TokenKind SkipToTok = tok::unknown); - bool consumeClose() { - if (P.Tok.is(Close)) { - LClose = (P.*Consumer)(); - return false; - } - - return diagnoseMissingClose(); - } - void skipToEnd(); - }; - /// getTypeAnnotation - Read a parsed type out of an annotation token. static ParsedType getTypeAnnotation(Token &Tok) { return ParsedType::getFromOpaquePtr(Tok.getAnnotationValue()); @@ -621,9 +566,11 @@ private: class ObjCDeclContextSwitch { Parser &P; Decl *DC; + SaveAndRestore<bool> WithinObjCContainer; public: - explicit ObjCDeclContextSwitch(Parser &p) : P(p), - DC(p.getObjCDeclContext()) { + explicit ObjCDeclContextSwitch(Parser &p) + : P(p), DC(p.getObjCDeclContext()), + WithinObjCContainer(P.ParsingInObjCContainer, DC != 0) { if (DC) P.Actions.ActOnObjCTemporaryExitContainerContext(cast<DeclContext>(DC)); } @@ -650,6 +597,17 @@ private: /// to the semicolon, consumes that extra token. bool ExpectAndConsumeSemi(unsigned DiagID); + /// \brief The kind of extra semi diagnostic to emit. + enum ExtraSemiKind { + OutsideFunction = 0, + InsideStruct = 1, + InstanceVariableList = 2, + AfterMemberFunctionDefinition = 3 + }; + + /// \brief Consume any extra semi-colons until the end of the line. + void ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST = TST_unspecified); + //===--------------------------------------------------------------------===// // Scope manipulation @@ -715,6 +673,9 @@ private: public: DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID); DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID); + DiagnosticBuilder Diag(unsigned DiagID) { + return Diag(Tok, DiagID); + } private: void SuggestParentheses(SourceLocation Loc, unsigned DK, @@ -951,120 +912,7 @@ private: return *ClassStack.top(); } - /// \brief RAII object used to inform the actions that we're - /// currently parsing a declaration. This is active when parsing a - /// variable's initializer, but not when parsing the body of a - /// class or function definition. - class ParsingDeclRAIIObject { - Sema &Actions; - Sema::ParsingDeclState State; - bool Popped; - - public: - ParsingDeclRAIIObject(Parser &P) : Actions(P.Actions) { - push(); - } - - ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *Other) - : Actions(P.Actions) { - if (Other) steal(*Other); - else push(); - } - - /// Creates a RAII object which steals the state from a different - /// object instead of pushing. - ParsingDeclRAIIObject(ParsingDeclRAIIObject &Other) - : Actions(Other.Actions) { - steal(Other); - } - - ~ParsingDeclRAIIObject() { - abort(); - } - - /// Resets the RAII object for a new declaration. - void reset() { - abort(); - push(); - } - - /// Signals that the context was completed without an appropriate - /// declaration being parsed. - void abort() { - pop(0); - } - - void complete(Decl *D) { - assert(!Popped && "ParsingDeclaration has already been popped!"); - pop(D); - } - - private: - void steal(ParsingDeclRAIIObject &Other) { - State = Other.State; - Popped = Other.Popped; - Other.Popped = true; - } - - void push() { - State = Actions.PushParsingDeclaration(); - Popped = false; - } - - void pop(Decl *D) { - if (!Popped) { - Actions.PopParsingDeclaration(State, D); - Popped = true; - } - } - }; - - /// A class for parsing a DeclSpec. - class ParsingDeclSpec : public DeclSpec { - ParsingDeclRAIIObject ParsingRAII; - - public: - ParsingDeclSpec(Parser &P) : DeclSpec(P.AttrFactory), ParsingRAII(P) {} - ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII) - : DeclSpec(P.AttrFactory), ParsingRAII(P, RAII) {} - - void complete(Decl *D) { - ParsingRAII.complete(D); - } - - void abort() { - ParsingRAII.abort(); - } - }; - - /// A class for parsing a declarator. - class ParsingDeclarator : public Declarator { - ParsingDeclRAIIObject ParsingRAII; - - public: - ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C) - : Declarator(DS, C), ParsingRAII(P) { - } - - const ParsingDeclSpec &getDeclSpec() const { - return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec()); - } - - ParsingDeclSpec &getMutableDeclSpec() const { - return const_cast<ParsingDeclSpec&>(getDeclSpec()); - } - - void clear() { - Declarator::clear(); - ParsingRAII.reset(); - } - - void complete(Decl *D) { - ParsingRAII.complete(D); - } - }; - - /// \brief RAII object used to + /// \brief RAII object used to manage the parsing of a class definition. class ParsingClassDefinition { Parser &P; bool Popped; @@ -1183,7 +1031,7 @@ private: void ParseLexedMethodDef(LexedMethod &LM); void ParseLexedMemberInitializers(ParsingClass &Class); void ParseLexedMemberInitializer(LateParsedMemberInitializer &MI); - Decl *ParseLexedObjCMethodDefs(LexedMethod &LM); + void ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod); bool ConsumeAndStoreFunctionPrologue(CachedTokens &Toks); bool ConsumeAndStoreUntil(tok::TokenKind T1, CachedTokens &Toks, @@ -1209,10 +1057,13 @@ private: ParsingDeclSpec *DS = 0); bool isDeclarationAfterDeclarator(); bool isStartOfFunctionDefinition(const ParsingDeclarator &Declarator); - DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs, - AccessSpecifier AS = AS_none); - DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS, + DeclGroupPtrTy ParseDeclarationOrFunctionDefinition( + ParsedAttributesWithRange &attrs, + ParsingDeclSpec *DS = 0, AccessSpecifier AS = AS_none); + DeclGroupPtrTy ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs, + ParsingDeclSpec &DS, + AccessSpecifier AS); Decl *ParseFunctionDefinition(ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), @@ -1245,11 +1096,12 @@ private: struct ObjCImplParsingDataRAII { Parser &P; Decl *Dcl; + bool HasCFunction; typedef SmallVector<LexedMethod*, 8> LateParsedObjCMethodContainer; LateParsedObjCMethodContainer LateParsedObjCMethods; ObjCImplParsingDataRAII(Parser &parser, Decl *D) - : P(parser), Dcl(D) { + : P(parser), Dcl(D), HasCFunction(false) { P.CurParsedObjCImpl = this; Finished = false; } @@ -1262,6 +1114,7 @@ private: bool Finished; }; ObjCImplParsingDataRAII *CurParsedObjCImpl; + void StashAwayMethodOrFunctionBodyTokens(Decl *MDecl); DeclGroupPtrTy ParseObjCAtImplementationDeclaration(SourceLocation AtLoc); DeclGroupPtrTy ParseObjCAtEndDeclaration(SourceRange atEnd); @@ -1380,6 +1233,8 @@ private: // C++ Expressions ExprResult ParseCXXIdExpression(bool isAddressOfOperand = false); + bool areTokensAdjacent(const Token &A, const Token &B); + void CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectTypePtr, bool EnteringContext, IdentifierInfo &II, CXXScopeSpec &SS); @@ -1452,8 +1307,6 @@ private: // C++ 5.2.3: Explicit type conversion (functional notation) ExprResult ParseCXXTypeConstructExpression(const DeclSpec &DS); - bool isCXXSimpleTypeSpecifier() const; - /// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers. /// This should only be called when the current token is known to be part of /// simple-type-specifier. @@ -1508,6 +1361,7 @@ private: ExprResult ParseObjCBooleanLiteral(SourceLocation AtLoc, bool ArgValue); ExprResult ParseObjCArrayLiteral(SourceLocation AtLoc); ExprResult ParseObjCDictionaryLiteral(SourceLocation AtLoc); + ExprResult ParseObjCBoxedExpr(SourceLocation AtLoc); ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc); ExprResult ParseObjCSelectorExpression(SourceLocation AtLoc); ExprResult ParseObjCProtocolExpression(SourceLocation AtLoc); @@ -1639,7 +1493,7 @@ private: enum DeclSpecContext { DSC_normal, // normal context DSC_class, // class context, enables 'friend' - DSC_type_specifier, // C++ type-specifier-seq + DSC_type_specifier, // C++ type-specifier-seq or C specifier-qualifier-list DSC_trailing, // C++11 trailing-type-specifier in a trailing return type DSC_top_level // top-level/namespace declaration context }; @@ -1659,7 +1513,7 @@ private: DeclGroupPtrTy ParseSimpleDeclaration(StmtVector &Stmts, unsigned Context, SourceLocation &DeclEnd, - ParsedAttributes &attrs, + ParsedAttributesWithRange &attrs, bool RequireSemi, ForRangeInit *FRI = 0); bool MightBeDeclarator(unsigned Context); @@ -1705,7 +1559,7 @@ private: Decl *TagDecl); struct FieldCallback { - virtual Decl *invoke(FieldDeclarator &Field) = 0; + virtual void invoke(ParsingFieldDeclarator &Field) = 0; virtual ~FieldCallback() {} private: @@ -1713,7 +1567,7 @@ private: }; struct ObjCPropertyCallback; - void ParseStructDeclaration(DeclSpec &DS, FieldCallback &Callback); + void ParseStructDeclaration(ParsingDeclSpec &DS, FieldCallback &Callback); bool isDeclarationSpecifier(bool DisambiguatingWithExpression = false); bool isTypeSpecifierQualifier(); @@ -1789,11 +1643,11 @@ private: /// isCXXFunctionDeclarator - Disambiguates between a function declarator or /// a constructor-style initializer, when parsing declaration statements. /// Returns true for function declarator and false for constructor-style - /// initializer. If 'warnIfAmbiguous' is true a warning will be emitted to - /// indicate that the parens were disambiguated as function declarator. + /// initializer. Sets 'IsAmbiguous' to true to indicate that this declaration + /// might be a constructor-style initializer. /// If during the disambiguation process a parsing error is encountered, /// the function returns true to let the declaration parsing code handle it. - bool isCXXFunctionDeclarator(bool warnIfAmbiguous); + bool isCXXFunctionDeclarator(bool *IsAmbiguous = 0); /// isCXXConditionDeclaration - Disambiguates between a declaration or an /// expression for a condition of a if/switch/while/for statement. @@ -1850,7 +1704,8 @@ private: /// BracedCastResult. /// Doesn't consume tokens. TPResult - isCXXDeclarationSpecifier(TPResult BracedCastResult = TPResult::False()); + isCXXDeclarationSpecifier(TPResult BracedCastResult = TPResult::False(), + bool *HasMissingTypename = 0); // "Tentative parsing" functions, used for disambiguation. If a parsing error // is encountered they will return TPResult::Error(). @@ -1859,13 +1714,13 @@ private: // that more tentative parsing is necessary for disambiguation. // They all consume tokens, so backtracking should be used after calling them. - TPResult TryParseDeclarationSpecifier(); + TPResult TryParseDeclarationSpecifier(bool *HasMissingTypename = 0); TPResult TryParseSimpleDeclaration(bool AllowForRangeDecl); TPResult TryParseTypeofSpecifier(); TPResult TryParseProtocolQualifiers(); TPResult TryParseInitDeclaratorList(); TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier=true); - TPResult TryParseParameterDeclarationClause(); + TPResult TryParseParameterDeclarationClause(bool *InvalidAsDeclaration = 0); TPResult TryParseFunctionDeclarator(); TPResult TryParseBracketDeclarator(); @@ -1874,7 +1729,7 @@ private: = Declarator::TypeNameContext, AccessSpecifier AS = AS_none, Decl **OwnedType = 0); - void ParseBlockId(); + void ParseBlockId(SourceLocation CaretLoc); // Check for the start of a C++11 attribute-specifier-seq in a context where // an attribute is not allowed. @@ -1953,8 +1808,16 @@ private: } void ParseMicrosoftAttributes(ParsedAttributes &attrs, SourceLocation *endLoc = 0); - void ParseMicrosoftDeclSpec(ParsedAttributes &attrs); + void ParseMicrosoftDeclSpec(ParsedAttributes &Attrs); + bool IsSimpleMicrosoftDeclSpec(IdentifierInfo *Ident); + void ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident, + SourceLocation Loc, + ParsedAttributes &Attrs); + void ParseMicrosoftDeclSpecWithSingleArg(IdentifierInfo *AttrName, + SourceLocation AttrNameLoc, + ParsedAttributes &Attrs); void ParseMicrosoftTypeAttributes(ParsedAttributes &attrs); + void ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs); void ParseBorlandTypeAttributes(ParsedAttributes &attrs); void ParseOpenCLAttributes(ParsedAttributes &attrs); void ParseOpenCLQualifiers(DeclSpec &DS); @@ -2040,6 +1903,7 @@ private: void ParseFunctionDeclarator(Declarator &D, ParsedAttributes &attrs, BalancedDelimiterTracker &Tracker, + bool IsAmbiguous, bool RequiresArg = false); bool isFunctionDeclaratorIdentifierList(); void ParseFunctionDeclaratorIdentifierList( @@ -2100,6 +1964,7 @@ private: //===--------------------------------------------------------------------===// // C++ 9: classes [class] and C structs/unions. + bool isValidAfterTypeSpecifier(bool CouldBeBitfield); void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc, DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS, bool EnteringContext, diff --git a/include/clang/Rewrite/FrontendActions.h b/include/clang/Rewrite/FrontendActions.h index 6e9ecac..ea876d9 100644 --- a/include/clang/Rewrite/FrontendActions.h +++ b/include/clang/Rewrite/FrontendActions.h @@ -73,6 +73,11 @@ protected: void ExecuteAction(); }; +class RewriteIncludesAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + } // end namespace clang #endif diff --git a/include/clang/Rewrite/Rewriter.h b/include/clang/Rewrite/Rewriter.h index f1358a0..5ffd88b 100644 --- a/include/clang/Rewrite/Rewriter.h +++ b/include/clang/Rewrite/Rewriter.h @@ -279,6 +279,13 @@ public: buffer_iterator buffer_begin() { return RewriteBuffers.begin(); } buffer_iterator buffer_end() { return RewriteBuffers.end(); } + /// SaveFiles - Save all changed files to disk. + /// + /// Returns whether not all changes were saved successfully. + /// Outputs diagnostics via the source manager's diagnostic engine + /// in case of an error. + bool overwriteChangedFiles(); + private: unsigned getLocationOffsetAndFileID(SourceLocation Loc, FileID &FID) const; }; diff --git a/include/clang/Rewrite/Rewriters.h b/include/clang/Rewrite/Rewriters.h index 203b9bc..f5ade5a 100644 --- a/include/clang/Rewrite/Rewriters.h +++ b/include/clang/Rewrite/Rewriters.h @@ -18,6 +18,7 @@ namespace clang { class Preprocessor; +class PreprocessorOutputOptions; /// RewriteMacrosInInput - Implement -rewrite-macros mode. void RewriteMacrosInInput(Preprocessor &PP, raw_ostream *OS); @@ -25,6 +26,10 @@ void RewriteMacrosInInput(Preprocessor &PP, raw_ostream *OS); /// DoRewriteTest - A simple test for the TokenRewriter class. void DoRewriteTest(Preprocessor &PP, raw_ostream *OS); +/// RewriteIncludesInInput - Implement -frewrite-includes mode. +void RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS, + const PreprocessorOutputOptions &Opts); + } // end namespace clang #endif diff --git a/include/clang/Rewrite/TokenRewriter.h b/include/clang/Rewrite/TokenRewriter.h index 9ebd33a..894db09 100644 --- a/include/clang/Rewrite/TokenRewriter.h +++ b/include/clang/Rewrite/TokenRewriter.h @@ -16,12 +16,12 @@ #define LLVM_CLANG_TOKENREWRITER_H #include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Token.h" #include "llvm/ADT/OwningPtr.h" #include <list> #include <map> namespace clang { - class Token; class LangOptions; class ScratchBuffer; diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index 142f144..5239044 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -52,6 +52,16 @@ struct AvailabilityChange { /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used. /// class AttributeList { // TODO: This should really be called ParsedAttribute +public: + /// The style used to specify an attribute. + enum Syntax { + AS_GNU, + AS_CXX11, + AS_Declspec, + // eg) __w64, __ptr32, etc. It is implied that an MSTypespec is also + // a declspec. + AS_MSTypespec + }; private: IdentifierInfo *AttrName; IdentifierInfo *ScopeName; @@ -64,11 +74,8 @@ private: /// The expressions themselves are stored after the object. unsigned NumArgs : 16; - /// True if Microsoft style: declspec(foo). - unsigned DeclspecAttribute : 1; - - /// True if C++0x-style: [[foo]]. - unsigned CXX0XAttribute : 1; + /// Corresponds to the Syntax enum. + unsigned SyntaxUsed : 2; /// True if already diagnosed as invalid. mutable unsigned Invalid : 1; @@ -123,15 +130,14 @@ private: IdentifierInfo *scopeName, SourceLocation scopeLoc, IdentifierInfo *parmName, SourceLocation parmLoc, Expr **args, unsigned numArgs, - bool declspec, bool cxx0x) + Syntax syntaxUsed) : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), - NumArgs(numArgs), - DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false), + NumArgs(numArgs), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), NextInPosition(0), NextInPool(0) { if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*)); - AttrKind = getKind(getName()); + AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } AttributeList(IdentifierInfo *attrName, SourceRange attrRange, @@ -142,17 +148,17 @@ private: const AvailabilityChange &obsoleted, SourceLocation unavailable, const Expr *messageExpr, - bool declspec, bool cxx0x) + Syntax syntaxUsed) : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), - NumArgs(0), DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), + NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), UnavailableLoc(unavailable), MessageExpr(messageExpr), NextInPosition(0), NextInPool(0) { new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced); new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated); new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted); - AttrKind = getKind(getName()); + AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } friend class AttributePool; @@ -162,17 +168,6 @@ public: enum Kind { #define PARSED_ATTR(NAME) AT_##NAME, #include "clang/Sema/AttrParsedAttrList.inc" - PARSED_ATTR(address_space) - PARSED_ATTR(base_check) - PARSED_ATTR(cf_returns_autoreleased) - PARSED_ATTR(ext_vector_type) - PARSED_ATTR(mode) - PARSED_ATTR(neon_polyvector_type) - PARSED_ATTR(neon_vector_type) - PARSED_ATTR(objc_gc) - PARSED_ATTR(objc_ownership) - PARSED_ATTR(opencl_image_access) - PARSED_ATTR(vector_size) #undef PARSED_ATTR IgnoredAttribute, UnknownAttribute @@ -189,8 +184,12 @@ public: IdentifierInfo *getParameterName() const { return ParmName; } SourceLocation getParameterLoc() const { return ParmLoc; } - bool isDeclspecAttribute() const { return DeclspecAttribute; } - bool isCXX0XAttribute() const { return CXX0XAttribute; } + /// Returns true if the attribute is a pure __declspec or a synthesized + /// declspec representing a type specification (like __w64 or __ptr32). + bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec || + SyntaxUsed == AS_MSTypespec; } + bool isCXX0XAttribute() const { return SyntaxUsed == AS_CXX11; } + bool isMSTypespecAttribute() const { return SyntaxUsed == AS_MSTypespec; } bool isInvalid() const { return Invalid; } void setInvalid(bool b = true) const { Invalid = b; } @@ -199,7 +198,8 @@ public: void setUsedAsTypeAttr() { UsedAsTypeAttr = true; } Kind getKind() const { return Kind(AttrKind); } - static Kind getKind(const IdentifierInfo *Name); + static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope, + Syntax SyntaxUsed); AttributeList *getNext() const { return NextInPosition; } void setNext(AttributeList *N) { NextInPosition = N; } @@ -256,27 +256,27 @@ public: } const AvailabilityChange &getAvailabilityIntroduced() const { - assert(getKind() == AT_availability && "Not an availability attribute"); + assert(getKind() == AT_Availability && "Not an availability attribute"); return getAvailabilitySlot(IntroducedSlot); } const AvailabilityChange &getAvailabilityDeprecated() const { - assert(getKind() == AT_availability && "Not an availability attribute"); + assert(getKind() == AT_Availability && "Not an availability attribute"); return getAvailabilitySlot(DeprecatedSlot); } const AvailabilityChange &getAvailabilityObsoleted() const { - assert(getKind() == AT_availability && "Not an availability attribute"); + assert(getKind() == AT_Availability && "Not an availability attribute"); return getAvailabilitySlot(ObsoletedSlot); } SourceLocation getUnavailableLoc() const { - assert(getKind() == AT_availability && "Not an availability attribute"); + assert(getKind() == AT_Availability && "Not an availability attribute"); return UnavailableLoc; } const Expr * getMessageExpr() const { - assert(getKind() == AT_availability && "Not an availability attribute"); + assert(getKind() == AT_Availability && "Not an availability attribute"); return MessageExpr; } }; @@ -383,14 +383,13 @@ public: IdentifierInfo *scopeName, SourceLocation scopeLoc, IdentifierInfo *parmName, SourceLocation parmLoc, Expr **args, unsigned numArgs, - bool declspec = false, bool cxx0x = false) { + AttributeList::Syntax syntax) { void *memory = allocate(sizeof(AttributeList) + numArgs * sizeof(Expr*)); return add(new (memory) AttributeList(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc, - args, numArgs, - declspec, cxx0x)); + args, numArgs, syntax)); } AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, @@ -401,14 +400,13 @@ public: const AvailabilityChange &obsoleted, SourceLocation unavailable, const Expr *MessageExpr, - bool declspec = false, bool cxx0x = false) { + AttributeList::Syntax syntax) { void *memory = allocate(AttributeFactory::AvailabilityAllocSize); return add(new (memory) AttributeList(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc, introduced, deprecated, obsoleted, - unavailable, MessageExpr, - declspec, cxx0x)); + unavailable, MessageExpr, syntax)); } AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name, @@ -510,10 +508,10 @@ public: IdentifierInfo *scopeName, SourceLocation scopeLoc, IdentifierInfo *parmName, SourceLocation parmLoc, Expr **args, unsigned numArgs, - bool declspec = false, bool cxx0x = false) { + AttributeList::Syntax syntax) { AttributeList *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc, - args, numArgs, declspec, cxx0x); + args, numArgs, syntax); add(attr); return attr; } @@ -526,12 +524,11 @@ public: const AvailabilityChange &obsoleted, SourceLocation unavailable, const Expr *MessageExpr, - bool declspec = false, bool cxx0x = false) { + AttributeList::Syntax syntax) { AttributeList *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc, introduced, deprecated, obsoleted, unavailable, - MessageExpr, - declspec, cxx0x); + MessageExpr, syntax); add(attr); return attr; } diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index fe9bed5..d43aaaf 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -15,6 +15,7 @@ #include "clang/AST/Type.h" #include "clang/AST/CanonicalType.h" +#include "clang/Sema/CodeCompleteOptions.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" @@ -237,7 +238,7 @@ public: /// This context usually implies that no completions should be added, /// unless they come from an appropriate natural-language dictionary. CCC_NaturalLanguage, - /// \brief Code completion for a selector, as in an @selector expression. + /// \brief Code completion for a selector, as in an \@selector expression. CCC_SelectorName, /// \brief Code completion within a type-qualifier list. CCC_TypeQualifiers, @@ -379,7 +380,7 @@ public: CK_Equal, /// \brief Horizontal whitespace (' '). CK_HorizontalSpace, - /// \brief Verticle whitespace ('\n' or '\r\n', depending on the + /// \brief Vertical whitespace ('\\n' or '\\r\\n', depending on the /// platform). CK_VerticalSpace }; @@ -444,6 +445,10 @@ private: /// \brief The name of the parent context. StringRef ParentName; + + /// \brief A brief documentation comment attached to the declaration of + /// entity being completed by this result. + const char *BriefComment; CodeCompletionString(const CodeCompletionString &); // DO NOT IMPLEMENT CodeCompletionString &operator=(const CodeCompletionString &); // DITTO @@ -451,7 +456,8 @@ private: CodeCompletionString(const Chunk *Chunks, unsigned NumChunks, unsigned Priority, CXAvailabilityKind Availability, const char **Annotations, unsigned NumAnnotations, - CXCursorKind ParentKind, StringRef ParentName); + CXCursorKind ParentKind, StringRef ParentName, + const char *BriefComment); ~CodeCompletionString() { } friend class CodeCompletionBuilder; @@ -493,6 +499,10 @@ public: StringRef getParentContextName() const { return ParentName; } + + const char *getBriefComment() const { + return BriefComment; + } /// \brief Retrieve a string representation of the code completion string, /// which is mainly useful for debugging. @@ -569,6 +579,7 @@ private: CXAvailabilityKind Availability; CXCursorKind ParentKind; StringRef ParentName; + const char *BriefComment; /// \brief The chunks stored in this string. SmallVector<Chunk, 4> Chunks; @@ -580,14 +591,14 @@ public: CodeCompletionTUInfo &CCTUInfo) : Allocator(Allocator), CCTUInfo(CCTUInfo), Priority(0), Availability(CXAvailability_Available), - ParentKind(CXCursor_NotImplemented) { } + ParentKind(CXCursor_NotImplemented), BriefComment(NULL) { } CodeCompletionBuilder(CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, unsigned Priority, CXAvailabilityKind Availability) : Allocator(Allocator), CCTUInfo(CCTUInfo), Priority(Priority), Availability(Availability), - ParentKind(CXCursor_NotImplemented) { } + ParentKind(CXCursor_NotImplemented), BriefComment(NULL) { } /// \brief Retrieve the allocator into which the code completion /// strings should be allocated. @@ -628,6 +639,8 @@ public: /// \brief Add the parent context information to this code completion. void addParentContext(DeclContext *DC); + + void addBriefComment(StringRef Comment); CXCursorKind getParentKind() const { return ParentKind; } StringRef getParentName() const { return ParentName; } @@ -638,15 +651,12 @@ class CodeCompletionResult { public: /// \brief Describes the kind of result generated. enum ResultKind { - RK_Declaration = 0, //< Refers to a declaration - RK_Keyword, //< Refers to a keyword or symbol. - RK_Macro, //< Refers to a macro - RK_Pattern //< Refers to a precomputed pattern. + RK_Declaration = 0, ///< Refers to a declaration + RK_Keyword, ///< Refers to a keyword or symbol. + RK_Macro, ///< Refers to a macro + RK_Pattern ///< Refers to a precomputed pattern. }; - /// \brief The kind of result stored here. - ResultKind Kind; - /// \brief When Kind == RK_Declaration or RK_Pattern, the declaration we are /// referring to. In the latter case, the declaration might be NULL. NamedDecl *Declaration; @@ -667,16 +677,19 @@ public: /// \brief The priority of this particular code-completion result. unsigned Priority; + /// \brief Specifies which parameter (of a function, Objective-C method, + /// macro, etc.) we should start with when formatting the result. + unsigned StartParameter; + + /// \brief The kind of result stored here. + ResultKind Kind; + /// \brief The cursor kind that describes this result. CXCursorKind CursorKind; /// \brief The availability of this result. CXAvailabilityKind Availability; - /// \brief Specifies which parameter (of a function, Objective-C method, - /// macro, etc.) we should start with when formatting the result. - unsigned StartParameter; - /// \brief Whether this result is hidden by another name. bool Hidden : 1; @@ -705,10 +718,10 @@ public: NestedNameSpecifier *Qualifier = 0, bool QualifierIsInformative = false, bool Accessible = true) - : Kind(RK_Declaration), Declaration(Declaration), - Priority(getPriorityFromDecl(Declaration)), - Availability(CXAvailability_Available), StartParameter(0), - Hidden(false), QualifierIsInformative(QualifierIsInformative), + : Declaration(Declaration), Priority(getPriorityFromDecl(Declaration)), + StartParameter(0), Kind(RK_Declaration), + Availability(CXAvailability_Available), Hidden(false), + QualifierIsInformative(QualifierIsInformative), StartsNestedNameSpecifier(false), AllParametersAreInformative(false), DeclaringEntity(false), Qualifier(Qualifier) { computeCursorKindAndAvailability(Accessible); @@ -716,22 +729,22 @@ public: /// \brief Build a result that refers to a keyword or symbol. CodeCompletionResult(const char *Keyword, unsigned Priority = CCP_Keyword) - : Kind(RK_Keyword), Declaration(0), Keyword(Keyword), Priority(Priority), - Availability(CXAvailability_Available), - StartParameter(0), Hidden(false), QualifierIsInformative(0), - StartsNestedNameSpecifier(false), AllParametersAreInformative(false), - DeclaringEntity(false), Qualifier(0) { - computeCursorKindAndAvailability(); + : Declaration(0), Keyword(Keyword), Priority(Priority), StartParameter(0), + Kind(RK_Keyword), CursorKind(CXCursor_NotImplemented), + Availability(CXAvailability_Available), Hidden(false), + QualifierIsInformative(0), StartsNestedNameSpecifier(false), + AllParametersAreInformative(false), DeclaringEntity(false), Qualifier(0) + { } /// \brief Build a result that refers to a macro. CodeCompletionResult(IdentifierInfo *Macro, unsigned Priority = CCP_Macro) - : Kind(RK_Macro), Declaration(0), Macro(Macro), Priority(Priority), - Availability(CXAvailability_Available), StartParameter(0), - Hidden(false), QualifierIsInformative(0), - StartsNestedNameSpecifier(false), AllParametersAreInformative(false), - DeclaringEntity(false), Qualifier(0) { - computeCursorKindAndAvailability(); + : Declaration(0), Macro(Macro), Priority(Priority), StartParameter(0), + Kind(RK_Macro), CursorKind(CXCursor_MacroDefinition), + Availability(CXAvailability_Available), Hidden(false), + QualifierIsInformative(0), StartsNestedNameSpecifier(false), + AllParametersAreInformative(false), DeclaringEntity(false), Qualifier(0) + { } /// \brief Build a result that refers to a pattern. @@ -740,8 +753,8 @@ public: CXCursorKind CursorKind = CXCursor_NotImplemented, CXAvailabilityKind Availability = CXAvailability_Available, NamedDecl *D = 0) - : Kind(RK_Pattern), Declaration(D), Pattern(Pattern), Priority(Priority), - CursorKind(CursorKind), Availability(Availability), StartParameter(0), + : Declaration(D), Pattern(Pattern), Priority(Priority), StartParameter(0), + Kind(RK_Pattern), CursorKind(CursorKind), Availability(Availability), Hidden(false), QualifierIsInformative(0), StartsNestedNameSpecifier(false), AllParametersAreInformative(false), DeclaringEntity(false), Qualifier(0) @@ -752,11 +765,10 @@ public: /// declaration. CodeCompletionResult(CodeCompletionString *Pattern, NamedDecl *D, unsigned Priority) - : Kind(RK_Pattern), Declaration(D), Pattern(Pattern), Priority(Priority), - Availability(CXAvailability_Available), StartParameter(0), - Hidden(false), QualifierIsInformative(false), - StartsNestedNameSpecifier(false), AllParametersAreInformative(false), - DeclaringEntity(false), Qualifier(0) { + : Declaration(D), Pattern(Pattern), Priority(Priority), StartParameter(0), + Kind(RK_Pattern), Availability(CXAvailability_Available), Hidden(false), + QualifierIsInformative(false), StartsNestedNameSpecifier(false), + AllParametersAreInformative(false), DeclaringEntity(false), Qualifier(0) { computeCursorKindAndAvailability(); } @@ -781,11 +793,13 @@ public: /// string itself. CodeCompletionString *CreateCodeCompletionString(Sema &S, CodeCompletionAllocator &Allocator, - CodeCompletionTUInfo &CCTUInfo); + CodeCompletionTUInfo &CCTUInfo, + bool IncludeBriefComments); CodeCompletionString *CreateCodeCompletionString(ASTContext &Ctx, Preprocessor &PP, CodeCompletionAllocator &Allocator, - CodeCompletionTUInfo &CCTUInfo); + CodeCompletionTUInfo &CCTUInfo, + bool IncludeBriefComments); /// \brief Determine a base priority for the given declaration. static unsigned getPriorityFromDecl(NamedDecl *ND); @@ -819,16 +833,7 @@ raw_ostream &operator<<(raw_ostream &OS, /// information. class CodeCompleteConsumer { protected: - /// \brief Whether to include macros in the code-completion results. - bool IncludeMacros; - - /// \brief Whether to include code patterns (such as for loops) within - /// the completion results. - bool IncludeCodePatterns; - - /// \brief Whether to include global (top-level) declarations and names in - /// the completion results. - bool IncludeGlobals; + const CodeCompleteOptions CodeCompleteOpts; /// \brief Whether the output format for the code-completion consumer is /// binary. @@ -901,22 +906,31 @@ public: CodeCompletionTUInfo &CCTUInfo) const; }; - CodeCompleteConsumer() : IncludeMacros(false), IncludeCodePatterns(false), - IncludeGlobals(true), OutputIsBinary(false) { } - - CodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns, - bool IncludeGlobals, bool OutputIsBinary) - : IncludeMacros(IncludeMacros), IncludeCodePatterns(IncludeCodePatterns), - IncludeGlobals(IncludeGlobals), OutputIsBinary(OutputIsBinary) { } + CodeCompleteConsumer(const CodeCompleteOptions &CodeCompleteOpts, + bool OutputIsBinary) + : CodeCompleteOpts(CodeCompleteOpts), OutputIsBinary(OutputIsBinary) + { } /// \brief Whether the code-completion consumer wants to see macros. - bool includeMacros() const { return IncludeMacros; } + bool includeMacros() const { + return CodeCompleteOpts.IncludeMacros; + } /// \brief Whether the code-completion consumer wants to see code patterns. - bool includeCodePatterns() const { return IncludeCodePatterns; } + bool includeCodePatterns() const { + return CodeCompleteOpts.IncludeCodePatterns; + } /// \brief Whether to include global (top-level) declaration results. - bool includeGlobals() const { return IncludeGlobals; } + bool includeGlobals() const { + return CodeCompleteOpts.IncludeGlobals; + } + + /// \brief Whether to include brief documentation comments within the set of + /// code completions returned. + bool includeBriefComments() const { + return CodeCompleteOpts.IncludeBriefComments; + } /// \brief Determine whether the output of this consumer is binary. bool isOutputBinary() const { return OutputIsBinary; } @@ -963,11 +977,9 @@ class PrintingCodeCompleteConsumer : public CodeCompleteConsumer { public: /// \brief Create a new printing code-completion consumer that prints its /// results to the given raw output stream. - PrintingCodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns, - bool IncludeGlobals, + PrintingCodeCompleteConsumer(const CodeCompleteOptions &CodeCompleteOpts, raw_ostream &OS) - : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals, - false), OS(OS), + : CodeCompleteConsumer(CodeCompleteOpts, false), OS(OS), CCTUInfo(new GlobalCodeCompletionAllocator) {} /// \brief Prints the finalized code-completion results. diff --git a/include/clang/Sema/CodeCompleteOptions.h b/include/clang/Sema/CodeCompleteOptions.h new file mode 100644 index 0000000..30712db --- /dev/null +++ b/include/clang/Sema/CodeCompleteOptions.h @@ -0,0 +1,37 @@ +//===---- CodeCompleteOptions.h - Code Completion Options -------*- 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_SEMA_CODECOMPLETEOPTIONS_H +#define LLVM_CLANG_SEMA_CODECOMPLETEOPTIONS_H + +/// Options controlling the behavior of code completion. +class CodeCompleteOptions { +public: + ///< Show macros in code completion results. + unsigned IncludeMacros : 1; + + ///< Show code patterns in code completion results. + unsigned IncludeCodePatterns : 1; + + ///< Show top-level decls in code completion results. + unsigned IncludeGlobals : 1; + + ///< Show brief documentation comments in code completion results. + unsigned IncludeBriefComments : 1; + + CodeCompleteOptions() : + IncludeMacros(0), + IncludeCodePatterns(0), + IncludeGlobals(1), + IncludeBriefComments(0) + { } +}; + +#endif + diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 67fd393..792b0c6 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -6,15 +6,18 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the classes used to store parsed information about -// declaration-specifiers and declarators. -// -// static const int volatile x, *y, *(*(*z)[10])(const void *x); -// ------------------------- - -- --------------------------- -// declaration-specifiers \ | / -// declarators -// +/// +/// \file +/// \brief This file defines the classes used to store parsed information about +/// declaration-specifiers and declarators. +/// +/// \verbatim +/// static const int volatile x, *y, *(*(*z)[10])(const void *x); +/// ------------------------- - -- --------------------------- +/// declaration-specifiers \ | / +/// declarators +/// \endverbatim +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_SEMA_DECLSPEC_H @@ -48,8 +51,9 @@ namespace clang { class Declarator; struct TemplateIdAnnotation; -/// CXXScopeSpec - Represents a C++ nested-name-specifier or a global scope -/// specifier. These can be in 3 states: +/// \brief Represents a C++ nested-name-specifier or a global scope specifier. +/// +/// These can be in 3 states: /// 1) Not present, identified by isEmpty() /// 2) Present, identified by isNotEmpty() /// 2.a) Valid, idenified by isValid() @@ -158,9 +162,14 @@ public: NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const; /// \brief Retrieve the location of the name in the last qualifier - /// in this nested name specifier. For example: - /// ::foo::bar<0>:: - /// ^~~ + /// in this nested name specifier. + /// + /// For example, the location of \c bar + /// in + /// \verbatim + /// \::foo::bar<0>:: + /// ^~~ + /// \endverbatim SourceLocation getLastQualifierNameLoc() const; /// No scope specifier. @@ -199,13 +208,14 @@ public: unsigned location_size() const { return Builder.getBuffer().second; } }; -/// DeclSpec - This class captures information about "declaration specifiers", -/// which encompasses storage-class-specifiers, type-specifiers, -/// type-qualifiers, and function-specifiers. +/// \brief Captures information about "declaration specifiers". +/// +/// "Declaration specifiers" encompasses storage-class-specifiers, +/// type-specifiers, type-qualifiers, and function-specifiers. class DeclSpec { public: - // storage-class-specifier - // Note: The order of these enumerators is important for diagnostics. + /// \brief storage-class-specifier + /// \note The order of these enumerators is important for diagnostics. enum SCS { SCS_unspecified = 0, SCS_typedef, @@ -466,8 +476,7 @@ public: SourceRange getTypeofParensRange() const { return TypeofParensRange; } void setTypeofParensRange(SourceRange range) { TypeofParensRange = range; } - /// getSpecifierName - Turn a type-specifier-type into a string like "_Bool" - /// or "union". + /// \brief Turn a type-specifier-type into a string like "_Bool" or "union". static const char *getSpecifierName(DeclSpec::TST T); static const char *getSpecifierName(DeclSpec::TQ Q); static const char *getSpecifierName(DeclSpec::TSS S); @@ -510,7 +519,7 @@ public: FS_explicitLoc = SourceLocation(); } - /// hasTypeSpecifier - Return true if any type-specifier has been found. + /// \brief Return true if any type-specifier has been found. bool hasTypeSpecifier() const { return getTypeSpecType() != DeclSpec::TST_unspecified || getTypeSpecWidth() != DeclSpec::TSW_unspecified || @@ -518,9 +527,8 @@ public: getTypeSpecSign() != DeclSpec::TSS_unspecified; } - /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this + /// \brief Return a bitmask of which flavors of specifiers this /// DeclSpec includes. - /// unsigned getParsedSpecifiers() const; SCS getStorageClassSpecAsWritten() const { @@ -590,7 +598,8 @@ public: } bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, - unsigned &DiagID, const LangOptions &Lang); + unsigned &DiagID, const LangOptions &Lang, + bool IsTypeSpec); bool SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID); @@ -624,17 +633,22 @@ public: return Attrs.getPool(); } - /// AddAttributes - contatenates two attribute lists. + /// \brief Concatenates two attribute lists. + /// /// The GCC attribute syntax allows for the following: /// + /// \code /// short __attribute__(( unused, deprecated )) /// int __attribute__(( may_alias, aligned(16) )) var; + /// \endcode /// /// This declares 4 attributes using 2 lists. The following syntax is /// also allowed and equivalent to the previous declaration. /// + /// \code /// short __attribute__((unused)) __attribute__((deprecated)) /// int __attribute__((may_alias)) __attribute__((aligned(16))) var; + /// \endcode /// void addAttributes(AttributeList *AL) { Attrs.addAll(AL); @@ -648,7 +662,7 @@ public: ParsedAttributes &getAttributes() { return Attrs; } const ParsedAttributes &getAttributes() const { return Attrs; } - /// TakeAttributes - Return the current attribute list and remove them from + /// \brief Return the current attribute list and remove them from /// the DeclSpec so that it doesn't own them. ParsedAttributes takeAttributes() { // The non-const "copy" constructor clears the operand automatically. @@ -684,13 +698,14 @@ public: ObjCDeclSpec *getObjCQualifiers() const { return ObjCQualifiers; } void setObjCQualifiers(ObjCDeclSpec *quals) { ObjCQualifiers = quals; } - /// isMissingDeclaratorOk - This checks if this DeclSpec can stand alone, - /// without a Declarator. Only tag declspecs can stand alone. + /// \brief Checks if this DeclSpec can stand alone, without a Declarator. + /// + /// Only tag declspecs can stand alone. bool isMissingDeclaratorOk(); }; -/// ObjCDeclSpec - This class captures information about -/// "declaration specifiers" specific to objective-c +/// \brief Captures information about "declaration specifiers" specific to +/// Objective-C. class ObjCDeclSpec { public: /// ObjCDeclQualifier - Qualifier used on types in method @@ -853,12 +868,14 @@ public: assert(Other.Kind == IK_Identifier && "Cannot copy non-identifiers"); } - /// \brief Destroy this unqualified-id. - ~UnqualifiedId() { clear(); } - /// \brief Clear out this unqualified-id, setting it to default (invalid) /// state. - void clear(); + void clear() { + Kind = IK_Identifier; + Identifier = 0; + StartLocation = SourceLocation(); + EndLocation = SourceLocation(); + } /// \brief Determine whether this unqualified-id refers to a valid name. bool isValid() const { return StartLocation.isValid(); } @@ -979,12 +996,11 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return StartLocation; } SourceLocation getLocEnd() const LLVM_READONLY { return EndLocation; } }; - -/// CachedTokens - A set of tokens that has been cached for later -/// parsing. + +/// \brief A set of tokens that has been cached for later parsing. typedef SmallVector<Token, 4> CachedTokens; -/// DeclaratorChunk - One instance of this struct is used for each type in a +/// \brief One instance of this struct is used for each type in a /// declarator that is parsed. /// /// This is intended to be a small value object. @@ -1088,6 +1104,9 @@ struct DeclaratorChunk { /// contains the location of the ellipsis. unsigned isVariadic : 1; + /// Can this declaration be a constructor-style initializer? + unsigned isAmbiguous : 1; + /// \brief Whether the ref-qualifier (if any) is an lvalue reference. /// Otherwise, it's an rvalue reference. unsigned RefQualifierIsLValueRef : 1; @@ -1102,6 +1121,10 @@ struct DeclaratorChunk { /// DeleteArgInfo - If this is true, we need to delete[] ArgInfo. unsigned DeleteArgInfo : 1; + /// HasTrailingReturnType - If this is true, a trailing return type was + /// specified. + unsigned HasTrailingReturnType : 1; + /// When isVariadic is true, the location of the ellipsis in the source. unsigned EllipsisLoc; @@ -1132,8 +1155,7 @@ struct DeclaratorChunk { /// any. unsigned MutableLoc; - /// \brief When ExceptionSpecType isn't EST_None or EST_Delayed, the - /// location of the keyword introducing the spec. + /// \brief The location of the keyword introducing the spec, if any. unsigned ExceptionSpecLoc; /// ArgInfo - This is a pointer to a new[]'d array of ParamInfo objects that @@ -1152,13 +1174,13 @@ struct DeclaratorChunk { Expr *NoexceptExpr; }; - /// TrailingReturnType - If this isn't null, it's the trailing return type - /// specified. This is actually a ParsedType, but stored as void* to - /// allow union storage. - void *TrailingReturnType; + /// \brief If HasTrailingReturnType is true, this is the trailing return + /// type specified. + UnionParsedType TrailingReturnType; - /// freeArgs - reset the argument list to having zero arguments. This is - /// used in various places for error recovery. + /// \brief Reset the argument list to having zero arguments. + /// + /// This is used in various places for error recovery. void freeArgs() { if (DeleteArgInfo) { delete[] ArgInfo; @@ -1220,6 +1242,13 @@ struct DeclaratorChunk { ExceptionSpecificationType getExceptionSpecType() const { return static_cast<ExceptionSpecificationType>(ExceptionSpecType); } + + /// \brief Determine whether this function declarator had a + /// trailing-return-type. + bool hasTrailingReturnType() const { return HasTrailingReturnType; } + + /// \brief Get the trailing-return-type for this function declarator. + ParsedType getTrailingReturnType() const { return TrailingReturnType; } }; struct BlockPointerTypeInfo : TypeInfoCommon { @@ -1273,7 +1302,7 @@ struct DeclaratorChunk { } } - /// getAttrs - If there are attributes applied to this declaratorchunk, return + /// \brief If there are attributes applied to this declaratorchunk, return /// them. const AttributeList *getAttrs() const { return Common.AttrList; @@ -1283,8 +1312,7 @@ struct DeclaratorChunk { return Common.AttrList; } - /// getPointer - Return a DeclaratorChunk for a pointer. - /// + /// \brief Return a DeclaratorChunk for a pointer. static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc, SourceLocation ConstQualLoc, SourceLocation VolatileQualLoc, @@ -1300,8 +1328,7 @@ struct DeclaratorChunk { return I; } - /// getReference - Return a DeclaratorChunk for a reference. - /// + /// \brief Return a DeclaratorChunk for a reference. static DeclaratorChunk getReference(unsigned TypeQuals, SourceLocation Loc, bool lvalue) { DeclaratorChunk I; @@ -1313,8 +1340,7 @@ struct DeclaratorChunk { return I; } - /// getArray - Return a DeclaratorChunk for an array. - /// + /// \brief Return a DeclaratorChunk for an array. static DeclaratorChunk getArray(unsigned TypeQuals, bool isStatic, bool isStar, Expr *NumElts, SourceLocation LBLoc, SourceLocation RBLoc) { @@ -1333,6 +1359,7 @@ struct DeclaratorChunk { /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. /// "TheDeclarator" is the declarator that this will be added to. static DeclaratorChunk getFunction(bool hasProto, bool isVariadic, + bool isAmbiguous, SourceLocation EllipsisLoc, ParamInfo *ArgInfo, unsigned NumArgs, unsigned TypeQuals, @@ -1350,11 +1377,10 @@ struct DeclaratorChunk { SourceLocation LocalRangeBegin, SourceLocation LocalRangeEnd, Declarator &TheDeclarator, - ParsedType TrailingReturnType = - ParsedType()); + TypeResult TrailingReturnType = + TypeResult()); - /// getBlockPointer - Return a DeclaratorChunk for a block. - /// + /// \brief Return a DeclaratorChunk for a block. static DeclaratorChunk getBlockPointer(unsigned TypeQuals, SourceLocation Loc) { DeclaratorChunk I; @@ -1377,8 +1403,7 @@ struct DeclaratorChunk { return I; } - /// getParen - Return a DeclaratorChunk for a paren. - /// + /// \brief Return a DeclaratorChunk for a paren. static DeclaratorChunk getParen(SourceLocation LParenLoc, SourceLocation RParenLoc) { DeclaratorChunk I; @@ -1399,10 +1424,12 @@ enum FunctionDefinitionKind { FDK_Defaulted, FDK_Deleted }; - -/// Declarator - Information about one declarator, including the parsed type -/// information and the identifier. When the declarator is fully formed, this -/// is turned into the appropriate Decl object. + +/// \brief Information about one declarator, including the parsed type +/// information and the identifier. +/// +/// When the declarator is fully formed, this is turned into the appropriate +/// Decl object. /// /// Declarators come in two types: normal declarators and abstract declarators. /// Abstract declarators are used when parsing types, and don't have an @@ -1441,8 +1468,7 @@ private: UnqualifiedId Name; SourceRange Range; - /// Context - Where we are parsing this declarator. - /// + /// \brief Where we are parsing this declarator. TheContext Context; /// DeclTypeInfo - This holds each type that the declarator includes as it is @@ -1463,13 +1489,13 @@ private: /// Actually a FunctionDefinitionKind. unsigned FunctionDefinition : 2; - // Redeclaration - Is this Declarator is a redeclaration. + /// \brief Is this Declarator a redeclaration? bool Redeclaration : 1; /// Attrs - Attributes. ParsedAttributes Attrs; - /// AsmLabel - The asm label, if specified. + /// \brief The asm label, if specified. Expr *AsmLabel; /// InlineParams - This is a local array used for the first function decl @@ -1478,7 +1504,7 @@ private: DeclaratorChunk::ParamInfo InlineParams[16]; bool InlineParamsUsed; - /// Extension - true if the declaration is preceded by __extension__. + /// \brief true if the declaration is preceded by \c __extension__. bool Extension : 1; /// \brief If this is the second or subsequent declarator in this declaration, @@ -1536,7 +1562,7 @@ public: Context == ObjCResultContext); } - /// getSourceRange - Get the source range that spans this declarator. + /// \brief Get the source range that spans this declarator. const SourceRange &getSourceRange() const LLVM_READONLY { return Range; } SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } @@ -1564,7 +1590,7 @@ public: Range.setEnd(SR.getEnd()); } - /// clear - Reset the contents of this Declarator. + /// \brief Reset the contents of this Declarator. void clear() { SS.clear(); Name.clear(); @@ -1730,13 +1756,12 @@ public: SetRangeEnd(EndLoc); } - /// AddInnermostTypeInfo - Add a new innermost chunk to this declarator. + /// \brief Add a new innermost chunk to this declarator. void AddInnermostTypeInfo(const DeclaratorChunk &TI) { DeclTypeInfo.insert(DeclTypeInfo.begin(), TI); } - /// getNumTypeObjects() - Return the number of types applied to this - /// declarator. + /// \brief Return the number of types applied to this declarator. unsigned getNumTypeObjects() const { return DeclTypeInfo.size(); } /// Return the specified TypeInfo from this declarator. TypeInfo #0 is @@ -1902,17 +1927,16 @@ public: bool isRedeclaration() const { return Redeclaration; } }; -/// FieldDeclarator - This little struct is used to capture information about +/// \brief This little struct is used to capture information about /// structure field declarators, which is basically just a bitfield size. struct FieldDeclarator { Declarator D; Expr *BitfieldSize; - explicit FieldDeclarator(DeclSpec &DS) : D(DS, Declarator::MemberContext) { - BitfieldSize = 0; - } + explicit FieldDeclarator(const DeclSpec &DS) + : D(DS, Declarator::MemberContext), BitfieldSize(0) { } }; -/// VirtSpecifiers - Represents a C++0x virt-specifier-seq. +/// \brief Represents a C++11 virt-specifier-seq. class VirtSpecifiers { public: enum Specifier { @@ -1945,7 +1969,7 @@ private: SourceLocation LastLocation; }; -/// LambdaCapture - An individual capture in a lambda introducer. +/// \brief An individual capture in a lambda introducer. struct LambdaCapture { LambdaCaptureKind Kind; SourceLocation Loc; @@ -1959,7 +1983,7 @@ struct LambdaCapture { {} }; -/// LambdaIntroducer - Represents a complete lambda introducer. +/// \brief Represents a complete lambda introducer. struct LambdaIntroducer { SourceRange Range; SourceLocation DefaultLoc; @@ -1969,7 +1993,7 @@ struct LambdaIntroducer { LambdaIntroducer() : Default(LCD_None) {} - /// addCapture - Append a capture in a lambda introducer. + /// \brief Append a capture in a lambda introducer. void addCapture(LambdaCaptureKind Kind, SourceLocation Loc, IdentifierInfo* Id = 0, diff --git a/include/clang/Sema/DelayedDiagnostic.h b/include/clang/Sema/DelayedDiagnostic.h index 3320cd8..c241266 100644 --- a/include/clang/Sema/DelayedDiagnostic.h +++ b/include/clang/Sema/DelayedDiagnostic.h @@ -21,7 +21,7 @@ #ifndef LLVM_CLANG_SEMA_DELAYED_DIAGNOSTIC_H #define LLVM_CLANG_SEMA_DELAYED_DIAGNOSTIC_H -#include "clang/AST/DeclCXX.h" +#include "clang/Sema/Sema.h" namespace clang { namespace sema { @@ -40,17 +40,17 @@ public: bool isMemberAccess() const { return IsMember; } - AccessedEntity(ASTContext &Context, + AccessedEntity(PartialDiagnostic::StorageAllocator &Allocator, MemberNonce _, CXXRecordDecl *NamingClass, DeclAccessPair FoundDecl, QualType BaseObjectType) : Access(FoundDecl.getAccess()), IsMember(true), Target(FoundDecl.getDecl()), NamingClass(NamingClass), - BaseObjectType(BaseObjectType), Diag(0, Context.getDiagAllocator()) { + BaseObjectType(BaseObjectType), Diag(0, Allocator) { } - AccessedEntity(ASTContext &Context, + AccessedEntity(PartialDiagnostic::StorageAllocator &Allocator, BaseNonce _, CXXRecordDecl *BaseClass, CXXRecordDecl *DerivedClass, @@ -58,7 +58,7 @@ public: : Access(Access), IsMember(false), Target(BaseClass), NamingClass(DerivedClass), - Diag(0, Context.getDiagAllocator()) { + Diag(0, Allocator) { } bool isQuiet() const { return Diag.getDiagID() == 0; } @@ -214,7 +214,63 @@ private: }; }; +/// DelayedDiagnosticPool - A collection of diagnostics which were +/// delayed. +class DelayedDiagnosticPool { + const DelayedDiagnosticPool *Parent; + llvm::SmallVector<DelayedDiagnostic, 4> Diagnostics; + + // Do not implement. + DelayedDiagnosticPool(const DelayedDiagnosticPool &other); + DelayedDiagnosticPool &operator=(const DelayedDiagnosticPool &other); +public: + DelayedDiagnosticPool(const DelayedDiagnosticPool *parent) : Parent(parent) {} + ~DelayedDiagnosticPool() { + for (llvm::SmallVectorImpl<DelayedDiagnostic>::iterator + i = Diagnostics.begin(), e = Diagnostics.end(); i != e; ++i) + i->Destroy(); + } + + const DelayedDiagnosticPool *getParent() const { return Parent; } + + /// Does this pool, or any of its ancestors, contain any diagnostics? + bool empty() const { + return (Diagnostics.empty() && (Parent == NULL || Parent->empty())); + } + + /// Add a diagnostic to this pool. + void add(const DelayedDiagnostic &diag) { + Diagnostics.push_back(diag); + } + + /// Steal the diagnostics from the given pool. + void steal(DelayedDiagnosticPool &pool) { + if (pool.Diagnostics.empty()) return; + + if (Diagnostics.empty()) { + Diagnostics = llvm_move(pool.Diagnostics); + } else { + Diagnostics.append(pool.pool_begin(), pool.pool_end()); + } + pool.Diagnostics.clear(); + } + + typedef llvm::SmallVectorImpl<DelayedDiagnostic>::const_iterator + pool_iterator; + pool_iterator pool_begin() const { return Diagnostics.begin(); } + pool_iterator pool_end() const { return Diagnostics.end(); } + bool pool_empty() const { return Diagnostics.empty(); } +}; + } + +/// Add a diagnostic to the current delay pool. +inline void Sema::DelayedDiagnostics::add(const sema::DelayedDiagnostic &diag) { + assert(shouldDelayDiagnostics() && "trying to delay without pool"); + CurPool->add(diag); +} + + } #endif diff --git a/include/clang/Sema/Designator.h b/include/clang/Sema/Designator.h index fe01f4d..55603fe 100644 --- a/include/clang/Sema/Designator.h +++ b/include/clang/Sema/Designator.h @@ -179,18 +179,10 @@ public: /// Designation - Represent a full designation, which is a sequence of /// designators. This class is mostly a helper for InitListDesignations. class Designation { - /// InitIndex - The index of the initializer expression this is for. For - /// example, if the initializer were "{ A, .foo=B, C }" a Designation would - /// exist with InitIndex=1, because element #1 has a designation. - unsigned InitIndex; - /// Designators - The actual designators for this initializer. SmallVector<Designator, 2> Designators; - Designation(unsigned Idx) : InitIndex(Idx) {} public: - Designation() : InitIndex(4000) {} - /// AddDesignator - Add a designator to the end of this list. void AddDesignator(Designator D) { Designators.push_back(D); diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h index 0dd6887..77659be 100644 --- a/include/clang/Sema/Initialization.h +++ b/include/clang/Sema/Initialization.h @@ -15,6 +15,7 @@ #include "clang/Sema/Ownership.h" #include "clang/Sema/Overload.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/Type.h" #include "clang/AST/UnresolvedSet.h" #include "clang/Basic/SourceLocation.h" @@ -855,8 +856,8 @@ public: /// /// \param BaseType the base type to which we will be casting. /// - /// \param IsLValue true if the result of this cast will be treated as - /// an lvalue. + /// \param Category Indicates whether the result will be treated as an + /// rvalue, an xvalue, or an lvalue. void AddDerivedToBaseCastStep(QualType BaseType, ExprValueKind Category); @@ -865,9 +866,6 @@ public: /// \param BindingTemporary True if we are binding a reference to a temporary /// object (thereby extending its lifetime); false if we are binding to an /// lvalue or an lvalue treated as an rvalue. - /// - /// \param UnnecessaryCopy True if we should check for a copy - /// constructor for a completely unnecessary but void AddReferenceBindingStep(QualType T, bool BindingTemporary); /// \brief Add a new step that makes an extraneous copy of the input diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h index d334447..d2fc285 100644 --- a/include/clang/Sema/Overload.h +++ b/include/clang/Sema/Overload.h @@ -659,12 +659,25 @@ namespace clang { /// A structure used to record information about a failed /// template argument deduction. struct DeductionFailureInfo { - // A Sema::TemplateDeductionResult. - unsigned Result; + /// A Sema::TemplateDeductionResult. + unsigned Result : 8; + + /// \brief Indicates whether a diagnostic is stored in Diagnostic. + unsigned HasDiagnostic : 1; /// \brief Opaque pointer containing additional data about /// this deduction failure. void *Data; + + /// \brief A diagnostic indicating why deduction failed. + union { + void *Align; + char Diagnostic[sizeof(PartialDiagnosticAt)]; + }; + + /// \brief Retrieve the diagnostic which caused this deduction failure, + /// if any. + PartialDiagnosticAt *getSFINAEDiagnostic(); /// \brief Retrieve the template parameter this deduction failure /// refers to, if any. @@ -740,11 +753,7 @@ namespace clang { public: OverloadCandidateSet(SourceLocation Loc) : Loc(Loc), NumInlineSequences(0){} - ~OverloadCandidateSet() { - for (iterator i = begin(), e = end(); i != e; ++i) - for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii) - i->Conversions[ii].~ImplicitConversionSequence(); - } + ~OverloadCandidateSet() { clear(); } SourceLocation getLocation() const { return Loc; } diff --git a/include/clang/Sema/ParsedTemplate.h b/include/clang/Sema/ParsedTemplate.h index c1b4710..69080ad 100644 --- a/include/clang/Sema/ParsedTemplate.h +++ b/include/clang/Sema/ParsedTemplate.h @@ -58,7 +58,7 @@ namespace clang { SourceLocation TemplateLoc) : Kind(ParsedTemplateArgument::Template), Arg(Template.getAsOpaquePtr()), - Loc(TemplateLoc), SS(SS), EllipsisLoc() { } + SS(SS), Loc(TemplateLoc), EllipsisLoc() { } /// \brief Determine whether the given template argument is invalid. bool isInvalid() const { return Arg == 0; } @@ -118,13 +118,13 @@ namespace clang { /// expression), or an ActionBase::TemplateTy (for a template). void *Arg; - /// \brief the location of the template argument. - SourceLocation Loc; - /// \brief The nested-name-specifier that can accompany a template template /// argument. CXXScopeSpec SS; - + + /// \brief the location of the template argument. + SourceLocation Loc; + /// \brief The ellipsis location that can accompany a template template /// argument (turning it into a template template argument expansion). SourceLocation EllipsisLoc; diff --git a/include/clang/Sema/Scope.h b/include/clang/Sema/Scope.h index 48f5417..b78556e 100644 --- a/include/clang/Sema/Scope.h +++ b/include/clang/Sema/Scope.h @@ -71,7 +71,7 @@ public: FunctionPrototypeScope = 0x100, /// AtCatchScope - This is a scope that corresponds to the Objective-C - /// @catch statement. + /// \@catch statement. AtCatchScope = 0x200, /// ObjCMethodScope - This scope corresponds to an Objective-C method body. @@ -270,7 +270,7 @@ public: return getFlags() & Scope::FunctionPrototypeScope; } - /// isAtCatchScope - Return true if this scope is @catch. + /// isAtCatchScope - Return true if this scope is \@catch. bool isAtCatchScope() const { return getFlags() & Scope::AtCatchScope; } diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h index ceaf586..b4752f5 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/include/clang/Sema/ScopeInfo.h @@ -74,7 +74,7 @@ public: /// ScopeKind Kind; - /// \brief Whether this function contains a VLA, @try, try, C++ + /// \brief Whether this function contains a VLA, \@try, try, C++ /// initializer, or anything else that can't be jumped past. bool HasBranchProtectedScope; @@ -84,6 +84,14 @@ public: /// \brief Whether this function contains any indirect gotos. bool HasIndirectGoto; + /// A flag that is set when parsing a -dealloc method and no [super dealloc] + /// call was found yet. + bool ObjCShouldCallSuperDealloc; + + /// A flag that is set when parsing a -finalize method and no [super finalize] + /// call was found yet. + bool ObjCShouldCallSuperFinalize; + /// \brief Used to determine if errors occurred in this function or block. DiagnosticErrorTrap ErrorTrap; @@ -93,7 +101,7 @@ public: /// \brief The list of return statements that occur within the function or /// block, if there is any chance of applying the named return value - /// optimization. + /// optimization, or if we need to infer a return type. SmallVector<ReturnStmt*, 4> Returns; /// \brief The stack of currently active compound stamement scopes in the @@ -127,6 +135,8 @@ public: HasBranchProtectedScope(false), HasBranchIntoScope(false), HasIndirectGoto(false), + ObjCShouldCallSuperDealloc(false), + ObjCShouldCallSuperFinalize(false), ErrorTrap(Diag) { } virtual ~FunctionScopeInfo(); @@ -344,6 +354,9 @@ public: /// \brief Whether any of the capture expressions requires cleanups. bool ExprNeedsCleanups; + /// \brief Whether the lambda contains an unexpanded parameter pack. + bool ContainsUnexpandedParameterPack; + /// \brief Variables used to index into by-copy array captures. llvm::SmallVector<VarDecl *, 4> ArrayIndexVars; @@ -355,7 +368,7 @@ public: CXXMethodDecl *CallOperator) : CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda), CallOperator(CallOperator), NumExplicitCaptures(0), Mutable(false), - ExprNeedsCleanups(false) + ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false) { Kind = SK_Lambda; } diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index c8767b6..058e0d9 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -28,6 +28,7 @@ #include "clang/AST/ExprObjC.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExternalASTSource.h" +#include "clang/AST/LambdaMangleContext.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/NSAPI.h" #include "clang/Lex/ModuleLoader.h" @@ -36,7 +37,9 @@ #include "clang/Basic/TypeTraits.h" #include "clang/Basic/ExpressionTraits.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include <deque> @@ -167,8 +170,10 @@ namespace clang { namespace sema { class AccessedEntity; class BlockScopeInfo; + class CapturingScopeInfo; class CompoundScopeInfo; class DelayedDiagnostic; + class DelayedDiagnosticPool; class FunctionScopeInfo; class LambdaScopeInfo; class PossiblyUnreachableDiag; @@ -220,13 +225,13 @@ public: /// This is used as part of a hack to omit that class from ADL results. DeclarationName VAListTagName; - /// PackContext - Manages the stack for #pragma pack. An alignment + /// PackContext - Manages the stack for \#pragma pack. An alignment /// of 0 indicates default alignment. void *PackContext; // Really a "PragmaPackStack*" - bool MSStructPragmaOn; // True when #pragma ms_struct on + bool MSStructPragmaOn; // True when \#pragma ms_struct on - /// VisContext - Manages the stack for #pragma GCC visibility. + /// VisContext - Manages the stack for \#pragma GCC visibility. void *VisContext; // Really a "PragmaVisStack*" /// ExprNeedsCleanups - True if the current evaluation context @@ -262,10 +267,15 @@ public: /// /// This set is used to suppress redundant diagnostics. llvm::SmallPtrSet<NamedDecl *, 4> HiddenDefinitions; - + /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes. OwningPtr<CXXFieldCollector> FieldCollector; + typedef llvm::SmallSetVector<const NamedDecl*, 16> NamedDeclSetType; + + /// \brief Set containing all declared private fields that are not used. + NamedDeclSetType UnusedPrivateFields; + typedef llvm::SmallPtrSet<const CXXRecordDecl*, 8> RecordDeclSetTy; /// PureVirtualClassDiagSet - a set of class declarations which we have @@ -355,93 +365,63 @@ public: class DelayedDiagnostics; - class ParsingDeclState { - unsigned SavedStackSize; - friend class Sema::DelayedDiagnostics; - }; - - class ProcessingContextState { - unsigned SavedParsingDepth; - unsigned SavedActiveStackBase; + class DelayedDiagnosticsState { + sema::DelayedDiagnosticPool *SavedPool; friend class Sema::DelayedDiagnostics; }; + typedef DelayedDiagnosticsState ParsingDeclState; + typedef DelayedDiagnosticsState ProcessingContextState; /// A class which encapsulates the logic for delaying diagnostics /// during parsing and other processing. class DelayedDiagnostics { - /// \brief The stack of diagnostics that were delayed due to being - /// produced during the parsing of a declaration. - sema::DelayedDiagnostic *Stack; - - /// \brief The number of objects on the delayed-diagnostics stack. - unsigned StackSize; - - /// \brief The current capacity of the delayed-diagnostics stack. - unsigned StackCapacity; - - /// \brief The index of the first "active" delayed diagnostic in - /// the stack. When parsing class definitions, we ignore active - /// delayed diagnostics from the surrounding context. - unsigned ActiveStackBase; - - /// \brief The depth of the declarations we're currently parsing. - /// This gets saved and reset whenever we enter a class definition. - unsigned ParsingDepth; + /// \brief The current pool of diagnostics into which delayed + /// diagnostics should go. + sema::DelayedDiagnosticPool *CurPool; public: - DelayedDiagnostics() : Stack(0), StackSize(0), StackCapacity(0), - ActiveStackBase(0), ParsingDepth(0) {} - - ~DelayedDiagnostics() { - delete[] reinterpret_cast<char*>(Stack); - } + DelayedDiagnostics() : CurPool(0) {} /// Adds a delayed diagnostic. - void add(const sema::DelayedDiagnostic &diag); + void add(const sema::DelayedDiagnostic &diag); // in DelayedDiagnostic.h /// Determines whether diagnostics should be delayed. - bool shouldDelayDiagnostics() { return ParsingDepth > 0; } - - /// Observe that we've started parsing a declaration. Access and - /// deprecation diagnostics will be delayed; when the declaration - /// is completed, all active delayed diagnostics will be evaluated - /// in its context, and then active diagnostics stack will be - /// popped down to the saved depth. - ParsingDeclState pushParsingDecl() { - ParsingDepth++; - - ParsingDeclState state; - state.SavedStackSize = StackSize; - return state; - } - - /// Observe that we're completed parsing a declaration. - static void popParsingDecl(Sema &S, ParsingDeclState state, Decl *decl); + bool shouldDelayDiagnostics() { return CurPool != 0; } - /// Observe that we've started processing a different context, the - /// contents of which are semantically separate from the - /// declarations it may lexically appear in. This sets aside the - /// current stack of active diagnostics and starts afresh. - ProcessingContextState pushContext() { - assert(StackSize >= ActiveStackBase); + /// Returns the current delayed-diagnostics pool. + sema::DelayedDiagnosticPool *getCurrentPool() const { + return CurPool; + } - ProcessingContextState state; - state.SavedParsingDepth = ParsingDepth; - state.SavedActiveStackBase = ActiveStackBase; + /// Enter a new scope. Access and deprecation diagnostics will be + /// collected in this pool. + DelayedDiagnosticsState push(sema::DelayedDiagnosticPool &pool) { + DelayedDiagnosticsState state; + state.SavedPool = CurPool; + CurPool = &pool; + return state; + } - ActiveStackBase = StackSize; - ParsingDepth = 0; + /// Leave a delayed-diagnostic state that was previously pushed. + /// Do not emit any of the diagnostics. This is performed as part + /// of the bookkeeping of popping a pool "properly". + void popWithoutEmitting(DelayedDiagnosticsState state) { + CurPool = state.SavedPool; + } + /// Enter a new scope where access and deprecation diagnostics are + /// not delayed. + DelayedDiagnosticsState pushUndelayed() { + DelayedDiagnosticsState state; + state.SavedPool = CurPool; + CurPool = 0; return state; } - /// Observe that we've stopped processing a context. This - /// restores the previous stack of active diagnostics. - void popContext(ProcessingContextState state) { - assert(ActiveStackBase == StackSize); - assert(ParsingDepth == 0); - ActiveStackBase = state.SavedActiveStackBase; - ParsingDepth = state.SavedParsingDepth; + /// Undo a previous pushUndelayed(). + void popUndelayed(DelayedDiagnosticsState state) { + assert(CurPool == NULL); + CurPool = state.SavedPool; } } DelayedDiagnostics; @@ -452,11 +432,11 @@ public: DeclContext *SavedContext; ProcessingContextState SavedContextState; QualType SavedCXXThisTypeOverride; - + public: ContextRAII(Sema &S, DeclContext *ContextToPush) : S(S), SavedContext(S.CurContext), - SavedContextState(S.DelayedDiagnostics.pushContext()), + SavedContextState(S.DelayedDiagnostics.pushUndelayed()), SavedCXXThisTypeOverride(S.CXXThisTypeOverride) { assert(ContextToPush && "pushing null context"); @@ -466,7 +446,7 @@ public: void pop() { if (!SavedContext) return; S.CurContext = SavedContext; - S.DelayedDiagnostics.popContext(SavedContextState); + S.DelayedDiagnostics.popUndelayed(SavedContextState); S.CXXThisTypeOverride = SavedCXXThisTypeOverride; SavedContext = 0; } @@ -477,12 +457,12 @@ public: }; /// WeakUndeclaredIdentifiers - Identifiers contained in - /// #pragma weak before declared. rare. may alias another + /// \#pragma weak before declared. rare. may alias another /// identifier, declared or undeclared llvm::DenseMap<IdentifierInfo*,WeakInfo> WeakUndeclaredIdentifiers; /// ExtnameUndeclaredIdentifiers - Identifiers contained in - /// #pragma redefine_extname before declared. Used in Solaris system headers + /// \#pragma redefine_extname before declared. Used in Solaris system headers /// to define functions that occur in multiple standards to call the version /// in the currently selected standard. llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*> ExtnameUndeclaredIdentifiers; @@ -492,7 +472,7 @@ public: void LoadExternalWeakUndeclaredIdentifiers(); /// WeakTopLevelDecl - Translation-unit scoped declarations generated by - /// #pragma weak during processing of other Decls. + /// \#pragma weak during processing of other Decls. /// I couldn't figure out a clean way to generate these in-line, so /// we store them here and handle separately -- which is a hack. /// It would be best to refactor this. @@ -513,10 +493,10 @@ public: LazyDeclPtr StdBadAlloc; /// \brief The C++ "std::initializer_list" template, which is defined in - /// <initializer_list>. + /// \<initializer_list>. ClassTemplateDecl *StdInitializerList; - /// \brief The C++ "type_info" declaration, which is defined in <typeinfo>. + /// \brief The C++ "type_info" declaration, which is defined in \<typeinfo>. RecordDecl *CXXTypeInfoDecl; /// \brief The MSVC "_GUID" struct, which is defined in MSVC header files. @@ -527,16 +507,28 @@ public: /// \brief The declaration of the Objective-C NSNumber class. ObjCInterfaceDecl *NSNumberDecl; - + + /// \brief Pointer to NSNumber type (NSNumber *). + QualType NSNumberPointer; + /// \brief The Objective-C NSNumber methods used to create NSNumber literals. ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods]; - + + /// \brief The declaration of the Objective-C NSString class. + ObjCInterfaceDecl *NSStringDecl; + + /// \brief Pointer to NSString type (NSString *). + QualType NSStringPointer; + + /// \brief The declaration of the stringWithUTF8String: method. + ObjCMethodDecl *StringWithUTF8StringMethod; + /// \brief The declaration of the Objective-C NSArray class. ObjCInterfaceDecl *NSArrayDecl; /// \brief The declaration of the arrayWithObjects:count: method. ObjCMethodDecl *ArrayWithObjectsMethod; - + /// \brief The declaration of the Objective-C NSDictionary class. ObjCInterfaceDecl *NSDictionaryDecl; @@ -550,13 +542,6 @@ public: /// have been declared. bool GlobalNewDeleteDeclared; - /// A flag that is set when parsing a -dealloc method and no [super dealloc] - /// call was found yet. - bool ObjCShouldCallSuperDealloc; - /// A flag that is set when parsing a -finalize method and no [super finalize] - /// call was found yet. - bool ObjCShouldCallSuperFinalize; - /// \brief Describes how the expressions currently being parsed are /// evaluated at run-time, if at all. enum ExpressionEvaluationContext { @@ -611,10 +596,10 @@ public: llvm::SmallVector<LambdaExpr *, 2> Lambdas; /// \brief The declaration that provides context for the lambda expression - /// if the normal declaration context does not suffice, e.g., in a + /// if the normal declaration context does not suffice, e.g., in a /// default function argument. Decl *LambdaContextDecl; - + /// \brief The context information used to mangle lambda expressions /// within this context. /// @@ -629,7 +614,7 @@ public: /// \brief If we are processing a decltype type, a set of temporary binding /// expressions for which we have deferred checking the destructor. llvm::SmallVector<CXXBindTemporaryExpr*, 8> DelayedDecltypeBinds; - + ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context, unsigned NumCleanupObjects, bool ParentNeedsCleanups, @@ -638,11 +623,11 @@ public: : Context(Context), ParentNeedsCleanups(ParentNeedsCleanups), IsDecltype(IsDecltype), NumCleanupObjects(NumCleanupObjects), LambdaContextDecl(LambdaContextDecl), LambdaMangle() { } - + ~ExpressionEvaluationContextRecord() { delete LambdaMangle; } - + /// \brief Retrieve the mangling context for lambdas. LambdaMangleContext &getLambdaMangleContext() { assert(LambdaContextDecl && "Need to have a lambda context declaration"); @@ -654,17 +639,12 @@ public: /// A stack of expression evaluation contexts. SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts; - + /// SpecialMemberOverloadResult - The overloading result for a special member /// function. /// /// This is basically a wrapper around PointerIntPair. The lowest bits of the - /// integer are used to determine whether overload resolution succeeded, and - /// whether, when looking up a copy constructor or assignment operator, we - /// found a potential copy constructor/assignment operator whose first - /// parameter is const-qualified. This is used for determining parameter types - /// of other objects and is utterly meaningless on other types of special - /// members. + /// integer are used to determine whether overload resolution succeeded. class SpecialMemberOverloadResult : public llvm::FastFoldingSetNode { public: enum Kind { @@ -735,7 +715,7 @@ public: /// of selectors are "overloaded"). GlobalMethodPool MethodPool; - /// Method selectors used in a @selector expression. Used for implementation + /// Method selectors used in a \@selector expression. Used for implementation /// of -Wselector. llvm::DenseMap<Selector, SourceLocation> ReferencedSelectors; @@ -826,7 +806,8 @@ public: bool findMacroSpelling(SourceLocation &loc, StringRef name); /// \brief Get a string to suggest for zero-initialization of a type. - const char *getFixItZeroInitializerForType(QualType T) const; + std::string getFixItZeroInitializerForType(QualType T) const; + std::string getFixItZeroLiteralForType(QualType T) const; ExprResult Owned(Expr* E) { return E; } ExprResult Owned(ExprResult R) { return R; } @@ -861,9 +842,11 @@ public: /// \brief Retrieve the current lambda expression, if any. sema::LambdaScopeInfo *getCurLambda(); - /// WeakTopLevelDeclDecls - access to #pragma weak-generated Decls + /// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls SmallVector<Decl*,2> &WeakTopLevelDecls() { return WeakTopLevelDecl; } + void ActOnComment(SourceRange Comment); + //===--------------------------------------------------------------------===// // Type Analysis / Processing: SemaType.cpp. // @@ -899,7 +882,7 @@ public: TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy); TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, TypeSourceInfo *ReturnTypeInfo); - + /// \brief Package the given type and TSI into a ParsedType. ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo); DeclarationNameInfo GetNameForDeclarator(Declarator &D); @@ -936,19 +919,168 @@ public: /// in an Objective-C message declaration. Return the appropriate type. ParsedType ActOnObjCInstanceType(SourceLocation Loc); + /// \brief Abstract class used to diagnose incomplete types. + struct TypeDiagnoser { + bool Suppressed; + + TypeDiagnoser(bool Suppressed = false) : Suppressed(Suppressed) { } + + virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) = 0; + virtual ~TypeDiagnoser() {} + }; + + static int getPrintable(int I) { return I; } + static unsigned getPrintable(unsigned I) { return I; } + static bool getPrintable(bool B) { return B; } + static const char * getPrintable(const char *S) { return S; } + static StringRef getPrintable(StringRef S) { return S; } + static const std::string &getPrintable(const std::string &S) { return S; } + static const IdentifierInfo *getPrintable(const IdentifierInfo *II) { + return II; + } + static DeclarationName getPrintable(DeclarationName N) { return N; } + static QualType getPrintable(QualType T) { return T; } + static SourceRange getPrintable(SourceRange R) { return R; } + static SourceRange getPrintable(SourceLocation L) { return L; } + static SourceRange getPrintable(Expr *E) { return E->getSourceRange(); } + static SourceRange getPrintable(TypeLoc TL) { return TL.getSourceRange();} + + template<typename T1> + class BoundTypeDiagnoser1 : public TypeDiagnoser { + unsigned DiagID; + const T1 &Arg1; + + public: + BoundTypeDiagnoser1(unsigned DiagID, const T1 &Arg1) + : TypeDiagnoser(DiagID == 0), DiagID(DiagID), Arg1(Arg1) { } + virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) { + if (Suppressed) return; + S.Diag(Loc, DiagID) << getPrintable(Arg1) << T; + } + + virtual ~BoundTypeDiagnoser1() { } + }; + + template<typename T1, typename T2> + class BoundTypeDiagnoser2 : public TypeDiagnoser { + unsigned DiagID; + const T1 &Arg1; + const T2 &Arg2; + + public: + BoundTypeDiagnoser2(unsigned DiagID, const T1 &Arg1, + const T2 &Arg2) + : TypeDiagnoser(DiagID == 0), DiagID(DiagID), Arg1(Arg1), + Arg2(Arg2) { } + + virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) { + if (Suppressed) return; + S.Diag(Loc, DiagID) << getPrintable(Arg1) << getPrintable(Arg2) << T; + } + + virtual ~BoundTypeDiagnoser2() { } + }; + + template<typename T1, typename T2, typename T3> + class BoundTypeDiagnoser3 : public TypeDiagnoser { + unsigned DiagID; + const T1 &Arg1; + const T2 &Arg2; + const T3 &Arg3; + + public: + BoundTypeDiagnoser3(unsigned DiagID, const T1 &Arg1, + const T2 &Arg2, const T3 &Arg3) + : TypeDiagnoser(DiagID == 0), DiagID(DiagID), Arg1(Arg1), + Arg2(Arg2), Arg3(Arg3) { } + + virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) { + if (Suppressed) return; + S.Diag(Loc, DiagID) + << getPrintable(Arg1) << getPrintable(Arg2) << getPrintable(Arg3) << T; + } + + virtual ~BoundTypeDiagnoser3() { } + }; + bool RequireCompleteType(SourceLocation Loc, QualType T, - const PartialDiagnostic &PD, - std::pair<SourceLocation, PartialDiagnostic> Note); - bool RequireCompleteType(SourceLocation Loc, QualType T, - const PartialDiagnostic &PD); + TypeDiagnoser &Diagnoser); bool RequireCompleteType(SourceLocation Loc, QualType T, unsigned DiagID); - bool RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD, - std::pair<SourceLocation, - PartialDiagnostic> Note); + + template<typename T1> + bool RequireCompleteType(SourceLocation Loc, QualType T, + unsigned DiagID, const T1 &Arg1) { + BoundTypeDiagnoser1<T1> Diagnoser(DiagID, Arg1); + return RequireCompleteType(Loc, T, Diagnoser); + } + + template<typename T1, typename T2> + bool RequireCompleteType(SourceLocation Loc, QualType T, + unsigned DiagID, const T1 &Arg1, const T2 &Arg2) { + BoundTypeDiagnoser2<T1, T2> Diagnoser(DiagID, Arg1, Arg2); + return RequireCompleteType(Loc, T, Diagnoser); + } + + template<typename T1, typename T2, typename T3> + bool RequireCompleteType(SourceLocation Loc, QualType T, + unsigned DiagID, const T1 &Arg1, const T2 &Arg2, + const T3 &Arg3) { + BoundTypeDiagnoser3<T1, T2, T3> Diagnoser(DiagID, Arg1, Arg2, + Arg3); + return RequireCompleteType(Loc, T, Diagnoser); + } + + bool RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser); + bool RequireCompleteExprType(Expr *E, unsigned DiagID); + + template<typename T1> + bool RequireCompleteExprType(Expr *E, unsigned DiagID, const T1 &Arg1) { + BoundTypeDiagnoser1<T1> Diagnoser(DiagID, Arg1); + return RequireCompleteExprType(E, Diagnoser); + } + + template<typename T1, typename T2> + bool RequireCompleteExprType(Expr *E, unsigned DiagID, const T1 &Arg1, + const T2 &Arg2) { + BoundTypeDiagnoser2<T1, T2> Diagnoser(DiagID, Arg1, Arg2); + return RequireCompleteExprType(E, Diagnoser); + } + + template<typename T1, typename T2, typename T3> + bool RequireCompleteExprType(Expr *E, unsigned DiagID, const T1 &Arg1, + const T2 &Arg2, const T3 &Arg3) { + BoundTypeDiagnoser3<T1, T2, T3> Diagnoser(DiagID, Arg1, Arg2, + Arg3); + return RequireCompleteExprType(E, Diagnoser); + } bool RequireLiteralType(SourceLocation Loc, QualType T, - const PartialDiagnostic &PD); + TypeDiagnoser &Diagnoser); + bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID); + + template<typename T1> + bool RequireLiteralType(SourceLocation Loc, QualType T, + unsigned DiagID, const T1 &Arg1) { + BoundTypeDiagnoser1<T1> Diagnoser(DiagID, Arg1); + return RequireLiteralType(Loc, T, Diagnoser); + } + + template<typename T1, typename T2> + bool RequireLiteralType(SourceLocation Loc, QualType T, + unsigned DiagID, const T1 &Arg1, const T2 &Arg2) { + BoundTypeDiagnoser2<T1, T2> Diagnoser(DiagID, Arg1, Arg2); + return RequireLiteralType(Loc, T, Diagnoser); + } + + template<typename T1, typename T2, typename T3> + bool RequireLiteralType(SourceLocation Loc, QualType T, + unsigned DiagID, const T1 &Arg1, const T2 &Arg2, + const T3 &Arg3) { + BoundTypeDiagnoser3<T1, T2, T3> Diagnoser(DiagID, Arg1, Arg2, + Arg3); + return RequireLiteralType(Loc, T, Diagnoser); + } QualType getElaboratedType(ElaboratedTypeKeyword Keyword, const CXXScopeSpec &SS, QualType T); @@ -978,6 +1110,8 @@ public: void DiagnoseUseOfUnimplementedSelectors(); + bool isSimpleTypeSpecifier(tok::TokenKind Kind) const; + ParsedType getTypeName(IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS = 0, bool isClassName = false, @@ -988,7 +1122,7 @@ public: IdentifierInfo **CorrectedII = 0); TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S); bool isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S); - bool DiagnoseUnknownTypeName(const IdentifierInfo &II, + bool DiagnoseUnknownTypeName(IdentifierInfo *&II, SourceLocation IILoc, Scope *S, CXXScopeSpec *SS, @@ -1173,12 +1307,21 @@ public: unsigned NumDecls); DeclGroupPtrTy BuildDeclaratorGroup(Decl **Group, unsigned NumDecls, bool TypeMayContainAuto = true); + + /// Should be called on all declarations that might have attached + /// documentation comments. + void ActOnDocumentableDecl(Decl *D); + void ActOnDocumentableDecls(Decl **Group, unsigned NumDecls); + void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, SourceLocation LocAfterDecls); void CheckForFunctionRedefinition(FunctionDecl *FD); Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D); Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D); void ActOnStartOfObjCMethodDef(Scope *S, Decl *D); + bool isObjCMethodDecl(Decl *D) { + return D && isa<ObjCMethodDecl>(D); + } void computeNRVO(Stmt *Body, sema::FunctionScopeInfo *Scope); Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body); @@ -1213,7 +1356,7 @@ public: /// \param ImportLoc The location of the 'import' keyword. /// /// \param Path The module access path. - DeclResult ActOnModuleImport(SourceLocation AtLoc, SourceLocation ImportLoc, + DeclResult ActOnModuleImport(SourceLocation AtLoc, SourceLocation ImportLoc, ModuleIdPath Path); /// \brief Retrieve a suitable printing policy. @@ -1286,13 +1429,15 @@ public: Declarator &D, Expr *BitfieldWidth); FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart, - Declarator &D, Expr *BitfieldWidth, bool HasInit, + Declarator &D, Expr *BitfieldWidth, + InClassInitStyle InitStyle, AccessSpecifier AS); FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T, TypeSourceInfo *TInfo, RecordDecl *Record, SourceLocation Loc, - bool Mutable, Expr *BitfieldWidth, bool HasInit, + bool Mutable, Expr *BitfieldWidth, + InClassInitStyle InitStyle, SourceLocation TSSL, AccessSpecifier AS, NamedDecl *PrevDecl, Declarator *D = 0); @@ -1432,6 +1577,24 @@ public: TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T, TypeSourceInfo *TInfo); bool isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New); + + /// Attribute merging methods. Return true if a new attribute was added. + AvailabilityAttr *mergeAvailabilityAttr(Decl *D, SourceRange Range, + IdentifierInfo *Platform, + VersionTuple Introduced, + VersionTuple Deprecated, + VersionTuple Obsoleted, + bool IsUnavailable, + StringRef Message); + VisibilityAttr *mergeVisibilityAttr(Decl *D, SourceRange Range, + VisibilityAttr::VisibilityType Vis); + DLLImportAttr *mergeDLLImportAttr(Decl *D, SourceRange Range); + DLLExportAttr *mergeDLLExportAttr(Decl *D, SourceRange Range); + FormatAttr *mergeFormatAttr(Decl *D, SourceRange Range, StringRef Format, + int FormatIdx, int FirstArg); + SectionAttr *mergeSectionAttr(Decl *D, SourceRange Range, StringRef Name); + bool mergeDeclAttribute(Decl *New, InheritableAttr *Attr); + void mergeDeclAttributes(Decl *New, Decl *Old, bool MergeDeprecation = true); void MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls); bool MergeFunctionDecl(FunctionDecl *New, Decl *Old, Scope *S); @@ -1558,16 +1721,59 @@ public: ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, llvm::APSInt &Value, CCEKind CCE); + /// \brief Abstract base class used to diagnose problems that occur while + /// trying to convert an expression to integral or enumeration type. + class ICEConvertDiagnoser { + public: + bool Suppress; + bool SuppressConversion; + + ICEConvertDiagnoser(bool Suppress = false, + bool SuppressConversion = false) + : Suppress(Suppress), SuppressConversion(SuppressConversion) { } + + /// \brief Emits a diagnostic complaining that the expression does not have + /// integral or enumeration type. + virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, + QualType T) = 0; + + /// \brief Emits a diagnostic when the expression has incomplete class type. + virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc, + QualType T) = 0; + + /// \brief Emits a diagnostic when the only matching conversion function + /// is explicit. + virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc, + QualType T, + QualType ConvTy) = 0; + + /// \brief Emits a note for the explicit conversion function. + virtual DiagnosticBuilder + noteExplicitConv(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0; + + /// \brief Emits a diagnostic when there are multiple possible conversion + /// functions. + virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc, + QualType T) = 0; + + /// \brief Emits a note for one of the candidate conversions. + virtual DiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv, + QualType ConvTy) = 0; + + /// \brief Emits a diagnostic when we picked a conversion function + /// (for cases when we are not allowed to pick a conversion function). + virtual DiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc, + QualType T, + QualType ConvTy) = 0; + + virtual ~ICEConvertDiagnoser() {} + }; + ExprResult ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *FromE, - const PartialDiagnostic &NotIntDiag, - const PartialDiagnostic &IncompleteDiag, - const PartialDiagnostic &ExplicitConvDiag, - const PartialDiagnostic &ExplicitConvNote, - const PartialDiagnostic &AmbigDiag, - const PartialDiagnostic &AmbigNote, - const PartialDiagnostic &ConvDiag, + ICEConvertDiagnoser &Diagnoser, bool AllowScopedEnumerations); + enum ObjCSubscriptKind { OS_Array, OS_Dictionary, @@ -1910,14 +2116,16 @@ public: unsigned Quals); CXXMethodDecl *LookupCopyingAssignment(CXXRecordDecl *Class, unsigned Quals, bool RValueThis, unsigned ThisQuals); - CXXConstructorDecl *LookupMovingConstructor(CXXRecordDecl *Class); - CXXMethodDecl *LookupMovingAssignment(CXXRecordDecl *Class, bool RValueThis, - unsigned ThisQuals); + CXXConstructorDecl *LookupMovingConstructor(CXXRecordDecl *Class, + unsigned Quals); + CXXMethodDecl *LookupMovingAssignment(CXXRecordDecl *Class, unsigned Quals, + bool RValueThis, unsigned ThisQuals); CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class); LiteralOperatorLookupResult LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef<QualType> ArgTys, bool AllowRawAndTemplate); + bool isKnownName(StringRef name); void ArgumentDependentLookup(DeclarationName Name, bool Operator, SourceLocation Loc, @@ -2000,13 +2208,11 @@ public: bool isPropertyReadonly(ObjCPropertyDecl *PropertyDecl, ObjCInterfaceDecl *IDecl); - typedef llvm::DenseSet<Selector, llvm::DenseMapInfo<Selector> > SelectorSet; + typedef llvm::SmallPtrSet<Selector, 8> SelectorSet; typedef llvm::DenseMap<Selector, ObjCMethodDecl*> ProtocolsMethodsMap; /// CheckProtocolMethodDefs - This routine checks unimplemented /// methods declared in protocol, and those referenced by it. - /// \param IDecl - Used for checking for methods which may have been - /// inherited. void CheckProtocolMethodDefs(SourceLocation ImpLoc, ObjCProtocolDecl *PDecl, bool& IncompleteImpl, @@ -2021,7 +2227,7 @@ public: SourceLocation Loc); /// ImplMethodsVsClassMethods - This is main routine to warn if any method - /// remains unimplemented in the class or category @implementation. + /// remains unimplemented in the class or category \@implementation. void ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl, ObjCContainerDecl* IDecl, bool IncompleteImpl = false); @@ -2033,7 +2239,7 @@ public: const SelectorSet &InsMap); /// DefaultSynthesizeProperties - This routine default synthesizes all - /// properties which must be synthesized in class's @implementation. + /// properties which must be synthesized in the class's \@implementation. void DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl, ObjCInterfaceDecl *IDecl); void DefaultSynthesizeProperties(Scope *S, Decl *D); @@ -2050,8 +2256,8 @@ public: ObjCPropertyDecl *LookupPropertyDecl(const ObjCContainerDecl *CDecl, IdentifierInfo *II); - /// Called by ActOnProperty to handle @property declarations in - //// class extensions. + /// Called by ActOnProperty to handle \@property declarations in + /// class extensions. Decl *HandlePropertyInClassExtension(Scope *S, SourceLocation AtLoc, SourceLocation LParenLoc, @@ -2067,7 +2273,7 @@ public: tok::ObjCKeywordKind MethodImplKind); /// Called by ActOnProperty and HandlePropertyInClassExtension to - /// handle creating the ObjcPropertyDecl for a category or @interface. + /// handle creating the ObjcPropertyDecl for a category or \@interface. ObjCPropertyDecl *CreatePropertyDecl(Scope *S, ObjCContainerDecl *CDecl, SourceLocation AtLoc, @@ -2123,7 +2329,7 @@ public: /// \brief Add the given method to the list of globally-known methods. void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method); - + private: /// AddMethodToGlobalPool - Add an instance or factory method to the global /// pool. See descriptoin of AddInstanceMethodToGlobalPool. @@ -2213,7 +2419,10 @@ public: }; FullExprArg MakeFullExpr(Expr *Arg) { - return FullExprArg(ActOnFinishFullExpr(Arg).release()); + return MakeFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation()); + } + FullExprArg MakeFullExpr(Expr *Arg, SourceLocation CC) { + return FullExprArg(ActOnFinishFullExpr(Arg, CC).release()); } StmtResult ActOnExprStmt(FullExprArg Expr); @@ -2258,7 +2467,8 @@ public: StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl, SourceLocation ColonLoc, Stmt *SubStmt); - StmtResult ActOnAttributedStmt(SourceLocation AttrLoc, const AttrVec &Attrs, + StmtResult ActOnAttributedStmt(SourceLocation AttrLoc, + ArrayRef<const Attr*> Attrs, Stmt *SubStmt); StmtResult ActOnIfStmt(SourceLocation IfLoc, @@ -2285,12 +2495,14 @@ public: FullExprArg Third, SourceLocation RParenLoc, Stmt *Body); - ExprResult ActOnObjCForCollectionOperand(SourceLocation forLoc, + ExprResult CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection); StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc, SourceLocation LParenLoc, - Stmt *First, Expr *Second, - SourceLocation RParenLoc, Stmt *Body); + Stmt *First, Expr *collection, + SourceLocation RParenLoc); + StmtResult FinishObjCForCollectionStmt(Stmt *ForCollection, Stmt *Body); + StmtResult ActOnCXXForRangeStmt(SourceLocation ForLoc, SourceLocation LParenLoc, Stmt *LoopVar, SourceLocation ColonLoc, Expr *Collection, @@ -2329,6 +2541,10 @@ public: SourceLocation RParenLoc, bool MSAsm = false); + StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, + ArrayRef<Token> AsmToks, + ArrayRef<unsigned> LineEnds, + SourceLocation EndLoc); VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType, SourceLocation StartLoc, @@ -2408,21 +2624,21 @@ public: void DiagnoseEmptyLoopBody(const Stmt *S, const Stmt *PossibleBody); - ParsingDeclState PushParsingDeclaration() { - return DelayedDiagnostics.pushParsingDecl(); - } - void PopParsingDeclaration(ParsingDeclState state, Decl *decl) { - DelayedDiagnostics::popParsingDecl(*this, state, decl); + ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool) { + return DelayedDiagnostics.push(pool); } + void PopParsingDeclaration(ParsingDeclState state, Decl *decl); typedef ProcessingContextState ParsingClassState; ParsingClassState PushParsingClass() { - return DelayedDiagnostics.pushContext(); + return DelayedDiagnostics.pushUndelayed(); } void PopParsingClass(ParsingClassState state) { - DelayedDiagnostics.popContext(state); + DelayedDiagnostics.popUndelayed(state); } + void redelayDiagnostics(sema::DelayedDiagnosticPool &pool); + void EmitDeprecationWarning(NamedDecl *D, StringRef Message, SourceLocation Loc, const ObjCInterfaceDecl *UnknownObjCClass=0); @@ -2484,13 +2700,13 @@ public: /// /// \param Loc The location at which the capture occurs. /// - /// \param Kind The kind of capture, which may be implicit (for either a + /// \param Kind The kind of capture, which may be implicit (for either a /// block or a lambda), or explicit by-value or by-reference (for a lambda). /// /// \param EllipsisLoc The location of the ellipsis, if one is provided in /// an explicit lambda capture. /// - /// \param BuildAndDiagnose Whether we are actually supposed to add the + /// \param BuildAndDiagnose Whether we are actually supposed to add the /// captures or diagnose errors. If false, this routine merely check whether /// the capture can occur without performing the capture itself or complaining /// if the variable cannot be captured. @@ -2499,14 +2715,14 @@ public: /// this variable in the innermost block or lambda. Only valid when the /// variable can be captured. /// - /// \param DeclRefType Will be set to the type of a refernce to the capture - /// from within the current scope. Only valid when the variable can be + /// \param DeclRefType Will be set to the type of a reference to the capture + /// from within the current scope. Only valid when the variable can be /// captured. /// /// \returns true if an error occurred (i.e., the variable cannot be /// captured) and false if the capture succeeded. bool tryCaptureVariable(VarDecl *Var, SourceLocation Loc, TryCaptureKind Kind, - SourceLocation EllipsisLoc, bool BuildAndDiagnose, + SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType, QualType &DeclRefType); @@ -2514,13 +2730,13 @@ public: bool tryCaptureVariable(VarDecl *Var, SourceLocation Loc, TryCaptureKind Kind = TryCapture_Implicit, SourceLocation EllipsisLoc = SourceLocation()); - + /// \brief Given a variable, determine the type that a reference to that /// variable will have in the given scope. QualType getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc); - + void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T); - void MarkDeclarationsReferencedInExpr(Expr *E, + void MarkDeclarationsReferencedInExpr(Expr *E, bool SkipLocalVariables = false); /// \brief Try to recover by turning the given expression into a @@ -2537,10 +2753,10 @@ public: /// \brief Conditionally issue a diagnostic based on the current /// evaluation context. /// - /// \param stmt - If stmt is non-null, delay reporting the diagnostic until - /// the function body is parsed, and then do a basic reachability analysis to - /// determine if the statement is reachable. If it is unreachable, the - /// diagnostic will not be emitted. + /// \param Statement If Statement is non-null, delay reporting the + /// diagnostic until the function body is parsed, and then do a basic + /// reachability analysis to determine if the statement is reachable. + /// If it is unreachable, the diagnostic will not be emitted. bool DiagRuntimeBehavior(SourceLocation Loc, const Stmt *Statement, const PartialDiagnostic &PD); @@ -2696,6 +2912,18 @@ public: const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs); + // This struct is for use by ActOnMemberAccess to allow + // BuildMemberReferenceExpr to be able to reinvoke ActOnMemberAccess after + // changing the access operator from a '.' to a '->' (to see if that is the + // change needed to fix an error about an unknown member, e.g. when the class + // defines a custom operator->). + struct ActOnMemberAccessExtraArgs { + Scope *S; + UnqualifiedId &Id; + Decl *ObjCImpDecl; + bool HasTrailingLParen; + }; + ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow, const CXXScopeSpec &SS, @@ -2703,7 +2931,8 @@ public: NamedDecl *FirstQualifierInScope, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs, - bool SuppressQualifierCheck = false); + bool SuppressQualifierCheck = false, + ActOnMemberAccessExtraArgs *ExtraArgs = 0); ExprResult PerformMemberExprBaseConversion(Expr *Base, bool IsArrow); ExprResult LookupMemberExpr(LookupResult &R, ExprResult &Base, @@ -2901,7 +3130,8 @@ public: /// ActOnBlockArguments - This callback allows processing of block arguments. /// If there are no arguments, this is still invoked. - void ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope); + void ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo, + Scope *CurScope); /// ActOnBlockError - If there is an error parsing a block, this callback /// is invoked to pop the information about the block from the action impl. @@ -3010,7 +3240,7 @@ public: TypeResult Type); /// InitializeVarWithConstructor - Creates an CXXConstructExpr - /// and sets it as the initializer for the the passed in VarDecl. + /// and sets it as the initializer for the passed in VarDecl. bool InitializeVarWithConstructor(VarDecl *VD, CXXConstructorDecl *Constructor, MultiExprArg Exprs, @@ -3075,7 +3305,7 @@ public: public: explicit ImplicitExceptionSpecification(Sema &Self) : Self(&Self), ComputedEST(EST_BasicNoexcept) { - if (!Self.Context.getLangOpts().CPlusPlus0x) + if (!Self.getLangOpts().CPlusPlus0x) ComputedEST = EST_DynamicNone; } @@ -3098,17 +3328,16 @@ public: /// \brief Integrate an invoked expression into the collected data. void CalledExpr(Expr *E); - /// \brief Specify that the exception specification can't be detemined yet. - void SetDelayed() { - ClearExceptions(); - ComputedEST = EST_Delayed; - } - - FunctionProtoType::ExtProtoInfo getEPI() const { - FunctionProtoType::ExtProtoInfo EPI; + /// \brief Overwrite an EPI's exception specification with this + /// computed exception specification. + void getEPI(FunctionProtoType::ExtProtoInfo &EPI) const { EPI.ExceptionSpecType = getExceptionSpecType(); EPI.NumExceptions = size(); EPI.Exceptions = data(); + } + FunctionProtoType::ExtProtoInfo getEPI() const { + FunctionProtoType::ExtProtoInfo EPI; + getEPI(EPI); return EPI; } }; @@ -3116,34 +3345,39 @@ public: /// \brief Determine what sort of exception specification a defaulted /// copy constructor of a class will have. ImplicitExceptionSpecification - ComputeDefaultedDefaultCtorExceptionSpec(CXXRecordDecl *ClassDecl); + ComputeDefaultedDefaultCtorExceptionSpec(SourceLocation Loc, + CXXMethodDecl *MD); /// \brief Determine what sort of exception specification a defaulted /// default constructor of a class will have, and whether the parameter /// will be const. - std::pair<ImplicitExceptionSpecification, bool> - ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl); + ImplicitExceptionSpecification + ComputeDefaultedCopyCtorExceptionSpec(CXXMethodDecl *MD); /// \brief Determine what sort of exception specification a defautled /// copy assignment operator of a class will have, and whether the /// parameter will be const. - std::pair<ImplicitExceptionSpecification, bool> - ComputeDefaultedCopyAssignmentExceptionSpecAndConst(CXXRecordDecl *ClassDecl); + ImplicitExceptionSpecification + ComputeDefaultedCopyAssignmentExceptionSpec(CXXMethodDecl *MD); /// \brief Determine what sort of exception specification a defaulted move /// constructor of a class will have. ImplicitExceptionSpecification - ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl); + ComputeDefaultedMoveCtorExceptionSpec(CXXMethodDecl *MD); /// \brief Determine what sort of exception specification a defaulted move /// assignment operator of a class will have. ImplicitExceptionSpecification - ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl *ClassDecl); + ComputeDefaultedMoveAssignmentExceptionSpec(CXXMethodDecl *MD); /// \brief Determine what sort of exception specification a defaulted /// destructor of a class will have. ImplicitExceptionSpecification - ComputeDefaultedDtorExceptionSpec(CXXRecordDecl *ClassDecl); + ComputeDefaultedDtorExceptionSpec(CXXMethodDecl *MD); + + /// \brief Evaluate the implicit exception specification for a defaulted + /// special member function. + void EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD); /// \brief Check the given exception-specification and update the /// extended prototype information with the results. @@ -3191,8 +3425,7 @@ public: /// C++11 says that user-defined destructors with no exception spec get one /// that looks as if the destructor was implicitly declared. void AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, - CXXDestructorDecl *Destructor, - bool WasDelayed = false); + CXXDestructorDecl *Destructor); /// \brief Declare all inherited constructors for the given class. /// @@ -3259,7 +3492,7 @@ public: /// \brief Determine whether the given function is an implicitly-deleted /// special member function. bool isImplicitlyDeleted(FunctionDecl *FD); - + /// \brief Check whether 'this' shows up in the type of a static member /// function after the (naturally empty) cv-qualifier-seq would be. /// @@ -3275,7 +3508,7 @@ public: /// /// \returns true if an error occurred. bool checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method); - + /// MaybeBindToTemporary - If the passed in expression has a record type with /// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise /// it simply returns the passed in expression. @@ -3352,34 +3585,32 @@ public: /// \brief Try to retrieve the type of the 'this' pointer. /// - /// \param Capture If true, capture 'this' in this context. - /// /// \returns The type of 'this', if possible. Otherwise, returns a NULL type. QualType getCurrentThisType(); - /// \brief When non-NULL, the C++ 'this' expression is allowed despite the + /// \brief When non-NULL, the C++ 'this' expression is allowed despite the /// current context not being a non-static member function. In such cases, /// this provides the type used for 'this'. QualType CXXThisTypeOverride; - + /// \brief RAII object used to temporarily allow the C++ 'this' expression /// to be used, with the given qualifiers on the current class type. class CXXThisScopeRAII { Sema &S; QualType OldCXXThisTypeOverride; bool Enabled; - + public: /// \brief Introduce a new scope where 'this' may be allowed (when enabled), - /// using the given declaration (which is either a class template or a + /// using the given declaration (which is either a class template or a /// class) along with the given qualifiers. /// along with the qualifiers placed on '*this'. - CXXThisScopeRAII(Sema &S, Decl *ContextDecl, unsigned CXXThisTypeQuals, + CXXThisScopeRAII(Sema &S, Decl *ContextDecl, unsigned CXXThisTypeQuals, bool Enabled = true); - + ~CXXThisScopeRAII(); }; - + /// \brief Make sure the value of 'this' is actually available in the current /// context, if it is a potentially evaluated context. /// @@ -3390,14 +3621,14 @@ public: void CheckCXXThisCapture(SourceLocation Loc, bool Explicit = false); /// \brief Determine whether the given type is the type of *this that is used - /// outside of the body of a member function for a type that is currently + /// outside of the body of a member function for a type that is currently /// being defined. bool isThisOutsideMemberFunctionBody(QualType BaseType); - + /// ActOnCXXBoolLiteral - Parse {true,false} literals. ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind); - - + + /// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals. ExprResult ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind); @@ -3513,7 +3744,7 @@ public: ExprResult BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc, ArrayRef<TypeSourceInfo *> Args, SourceLocation RParenLoc); - + /// ActOnArrayTypeTrait - Parsed one of the bianry type trait support /// pseudo-functions. ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT, @@ -3572,7 +3803,7 @@ public: ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, - SourceLocation TildeLoc, + SourceLocation TildeLoc, const DeclSpec& DS, bool HasTrailingLParen); @@ -3583,7 +3814,11 @@ public: Stmt *MaybeCreateStmtWithCleanups(Stmt *SubStmt); ExprResult MaybeCreateExprWithCleanups(ExprResult SubExpr); - ExprResult ActOnFinishFullExpr(Expr *Expr); + ExprResult ActOnFinishFullExpr(Expr *Expr) { + return ActOnFinishFullExpr(Expr, Expr ? Expr->getExprLoc() + : SourceLocation()); + } + ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC); StmtResult ActOnFinishFullStmt(Stmt *Stmt); // Marks SS invalid if it represents an incomplete type. @@ -3660,7 +3895,7 @@ public: ExprResult ActOnDecltypeExpression(Expr *E); bool ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS, - const DeclSpec &DS, + const DeclSpec &DS, SourceLocation ColonColonLoc); bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, @@ -3681,7 +3916,7 @@ public: /// including this new type). /// /// \param TemplateKWLoc the location of the 'template' keyword, if any. - /// \param TemplateName The template name. + /// \param TemplateName the template name. /// \param TemplateNameLoc The location of the template name. /// \param LAngleLoc The location of the opening angle bracket ('<'). /// \param TemplateArgs The template arguments. @@ -3696,7 +3931,7 @@ public: bool ActOnCXXNestedNameSpecifier(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, - TemplateTy Template, + TemplateTy TemplateName, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, @@ -3759,17 +3994,14 @@ public: /// \brief Create a new lambda closure type. CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange, bool KnownDependent = false); - + /// \brief Start the definition of a lambda expression. CXXMethodDecl *startLambdaDefinition(CXXRecordDecl *Class, SourceRange IntroducerRange, TypeSourceInfo *MethodType, SourceLocation EndLoc, - llvm::ArrayRef<ParmVarDecl *> Params, - llvm::Optional<unsigned> ManglingNumber - = llvm::Optional<unsigned>(), - Decl *ContextDecl = 0); - + llvm::ArrayRef<ParmVarDecl *> Params); + /// \brief Introduce the scope for a lambda expression. sema::LambdaScopeInfo *enterLambdaScope(CXXMethodDecl *CallOperator, SourceRange IntroducerRange, @@ -3777,16 +4009,20 @@ public: bool ExplicitParams, bool ExplicitResultType, bool Mutable); - + /// \brief Note that we have finished the explicit captures for the /// given lambda. void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI); - + /// \brief Introduce the lambda parameters into scope. void addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope); - + + /// \brief Deduce a block or lambda's return type based on the return + /// statements present in the body. + void deduceClosureReturnType(sema::CapturingScopeInfo &CSI); + /// ActOnStartOfLambdaDefinition - This is called just before we start - /// parsing the body of a lambda; it analyzes the explicit captures and + /// parsing the body of a lambda; it analyzes the explicit captures and /// arguments, and sets up various data-structures for the body of the /// lambda. void ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, @@ -3800,10 +4036,10 @@ public: /// ActOnLambdaExpr - This is called when the body of a lambda expression /// was successfully completed. ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, - Scope *CurScope, + Scope *CurScope, bool IsInstantiation = false); - /// \brief Define the "body" of the conversion from a lambda object to a + /// \brief Define the "body" of the conversion from a lambda object to a /// function pointer. /// /// This routine doesn't actually define a sensible body; rather, it fills @@ -3813,7 +4049,7 @@ public: void DefineImplicitLambdaToFunctionPointerConversion( SourceLocation CurrentLoc, CXXConversionDecl *Conv); - /// \brief Define the "body" of the conversion from a lambda object to a + /// \brief Define the "body" of the conversion from a lambda object to a /// block pointer. /// /// This routine doesn't actually define a sensible body; rather, it fills @@ -3832,26 +4068,33 @@ public: ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs, Expr **Strings, unsigned NumStrings); - + ExprResult BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S); - - /// BuildObjCNumericLiteral - builds an ObjCNumericLiteral AST node for the + + /// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the /// numeric literal expression. Type of the expression will be "NSNumber *" /// or "id" if NSNumber is unavailable. ExprResult BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number); ExprResult ActOnObjCBoolLiteral(SourceLocation AtLoc, SourceLocation ValueLoc, bool Value); ExprResult BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements); - + + /// BuildObjCBoxedExpr - builds an ObjCBoxedExpr AST node for the + /// '@' prefixed parenthesized expression. The type of the expression will + /// either be "NSNumber *" or "NSString *" depending on the type of + /// ValueType, which is allowed to be a built-in numeric type or + /// "char *" or "const char *". + ExprResult BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr); + ExprResult BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr, Expr *IndexExpr, ObjCMethodDecl *getterMethod, ObjCMethodDecl *setterMethod); - - ExprResult BuildObjCDictionaryLiteral(SourceRange SR, + + ExprResult BuildObjCDictionaryLiteral(SourceRange SR, ObjCDictionaryElement *Elements, unsigned NumElements); - + ExprResult BuildObjCEncodeExpression(SourceLocation AtLoc, TypeSourceInfo *EncodedTypeInfo, SourceLocation RParenLoc); @@ -3865,18 +4108,19 @@ public: ParsedType Ty, SourceLocation RParenLoc); - // ParseObjCSelectorExpression - Build selector expression for @selector + /// ParseObjCSelectorExpression - Build selector expression for \@selector ExprResult ParseObjCSelectorExpression(Selector Sel, SourceLocation AtLoc, SourceLocation SelLoc, SourceLocation LParenLoc, SourceLocation RParenLoc); - // ParseObjCProtocolExpression - Build protocol expression for @protocol + /// ParseObjCProtocolExpression - Build protocol expression for \@protocol ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName, SourceLocation AtLoc, SourceLocation ProtoLoc, SourceLocation LParenLoc, + SourceLocation ProtoIdLoc, SourceLocation RParenLoc); //===--------------------------------------------------------------------===// @@ -3907,7 +4151,7 @@ public: Declarator &D, MultiTemplateParamsArg TemplateParameterLists, Expr *BitfieldWidth, const VirtSpecifiers &VS, - bool HasDeferredInit); + InClassInitStyle InitStyle); void ActOnCXXInClassMemberInitializer(Decl *VarDecl, SourceLocation EqualLoc, Expr *Init); @@ -4004,6 +4248,11 @@ public: void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class, bool DefinitionRequired = false); + /// \brief Mark the exception specifications of all virtual member functions + /// in the given class as needed. + void MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc, + const CXXRecordDecl *RD); + /// MarkVirtualMembersReferenced - Will mark all members of the given /// CXXRecordDecl referenced. void MarkVirtualMembersReferenced(SourceLocation Loc, @@ -4047,6 +4296,11 @@ public: Expr *AssertExpr, Expr *AssertMessageExpr, SourceLocation RParenLoc); + Decl *BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc, + Expr *AssertExpr, + StringLiteral *AssertMessageExpr, + SourceLocation RParenLoc, + bool Failed); FriendDecl *CheckFriendTypeDecl(SourceLocation Loc, SourceLocation FriendLoc, @@ -4067,12 +4321,7 @@ public: Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion); void CheckExplicitlyDefaultedMethods(CXXRecordDecl *Record); - void CheckExplicitlyDefaultedDefaultConstructor(CXXConstructorDecl *Ctor); - void CheckExplicitlyDefaultedCopyConstructor(CXXConstructorDecl *Ctor); - void CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *Method); - void CheckExplicitlyDefaultedMoveConstructor(CXXConstructorDecl *Ctor); - void CheckExplicitlyDefaultedMoveAssignment(CXXMethodDecl *Method); - void CheckExplicitlyDefaultedDestructor(CXXDestructorDecl *Dtor); + void CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD); //===--------------------------------------------------------------------===// // C++ Derived Classes @@ -4130,12 +4379,12 @@ public: bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange); - /// CheckOverrideControl - Check C++0x override control semantics. - void CheckOverrideControl(const Decl *D); + /// CheckOverrideControl - Check C++11 override control semantics. + void CheckOverrideControl(Decl *D); /// CheckForFunctionMarkedFinal - Checks whether a virtual member function /// overrides a virtual member function marked 'final', according to - /// C++0x [class.virtual]p3. + /// C++11 [class.virtual]p4. bool CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New, const CXXMethodDecl *Old); @@ -4178,9 +4427,7 @@ public: CXXDestructorDecl *Dtor, const PartialDiagnostic &PDiag, QualType objectType = QualType()); - AccessResult CheckDirectMemberAccess(SourceLocation Loc, - NamedDecl *D, - const PartialDiagnostic &PDiag); + AccessResult CheckFriendAccess(NamedDecl *D); AccessResult CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr, Expr *ArgExpr, @@ -4206,36 +4453,10 @@ public: void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx); - /// A flag to suppress access checking. - bool SuppressAccessChecking; - /// \brief When true, access checking violations are treated as SFINAE /// failures rather than hard errors. bool AccessCheckingSFINAE; - /// \brief RAII object used to temporarily suppress access checking. - class SuppressAccessChecksRAII { - Sema &S; - bool SuppressingAccess; - - public: - SuppressAccessChecksRAII(Sema &S, bool Suppress) - : S(S), SuppressingAccess(Suppress) { - if (Suppress) S.ActOnStartSuppressingAccessChecks(); - } - ~SuppressAccessChecksRAII() { - done(); - } - void done() { - if (!SuppressingAccess) return; - S.ActOnStopSuppressingAccessChecks(); - SuppressingAccess = false; - } - }; - - void ActOnStartSuppressingAccessChecks(); - void ActOnStopSuppressingAccessChecks(); - enum AbstractDiagSelID { AbstractNone = -1, AbstractReturnType, @@ -4246,7 +4467,31 @@ public: }; bool RequireNonAbstractType(SourceLocation Loc, QualType T, - const PartialDiagnostic &PD); + TypeDiagnoser &Diagnoser); + template<typename T1> + bool RequireNonAbstractType(SourceLocation Loc, QualType T, + unsigned DiagID, + const T1 &Arg1) { + BoundTypeDiagnoser1<T1> Diagnoser(DiagID, Arg1); + return RequireNonAbstractType(Loc, T, Diagnoser); + } + + template<typename T1, typename T2> + bool RequireNonAbstractType(SourceLocation Loc, QualType T, + unsigned DiagID, + const T1 &Arg1, const T2 &Arg2) { + BoundTypeDiagnoser2<T1, T2> Diagnoser(DiagID, Arg1, Arg2); + return RequireNonAbstractType(Loc, T, Diagnoser); + } + + template<typename T1, typename T2, typename T3> + bool RequireNonAbstractType(SourceLocation Loc, QualType T, + unsigned DiagID, + const T1 &Arg1, const T2 &Arg2, const T3 &Arg3) { + BoundTypeDiagnoser3<T1, T2, T3> Diagnoser(DiagID, Arg1, Arg2, Arg3); + return RequireNonAbstractType(Loc, T, Diagnoser); + } + void DiagnoseAbstractType(const CXXRecordDecl *RD); bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID, @@ -4263,9 +4508,9 @@ public: //===--------------------------------------------------------------------===// // C++ Templates [C++ 14] // - void FilterAcceptableTemplateNames(LookupResult &R, + void FilterAcceptableTemplateNames(LookupResult &R, bool AllowFunctionTemplates = true); - bool hasAnyAcceptableTemplateNames(LookupResult &R, + bool hasAnyAcceptableTemplateNames(LookupResult &R, bool AllowFunctionTemplates = true); void LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS, @@ -4638,7 +4883,7 @@ public: ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, const CXXScopeSpec &SS, SourceLocation TemplateLoc, - TemplateTy Template, + TemplateTy TemplateName, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, @@ -4730,7 +4975,13 @@ public: UPPC_IfExists, /// \brief Microsoft __if_not_exists. - UPPC_IfNotExists + UPPC_IfNotExists, + + /// \brief Lambda expression. + UPPC_Lambda, + + /// \brief Block expression, + UPPC_Block }; /// \brief Diagnose unexpanded parameter packs. @@ -4741,7 +4992,9 @@ public: /// parameter packs. /// /// \param Unexpanded the set of unexpanded parameter packs. - void DiagnoseUnexpandedParameterPacks(SourceLocation Loc, + /// + /// \returns true if an error occurred, false otherwise. + bool DiagnoseUnexpandedParameterPacks(SourceLocation Loc, UnexpandedParameterPackContext UPPC, ArrayRef<UnexpandedParameterPack> Unexpanded); @@ -4922,9 +5175,6 @@ public: /// \param Unexpanded The set of unexpanded parameter packs within the /// pattern. /// - /// \param NumUnexpanded The number of unexpanded parameter packs in - /// \p Unexpanded. - /// /// \param ShouldExpand Will be set to \c true if the transformer should /// expand the corresponding pack expansions into separate arguments. When /// set, \c NumExpansions must also be set. @@ -4957,10 +5207,11 @@ public: /// \brief Determine the number of arguments in the given pack expansion /// type. /// - /// This routine already assumes that the pack expansion type can be - /// expanded and that the number of arguments in the expansion is + /// This routine assumes that the number of arguments in the expansion is /// consistent across all of the unexpanded parameter packs in its pattern. - unsigned getNumArgumentsInExpansion(QualType T, + /// + /// Returns an empty Optional if the type can't be expanded. + llvm::Optional<unsigned> getNumArgumentsInExpansion(QualType T, const MultiLevelTemplateArgumentList &TemplateArgs); /// \brief Determine whether the given declarator contains any unexpanded @@ -5366,16 +5617,14 @@ public: /// template-id. InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateDecl *Template, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, + ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange = SourceRange()); /// \brief Note that we are instantiating a default argument in a /// template-id. InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, FunctionTemplateDecl *FunctionTemplate, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, + ArrayRef<TemplateArgument> TemplateArgs, ActiveTemplateInstantiation::InstantiationKind Kind, sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange = SourceRange()); @@ -5385,15 +5634,13 @@ public: /// specialization. InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, ClassTemplatePartialSpecializationDecl *PartialSpec, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, + ArrayRef<TemplateArgument> TemplateArgs, sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange = SourceRange()); InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, ParmVarDecl *Param, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, + ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange = SourceRange()); /// \brief Note that we are substituting prior template arguments into a @@ -5401,15 +5648,13 @@ public: InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, NamedDecl *Template, NonTypeTemplateParmDecl *Param, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, + ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange); InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, NamedDecl *Template, TemplateTemplateParmDecl *Param, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, + ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange); /// \brief Note that we are checking the default template argument @@ -5417,8 +5662,7 @@ public: InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateDecl *Template, NamedDecl *Param, - const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, + ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange); @@ -5456,6 +5700,14 @@ public: /// diagnostics that will be suppressed. llvm::Optional<sema::TemplateDeductionInfo *> isSFINAEContext() const; + /// \brief Determines whether we are currently in a context that + /// is not evaluated as per C++ [expr] p5. + bool isUnevaluatedContext() const { + assert(!ExprEvalContexts.empty() && + "Must be in an expression evaluation context"); + return ExprEvalContexts.back().Context == Sema::Unevaluated; + } + /// \brief RAII class used to determine whether SFINAE has /// trapped any errors that occur during template argument /// deduction.` @@ -5705,7 +5957,7 @@ public: SourceLocation EndProtoLoc, AttributeList *AttrList); - Decl *ActOnCompatiblityAlias( + Decl *ActOnCompatibilityAlias( SourceLocation AtCompatibilityAliasLoc, IdentifierInfo *AliasName, SourceLocation AliasLocation, IdentifierInfo *ClassName, SourceLocation ClassLocation); @@ -5768,28 +6020,27 @@ public: /// be modified to be consistent with \arg PropertyTy. void CheckObjCPropertyAttributes(Decl *PropertyPtrTy, SourceLocation Loc, - unsigned &Attributes); + unsigned &Attributes, + bool propertyInPrimaryClass); /// Process the specified property declaration and create decls for the /// setters and getters as needed. /// \param property The property declaration being processed - /// \param DC The semantic container for the property + /// \param CD The semantic container for the property /// \param redeclaredProperty Declaration for property if redeclared /// in class extension. /// \param lexicalDC Container for redeclaredProperty. void ProcessPropertyDecl(ObjCPropertyDecl *property, - ObjCContainerDecl *DC, + ObjCContainerDecl *CD, ObjCPropertyDecl *redeclaredProperty = 0, ObjCContainerDecl *lexicalDC = 0); + void DiagnosePropertyMismatch(ObjCPropertyDecl *Property, ObjCPropertyDecl *SuperProperty, const IdentifierInfo *Name); void ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl); - void CompareMethodParamsInBaseAndSuper(Decl *IDecl, - ObjCMethodDecl *MethodDecl, - bool IsInstance); void CompareProperties(Decl *CDecl, Decl *MergeProtocols); @@ -5855,14 +6106,6 @@ public: AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind, bool isVariadic, bool MethodDefinition); - // Helper method for ActOnClassMethod/ActOnInstanceMethod. - // Will search "local" class/category implementations for a method decl. - // Will also search in class's root looking for instance method. - // Returns 0 if no method is found. - ObjCMethodDecl *LookupPrivateClassMethod(Selector Sel, - ObjCInterfaceDecl *CDecl); - ObjCMethodDecl *LookupPrivateInstanceMethod(Selector Sel, - ObjCInterfaceDecl *ClassDecl); ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel, const ObjCObjectPointerType *OPT, bool IsInstance); @@ -5988,9 +6231,16 @@ public: const ObjCMethodDecl *Overridden, bool IsImplementation); - /// \brief Check whether the given method overrides any methods in its class, - /// calling \c CheckObjCMethodOverride for each overridden method. - bool CheckObjCMethodOverrides(ObjCMethodDecl *NewMethod, DeclContext *DC); + /// \brief Describes the compatibility of a result type with its method. + enum ResultTypeCompatibilityKind { + RTC_Compatible, + RTC_Incompatible, + RTC_Unknown + }; + + void CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, + ObjCInterfaceDecl *CurrentClass, + ResultTypeCompatibilityKind RTC); enum PragmaOptionsAlignKind { POAK_Native, // #pragma options align=native @@ -6001,7 +6251,7 @@ public: POAK_Reset // #pragma options align=reset }; - /// ActOnPragmaOptionsAlign - Called on well formed #pragma options align. + /// ActOnPragmaOptionsAlign - Called on well formed \#pragma options align. void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, SourceLocation PragmaLoc, SourceLocation KindLoc); @@ -6018,7 +6268,7 @@ public: PMSST_ON // #pragms ms_struct on }; - /// ActOnPragmaPack - Called on well formed #pragma pack(...). + /// ActOnPragmaPack - Called on well formed \#pragma pack(...). void ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, Expr *Alignment, @@ -6026,15 +6276,15 @@ public: SourceLocation LParenLoc, SourceLocation RParenLoc); - /// ActOnPragmaMSStruct - Called on well formed #pragms ms_struct [on|off]. + /// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off]. void ActOnPragmaMSStruct(PragmaMSStructKind Kind); - /// ActOnPragmaUnused - Called on well-formed '#pragma unused'. + /// ActOnPragmaUnused - Called on well-formed '\#pragma unused'. void ActOnPragmaUnused(const Token &Identifier, Scope *curScope, SourceLocation PragmaLoc); - /// ActOnPragmaVisibility - Called on well formed #pragma GCC visibility... . + /// ActOnPragmaVisibility - Called on well formed \#pragma GCC visibility... . void ActOnPragmaVisibility(const IdentifierInfo* VisType, SourceLocation PragmaLoc); @@ -6042,20 +6292,20 @@ public: SourceLocation Loc); void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W); - /// ActOnPragmaWeakID - Called on well formed #pragma weak ident. + /// ActOnPragmaWeakID - Called on well formed \#pragma weak ident. void ActOnPragmaWeakID(IdentifierInfo* WeakName, SourceLocation PragmaLoc, SourceLocation WeakNameLoc); - /// ActOnPragmaRedefineExtname - Called on well formed - /// #pragma redefine_extname oldname newname. + /// ActOnPragmaRedefineExtname - Called on well formed + /// \#pragma redefine_extname oldname newname. void ActOnPragmaRedefineExtname(IdentifierInfo* WeakName, IdentifierInfo* AliasName, SourceLocation PragmaLoc, SourceLocation WeakNameLoc, SourceLocation AliasNameLoc); - /// ActOnPragmaWeakAlias - Called on well formed #pragma weak ident = ident. + /// ActOnPragmaWeakAlias - Called on well formed \#pragma weak ident = ident. void ActOnPragmaWeakAlias(IdentifierInfo* WeakName, IdentifierInfo* AliasName, SourceLocation PragmaLoc, @@ -6063,11 +6313,11 @@ public: SourceLocation AliasNameLoc); /// ActOnPragmaFPContract - Called on well formed - /// #pragma {STDC,OPENCL} FP_CONTRACT + /// \#pragma {STDC,OPENCL} FP_CONTRACT void ActOnPragmaFPContract(tok::OnOffSwitch OOS); /// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to - /// a the record decl, to handle '#pragma pack' and '#pragma options align'. + /// a the record decl, to handle '\#pragma pack' and '\#pragma options align'. void AddAlignmentAttributesForRecord(RecordDecl *RD); /// AddMsStructLayoutForRecord - Adds ms_struct layout attribute to record. @@ -6081,25 +6331,27 @@ public: void PushNamespaceVisibilityAttr(const VisibilityAttr *Attr, SourceLocation Loc); - /// AddPushedVisibilityAttribute - If '#pragma GCC visibility' was used, + /// AddPushedVisibilityAttribute - If '\#pragma GCC visibility' was used, /// add an appropriate visibility attribute. void AddPushedVisibilityAttribute(Decl *RD); /// PopPragmaVisibility - Pop the top element of the visibility stack; used - /// for '#pragma GCC visibility' and visibility attributes on namespaces. + /// for '\#pragma GCC visibility' and visibility attributes on namespaces. void PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc); /// FreeVisContext - Deallocate and null out VisContext. void FreeVisContext(); /// AddCFAuditedAttribute - Check whether we're currently within - /// '#pragma clang arc_cf_code_audited' and, if so, consider adding + /// '\#pragma clang arc_cf_code_audited' and, if so, consider adding /// the appropriate attribute. void AddCFAuditedAttribute(Decl *D); /// AddAlignedAttr - Adds an aligned attribute to a particular declaration. - void AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E); - void AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *T); + void AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, + bool isDeclSpec); + void AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *T, + bool isDeclSpec); /// \brief The kind of conversion being performed. enum CheckedConversionKind { @@ -6164,6 +6416,21 @@ public: VariadicDoesNotApply }; + VariadicCallType getVariadicCallType(FunctionDecl *FDecl, + const FunctionProtoType *Proto, + Expr *Fn); + + // Used for determining in which context a type is allowed to be passed to a + // vararg function. + enum VarArgKind { + VAK_Valid, + VAK_ValidInCXX11, + VAK_Invalid + }; + + // Determines which VarArgKind fits an expression. + VarArgKind isValidVarArgType(const QualType &Ty); + /// GatherArgumentsForCall - Collector argument expressions for various /// form of call prototypes. bool GatherArgumentsForCall(SourceLocation CallLoc, @@ -6176,10 +6443,14 @@ public: bool AllowExplicit = false); // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but - // will warn if the resulting type is not a POD type. + // will create a runtime trap if the resulting type is not a POD type. ExprResult DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, FunctionDecl *FDecl); + /// Checks to see if the given expression is a valid argument to a variadic + /// function, issuing a diagnostic and returning NULL if not. + bool variadicArgumentPODCheck(const Expr *E, VariadicCallType CT); + // UsualArithmeticConversions - performs the UsualUnaryConversions on it's // operands and then handles various conversions that are common to binary // operators (C99 6.3.1.8). If both operands aren't arithmetic, this @@ -6269,6 +6540,11 @@ public: Expr *SrcExpr, AssignmentAction Action, bool *Complained = 0); + /// DiagnoseAssignmentEnum - Warn if assignment to enum is a constant + /// integer not in the range of enum values. + void DiagnoseAssignmentEnum(QualType DstType, QualType SrcType, + Expr *SrcExpr); + /// CheckAssignmentConstraints - Perform type checking for assignment, /// argument passing, variable initialization, and function return values. /// C99 6.5.16. @@ -6434,7 +6710,7 @@ public: /// \brief Force an expression with unknown-type to an expression of the /// given type. ExprResult forceUnknownAnyToType(Expr *E, QualType ToType); - + // CheckVectorCast - check type constraints for vectors. // Since vectors are an extension, there are no C standard reference for this. // We allow casting between vectors and integer datatypes of the same size. @@ -6540,20 +6816,29 @@ public: /// in the global scope. bool CheckObjCDeclScope(Decl *D); + /// \brief Abstract base class used for diagnosing integer constant + /// expression violations. + class VerifyICEDiagnoser { + public: + bool Suppress; + + VerifyICEDiagnoser(bool Suppress = false) : Suppress(Suppress) { } + + virtual void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) =0; + virtual void diagnoseFold(Sema &S, SourceLocation Loc, SourceRange SR); + virtual ~VerifyICEDiagnoser() { } + }; + /// VerifyIntegerConstantExpression - Verifies that an expression is an ICE, /// and reports the appropriate diagnostics. Returns false on success. /// Can optionally return the value of the expression. ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, - const PartialDiagnostic &Diag, - bool AllowFold, - const PartialDiagnostic &FoldDiag); + VerifyICEDiagnoser &Diagnoser, + bool AllowFold = true); ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, - const PartialDiagnostic &Diag, - bool AllowFold = true) { - return VerifyIntegerConstantExpression(E, Result, Diag, AllowFold, - PDiag(0)); - } - ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result = 0); + unsigned DiagID, + bool AllowFold = true); + ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result=0); /// VerifyBitField - verifies that a bit field expression is an ICE and has /// the correct width, and that the field type is valid. @@ -6745,15 +7030,39 @@ private: const ArraySubscriptExpr *ASE=0, bool AllowOnePastEnd=true, bool IndexNegated=false); void CheckArrayAccess(const Expr *E); - bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall); - bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc, + // Used to grab the relevant information from a FormatAttr and a + // FunctionDeclaration. + struct FormatStringInfo { + unsigned FormatIdx; + unsigned FirstDataArg; + bool HasVAListArg; + }; + + bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember, + FormatStringInfo *FSI); + bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, + const FunctionProtoType *Proto); + bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc, Expr **Args, unsigned NumArgs); - bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall); + bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall, + const FunctionProtoType *Proto); + void CheckConstructorCall(FunctionDecl *FDecl, + Expr **Args, + unsigned NumArgs, + const FunctionProtoType *Proto, + SourceLocation Loc); + + void checkCall(NamedDecl *FDecl, Expr **Args, unsigned NumArgs, + unsigned NumProtoArgs, bool IsMemberFunction, + SourceLocation Loc, SourceRange Range, + VariadicCallType CallType); + bool CheckObjCString(Expr *Arg); ExprResult CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool SemaBuiltinVAStart(CallExpr *TheCall); bool SemaBuiltinUnorderedCompare(CallExpr *TheCall); @@ -6783,23 +7092,36 @@ private: FST_Unknown }; static FormatStringType GetFormatStringType(const FormatAttr *Format); - bool SemaCheckStringLiteral(const Expr *E, Expr **Args, unsigned NumArgs, - bool HasVAListArg, unsigned format_idx, - unsigned firstDataArg, FormatStringType Type, - bool inFunctionCall = true); + + enum StringLiteralCheckType { + SLCT_NotALiteral, + SLCT_UncheckedLiteral, + SLCT_CheckedLiteral + }; + + StringLiteralCheckType checkFormatStringExpr(const Expr *E, + Expr **Args, unsigned NumArgs, + bool HasVAListArg, + unsigned format_idx, + unsigned firstDataArg, + FormatStringType Type, + VariadicCallType CallType, + bool inFunctionCall = true); void CheckFormatString(const StringLiteral *FExpr, const Expr *OrigFormatExpr, Expr **Args, unsigned NumArgs, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg, - FormatStringType Type, bool inFunctionCall); + FormatStringType Type, bool inFunctionCall, + VariadicCallType CallType); - void CheckFormatArguments(const FormatAttr *Format, CallExpr *TheCall); - void CheckFormatArguments(const FormatAttr *Format, Expr **Args, + bool CheckFormatArguments(const FormatAttr *Format, Expr **Args, unsigned NumArgs, bool IsCXXMember, + VariadicCallType CallType, SourceLocation Loc, SourceRange Range); - void CheckFormatArguments(Expr **Args, unsigned NumArgs, + bool CheckFormatArguments(Expr **Args, unsigned NumArgs, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg, FormatStringType Type, + VariadicCallType CallType, SourceLocation Loc, SourceRange range); void CheckNonNullArguments(const NonNullAttr *NonNull, diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h index c16823a..273374d 100644 --- a/include/clang/Sema/Template.h +++ b/include/clang/Sema/Template.h @@ -152,10 +152,11 @@ namespace clang { /// \brief Construct an integral non-type template argument that /// has been deduced, possibly from an array bound. - DeducedTemplateArgument(const llvm::APSInt &Value, + DeducedTemplateArgument(ASTContext &Ctx, + const llvm::APSInt &Value, QualType ValueType, bool DeducedFromArrayBound) - : TemplateArgument(Value, ValueType), + : TemplateArgument(Ctx, Value, ValueType), DeducedFromArrayBound(DeducedFromArrayBound) { } /// \brief For a non-type template argument, determine whether the @@ -371,8 +372,10 @@ namespace clang { public: TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner, const MultiLevelTemplateArgumentList &TemplateArgs) - : SemaRef(SemaRef), SubstIndex(SemaRef, -1), Owner(Owner), - TemplateArgs(TemplateArgs), LateAttrs(0), StartingScope(0) { } + : SemaRef(SemaRef), + SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex), + Owner(Owner), TemplateArgs(TemplateArgs), LateAttrs(0), StartingScope(0) + { } // FIXME: Once we get closer to completion, replace these manually-written // declarations with automatically-generated ones from diff --git a/include/clang/Sema/TemplateDeduction.h b/include/clang/Sema/TemplateDeduction.h index 100d56e..4c2d876 100644 --- a/include/clang/Sema/TemplateDeduction.h +++ b/include/clang/Sema/TemplateDeduction.h @@ -39,6 +39,9 @@ class TemplateDeductionInfo { /// deduction is occurring. SourceLocation Loc; + /// \brief Have we suppressed an error during deduction? + bool HasSFINAEDiagnostic; + /// \brief Warnings (and follow-on notes) that were suppressed due to /// SFINAE while performing template argument deduction. SmallVector<PartialDiagnosticAt, 4> SuppressedDiagnostics; @@ -49,7 +52,7 @@ class TemplateDeductionInfo { public: TemplateDeductionInfo(ASTContext &Context, SourceLocation Loc) - : Context(Context), Deduced(0), Loc(Loc) { } + : Context(Context), Deduced(0), Loc(Loc), HasSFINAEDiagnostic(false) { } ~TemplateDeductionInfo() { // FIXME: if (Deduced) Deduced->Destroy(Context); @@ -68,6 +71,15 @@ public: return Result; } + /// \brief Take ownership of the SFINAE diagnostic. + void takeSFINAEDiagnostic(PartialDiagnosticAt &PD) { + assert(HasSFINAEDiagnostic); + PD.first = SuppressedDiagnostics.front().first; + PD.second.swap(SuppressedDiagnostics.front().second); + SuppressedDiagnostics.clear(); + HasSFINAEDiagnostic = false; + } + /// \brief Provide a new template argument list that contains the /// results of template argument deduction. void reset(TemplateArgumentList *NewDeduced) { @@ -75,10 +87,31 @@ public: Deduced = NewDeduced; } + /// \brief Is a SFINAE diagnostic available? + bool hasSFINAEDiagnostic() const { + return HasSFINAEDiagnostic; + } + + /// \brief Set the diagnostic which caused the SFINAE failure. + void addSFINAEDiagnostic(SourceLocation Loc, PartialDiagnostic PD) { + // Only collect the first diagnostic. + if (HasSFINAEDiagnostic) + return; + SuppressedDiagnostics.clear(); + SuppressedDiagnostics.push_back( + std::make_pair(Loc, PartialDiagnostic::NullDiagnostic())); + SuppressedDiagnostics.back().second.swap(PD); + HasSFINAEDiagnostic = true; + } + /// \brief Add a new diagnostic to the set of diagnostics void addSuppressedDiagnostic(SourceLocation Loc, - const PartialDiagnostic &PD) { - SuppressedDiagnostics.push_back(std::make_pair(Loc, PD)); + PartialDiagnostic PD) { + if (HasSFINAEDiagnostic) + return; + SuppressedDiagnostics.push_back( + std::make_pair(Loc, PartialDiagnostic::NullDiagnostic())); + SuppressedDiagnostics.back().second.swap(PD); } /// \brief Iterator over the set of suppressed diagnostics. diff --git a/include/clang/Sema/Weak.h b/include/clang/Sema/Weak.h index d36b970..6d1b64b 100644 --- a/include/clang/Sema/Weak.h +++ b/include/clang/Sema/Weak.h @@ -21,7 +21,7 @@ namespace clang { class IdentifierInfo; -/// \brief Captures information about a #pragma weak directive. +/// \brief Captures information about a \#pragma weak directive. class WeakInfo { IdentifierInfo *alias; // alias (optional) SourceLocation loc; // for diagnostics diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index f9bb892..dbe6e5a 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -207,7 +207,10 @@ namespace clang { PREPROCESSOR_DETAIL_BLOCK_ID, /// \brief The block containing the submodule structure. - SUBMODULE_BLOCK_ID + SUBMODULE_BLOCK_ID, + + /// \brief The block containing comments. + COMMENTS_BLOCK_ID }; /// \brief Record types that occur within the AST block itself. @@ -405,7 +408,7 @@ namespace clang { /// sets. CXX_BASE_SPECIFIER_OFFSETS = 37, - /// \brief Record code for #pragma diagnostic mappings. + /// \brief Record code for \#pragma diagnostic mappings. DIAG_PRAGMA_MAPPINGS = 38, /// \brief Record code for special CUDA declarations. @@ -417,7 +420,7 @@ namespace clang { /// \brief The directory that the PCH was originally created in. ORIGINAL_PCH_DIR = 41, - /// \brief Record code for floating point #pragma options. + /// \brief Record code for floating point \#pragma options. FP_PRAGMA_OPTIONS = 42, /// \brief Record code for enabled OpenCL extensions. @@ -441,7 +444,7 @@ namespace clang { MODULE_OFFSET_MAP = 47, /// \brief Record code for the source manager line table information, - /// which stores information about #line directives. + /// which stores information about \#line directives. SOURCE_MANAGER_LINE_TABLE = 48, /// \brief Record code for map of Objective-C class definition IDs to the @@ -469,7 +472,7 @@ namespace clang { /// /// This array can only be interpreted properly using the Objective-C /// categories map. - OBJC_CATEGORIES + OBJC_CATEGORIES = 54 }; /// \brief Record types used within a source manager block. @@ -500,8 +503,8 @@ namespace clang { PP_MACRO_OBJECT_LIKE = 1, /// \brief A function-like macro definition. - /// [PP_MACRO_FUNCTION_LIKE, <ObjectLikeStuff>, IsC99Varargs, IsGNUVarars, - /// NumArgs, ArgIdentInfoID* ] + /// [PP_MACRO_FUNCTION_LIKE, \<ObjectLikeStuff>, IsC99Varargs, + /// IsGNUVarars, NumArgs, ArgIdentInfoID* ] PP_MACRO_FUNCTION_LIKE = 2, /// \brief Describes one token. @@ -545,7 +548,12 @@ namespace clang { /// \brief Specifies a required feature. SUBMODULE_REQUIRES = 7 }; - + + /// \brief Record types used within a comments block. + enum CommentRecordTypes { + COMMENTS_RAW_COMMENT = 0 + }; + /// \defgroup ASTAST AST file AST constants /// /// The constants in this group describe various components of the @@ -557,7 +565,7 @@ namespace clang { /// /// These type IDs correspond to predefined types in the AST /// context, such as built-in types (int) and special place-holder - /// types (the <overload> and <dependent> type markers). Such + /// types (the \<overload> and \<dependent> type markers). Such /// types are never actually serialized, since they will be built /// by the AST context when it is created. enum PredefinedTypeIDs { @@ -632,7 +640,9 @@ namespace clang { /// \brief ARC's unbridged-cast placeholder type. PREDEF_TYPE_ARC_UNBRIDGED_CAST = 34, /// \brief The pseudo-object placeholder type. - PREDEF_TYPE_PSEUDO_OBJECT = 35 + PREDEF_TYPE_PSEUDO_OBJECT = 35, + /// \brief The __va_list_tag placeholder type. + PREDEF_TYPE_VA_LIST_TAG = 36 }; /// \brief The number of predefined type IDs that are reserved for @@ -738,28 +748,26 @@ namespace clang { /// The constants in this enumeration are indices into the /// SPECIAL_TYPES record. enum SpecialTypeIDs { - /// \brief __builtin_va_list - SPECIAL_TYPE_BUILTIN_VA_LIST = 0, /// \brief CFConstantString type - SPECIAL_TYPE_CF_CONSTANT_STRING = 1, + SPECIAL_TYPE_CF_CONSTANT_STRING = 0, /// \brief C FILE typedef type - SPECIAL_TYPE_FILE = 2, + SPECIAL_TYPE_FILE = 1, /// \brief C jmp_buf typedef type - SPECIAL_TYPE_JMP_BUF = 3, + SPECIAL_TYPE_JMP_BUF = 2, /// \brief C sigjmp_buf typedef type - SPECIAL_TYPE_SIGJMP_BUF = 4, + SPECIAL_TYPE_SIGJMP_BUF = 3, /// \brief Objective-C "id" redefinition type - SPECIAL_TYPE_OBJC_ID_REDEFINITION = 5, + SPECIAL_TYPE_OBJC_ID_REDEFINITION = 4, /// \brief Objective-C "Class" redefinition type - SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 6, + SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 5, /// \brief Objective-C "SEL" redefinition type - SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 7, + SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 6, /// \brief C ucontext_t typedef type - SPECIAL_TYPE_UCONTEXT_T = 8 + SPECIAL_TYPE_UCONTEXT_T = 7 }; /// \brief The number of special type IDs. - const unsigned NumSpecialTypeIDs = 9; + const unsigned NumSpecialTypeIDs = 8; /// \brief Predefined declaration IDs. /// @@ -793,14 +801,17 @@ namespace clang { PREDEF_DECL_UNSIGNED_INT_128_ID = 7, /// \brief The internal 'instancetype' typedef. - PREDEF_DECL_OBJC_INSTANCETYPE_ID = 8 + PREDEF_DECL_OBJC_INSTANCETYPE_ID = 8, + + /// \brief The internal '__builtin_va_list' typedef. + PREDEF_DECL_BUILTIN_VA_LIST_ID = 9 }; /// \brief The number of declaration IDs that are predefined. /// /// For more information about predefined declarations, see the /// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants. - const unsigned int NUM_PREDEF_DECL_IDS = 9; + const unsigned int NUM_PREDEF_DECL_IDS = 10; /// \brief Record codes for each kind of declaration. /// @@ -862,7 +873,7 @@ namespace clang { /// in the order in which those declarations were added to the /// declaration context. This data is used when iterating over /// the contents of a DeclContext, e.g., via - /// DeclContext::decls_begin()/DeclContext::decls_end(). + /// DeclContext::decls_begin() and DeclContext::decls_end(). DECL_CONTEXT_LEXICAL, /// \brief A record that stores the set of declarations that are /// visible from a given DeclContext. @@ -1066,7 +1077,7 @@ namespace clang { /// \brief An ObjCStringLiteral record. EXPR_OBJC_STRING_LITERAL, - EXPR_OBJC_NUMERIC_LITERAL, + EXPR_OBJC_BOXED_EXPRESSION, EXPR_OBJC_ARRAY_LITERAL, EXPR_OBJC_DICTIONARY_LITERAL, @@ -1089,7 +1100,7 @@ namespace clang { EXPR_OBJC_MESSAGE_EXPR, /// \brief An ObjCIsa Expr record. EXPR_OBJC_ISA, - /// \breif An ObjCIndirectCopyRestoreExpr record. + /// \brief An ObjCIndirectCopyRestoreExpr record. EXPR_OBJC_INDIRECT_COPY_RESTORE, /// \brief An ObjCForCollectionStmt record. diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index a9d0fc3..f0b7275 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -199,6 +199,8 @@ class ASTReader public ExternalSLocEntrySource { public: + typedef SmallVector<uint64_t, 64> RecordData; + enum ASTReadResult { Success, Failure, IgnorePCH }; /// \brief Types of AST files. friend class PCHValidator; @@ -454,7 +456,7 @@ private: /// consumer eagerly. SmallVector<uint64_t, 16> ExternalDefinitions; - /// \brief The IDs of all tentative definitions stored in the the chain. + /// \brief The IDs of all tentative definitions stored in the chain. /// /// Sema keeps track of all tentative definitions in a TU because it has to /// complete them and pass them on to CodeGen. Thus, tentative definitions in @@ -591,11 +593,14 @@ private: /// indicates how many separate module file load operations have occurred. unsigned CurrentGeneration; + typedef llvm::DenseMap<unsigned, SwitchCase *> SwitchCaseMapTy; /// \brief Mapping from switch-case IDs in the chain to switch-case statements /// /// Statements usually don't have IDs, but switch cases need them, so that the /// switch statement can refer to them. - std::map<unsigned, SwitchCase *> SwitchCaseStmts; + SwitchCaseMapTy SwitchCaseStmts; + + SwitchCaseMapTy *CurrSwitchCaseStmts; /// \brief The number of stat() calls that hit/missed the stat /// cache. @@ -798,7 +803,7 @@ private: llvm::BitstreamCursor &SLocCursorForID(int ID); SourceLocation getImportLocation(ModuleFile *F); ASTReadResult ReadSubmoduleBlock(ModuleFile &F); - bool ParseLanguageOptions(const SmallVectorImpl<uint64_t> &Record); + bool ParseLanguageOptions(const RecordData &Record); struct RecordLocation { RecordLocation(ModuleFile *M, uint64_t O) @@ -821,19 +826,19 @@ private: RecordLocation getLocalBitOffset(uint64_t GlobalOffset); uint64_t getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset); - /// \brief Returns the first preprocessed entity ID that ends after \arg BLoc. + /// \brief Returns the first preprocessed entity ID that ends after BLoc. serialization::PreprocessedEntityID findBeginPreprocessedEntity(SourceLocation BLoc) const; - /// \brief Returns the first preprocessed entity ID that begins after \arg - /// ELoc. + /// \brief Returns the first preprocessed entity ID that begins after ELoc. serialization::PreprocessedEntityID findEndPreprocessedEntity(SourceLocation ELoc) const; - /// \brief \arg SLocMapI points at a chunk of a module that contains no - /// preprocessed entities or the entities it contains are not the ones we are - /// looking for. Find the next module that contains entities and return the ID + /// \brief Find the next module that contains entities and return the ID /// of the first entry. + /// \arg SLocMapI points at a chunk of a module that contains no + /// preprocessed entities or the entities it contains are not the + /// ones we are looking for. serialization::PreprocessedEntityID findNextPreprocessedEntity( GlobalSLocOffsetMapType::const_iterator SLocMapI) const; @@ -859,8 +864,6 @@ private: ASTReader(const ASTReader&); // do not implement ASTReader &operator=(const ASTReader &); // do not implement public: - typedef SmallVector<uint64_t, 64> RecordData; - /// \brief Load the AST file and validate its contents against the given /// Preprocessor. /// @@ -907,8 +910,8 @@ public: /// /// \param Mod The module whose names should be made visible. /// - /// \param Visibility The level of visibility to give the names in the module. - /// Visibility can only be increased over time. + /// \param NameVisibility The level of visibility to give the names in the + /// module. Visibility can only be increased over time. void makeModuleVisible(Module *Mod, Module::NameVisibilityKind NameVisibility); @@ -1498,6 +1501,13 @@ public: SwitchCase *getSwitchCaseWithID(unsigned ID); void ClearSwitchCaseIDs(); + + /// \brief Cursors for comments blocks. + SmallVector<std::pair<llvm::BitstreamCursor, + serialization::ModuleFile *>, 8> CommentsCursors; + + /// \brief Loads comments ranges. + void ReadComments(); }; /// \brief Helper class that saves the current stream position and diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index e693f17..d038d58 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -110,6 +110,10 @@ private: /// serialization, rather than just queueing updates. bool WritingAST; + /// \brief Indicates that we are done serializing the collection of decls + /// and types to emit. + bool DoneWritingDeclsAndTypes; + /// \brief Indicates that the AST contained compiler errors. bool ASTHasCompilerErrors; @@ -296,6 +300,10 @@ private: /// it. llvm::SmallPtrSet<const DeclContext *, 16> UpdatedDeclContexts; + /// \brief Keeps track of visible decls that were added in DeclContexts + /// coming from another AST file. + SmallVector<const Decl *, 16> UpdatingVisibleDecls; + typedef llvm::SmallPtrSet<const Decl *, 16> DeclsToRewriteTy; /// \brief Decls that will be replaced in the current dependent AST file. DeclsToRewriteTy DeclsToRewrite; @@ -337,7 +345,7 @@ private: SmallVector<Stmt *, 16> *CollectedStmts; /// \brief Mapping from SwitchCase statements to IDs. - std::map<SwitchCase *, unsigned> SwitchCaseIDs; + llvm::DenseMap<SwitchCase *, unsigned> SwitchCaseIDs; /// \brief The number of statements written to the AST file. unsigned NumStatements; @@ -414,11 +422,12 @@ private: uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC); void WriteTypeDeclOffsets(); void WriteFileDeclIDsMap(); + void WriteComments(); void WriteSelectors(Sema &SemaRef); void WriteReferencedSelectorsPool(Sema &SemaRef); void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver, bool IsModule); - void WriteAttributes(const AttrVec &Attrs, RecordDataImpl &Record); + void WriteAttributes(ArrayRef<const Attr*> Attrs, RecordDataImpl &Record); void ResolveDeclUpdatesBlocks(); void WriteDeclUpdatesBlocks(); void WriteDeclReplacementsBlock(); diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 2b699a8..5ee52cc 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -101,20 +101,27 @@ protected: /// Used for clients to tell if the report's configuration has changed /// since the last time they checked. unsigned ConfigurationChangeToken; + + /// When set, this flag disables all callstack pruning from a diagnostic + /// path. This is useful for some reports that want maximum fidelty + /// when reporting an issue. + bool DoNotPrunePath; public: BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode) : BT(bt), DeclWithIssue(0), Description(desc), ErrorNode(errornode), - ConfigurationChangeToken(0) {} + ConfigurationChangeToken(0), DoNotPrunePath(false) {} BugReport(BugType& bt, StringRef shortDesc, StringRef desc, const ExplodedNode *errornode) : BT(bt), DeclWithIssue(0), ShortDescription(shortDesc), Description(desc), - ErrorNode(errornode), ConfigurationChangeToken(0) {} + ErrorNode(errornode), ConfigurationChangeToken(0), + DoNotPrunePath(false) {} BugReport(BugType& bt, StringRef desc, PathDiagnosticLocation l) : BT(bt), DeclWithIssue(0), Description(desc), Location(l), ErrorNode(0), - ConfigurationChangeToken(0) {} + ConfigurationChangeToken(0), + DoNotPrunePath(false) {} /// \brief Create a BugReport with a custom uniqueing location. /// @@ -142,6 +149,13 @@ public: return ShortDescription.empty() ? Description : ShortDescription; } + /// Indicates whether or not any path pruning should take place + /// when generating a PathDiagnostic from this BugReport. + bool shouldPrunePath() const { return !DoNotPrunePath; } + + /// Disable all path pruning when generating a PathDiagnostic. + void disablePathPruning() { DoNotPrunePath = true; } + void markInteresting(SymbolRef sym); void markInteresting(const MemRegion *R); void markInteresting(SVal V); diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h index 7e665ce..f53c15f 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h @@ -226,13 +226,11 @@ public: namespace bugreporter { -BugReporterVisitor *getTrackNullOrUndefValueVisitor(const ExplodedNode *N, - const Stmt *S, - BugReport *R); +void addTrackNullOrUndefValueVisitor(const ExplodedNode *N, const Stmt *S, + BugReport *R); const Stmt *GetDerefExpr(const ExplodedNode *N); const Stmt *GetDenomExpr(const ExplodedNode *N); -const Stmt *GetCalleeExpr(const ExplodedNode *N); const Stmt *GetRetValExpr(const ExplodedNode *N); } // end namespace clang diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index 5a8a1c7..2e7abfa 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -148,6 +148,15 @@ public: assert(Range.isValid()); } + /// Create a location at an explicit offset in the source. + /// + /// This should only be used if there are no more appropriate constructors. + PathDiagnosticLocation(SourceLocation loc, const SourceManager &sm) + : K(SingleLocK), S(0), D(0), SM(&sm), Loc(loc, sm), Range(genRange()) { + assert(Loc.isValid()); + assert(Range.isValid()); + } + /// Create a location corresponding to the given declaration. static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM) { @@ -163,6 +172,14 @@ public: const SourceManager &SM, const LocationOrAnalysisDeclContext LAC); + /// Create a location for the end of the statement. + /// + /// If the statement is a CompoundStatement, the location will point to the + /// closing brace instead of following it. + static PathDiagnosticLocation createEnd(const Stmt *S, + const SourceManager &SM, + const LocationOrAnalysisDeclContext LAC); + /// Create the location for the operator of the binary expression. /// Assumes the statement has a valid location. static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO, @@ -333,10 +350,17 @@ public: }; -class PathPieces : - public std::deque<IntrusiveRefCntPtr<PathDiagnosticPiece> > { +class PathPieces : public std::deque<IntrusiveRefCntPtr<PathDiagnosticPiece> > { + void flattenTo(PathPieces &Primary, PathPieces &Current, + bool ShouldFlattenMacros) const; public: - ~PathPieces(); + ~PathPieces(); + + PathPieces flatten(bool ShouldFlattenMacros) const { + PathPieces Result; + flattenTo(Result, Result, ShouldFlattenMacros); + return Result; + } }; class PathDiagnosticSpotPiece : public PathDiagnosticPiece { @@ -362,7 +386,7 @@ public: /// \brief Interface for classes constructing Stack hints. /// /// If a PathDiagnosticEvent occurs in a different frame than the final -/// diagnostic the hints can be used to summarise the effect of the call. +/// diagnostic the hints can be used to summarize the effect of the call. class StackHintGenerator { public: virtual ~StackHintGenerator() = 0; @@ -510,7 +534,7 @@ public: } static PathDiagnosticCallPiece *construct(const ExplodedNode *N, - const CallExit &CE, + const CallExitEnd &CE, const SourceManager &SM); static PathDiagnosticCallPiece *construct(PathPieces &pieces, @@ -637,6 +661,8 @@ public: void pushActivePath(PathPieces *p) { pathStack.push_back(p); } void popActivePath() { if (!pathStack.empty()) pathStack.pop_back(); } + + bool isWithinCall() const { return !pathStack.empty(); } // PathDiagnostic(); PathDiagnostic(const Decl *DeclWithIssue, diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h index 76d8c15..3214d96 100644 --- a/include/clang/StaticAnalyzer/Core/Checker.h +++ b/include/clang/StaticAnalyzer/Core/Checker.h @@ -122,7 +122,7 @@ public: class PreObjCMessage { template <typename CHECKER> - static void _checkObjCMessage(void *checker, const ObjCMessage &msg, + static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg, CheckerContext &C) { ((const CHECKER *)checker)->checkPreObjCMessage(msg, C); } @@ -137,7 +137,7 @@ public: class PostObjCMessage { template <typename CHECKER> - static void _checkObjCMessage(void *checker, const ObjCMessage &msg, + static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg, CheckerContext &C) { ((const CHECKER *)checker)->checkPostObjCMessage(msg, C); } @@ -150,6 +150,36 @@ public: } }; +class PreCall { + template <typename CHECKER> + static void _checkCall(void *checker, const CallEvent &msg, + CheckerContext &C) { + ((const CHECKER *)checker)->checkPreCall(msg, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForPreCall( + CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>)); + } +}; + +class PostCall { + template <typename CHECKER> + static void _checkCall(void *checker, const CallEvent &msg, + CheckerContext &C) { + ((const CHECKER *)checker)->checkPostCall(msg, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForPostCall( + CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>)); + } +}; + class Location { template <typename CHECKER> static void _checkLocation(void *checker, @@ -266,7 +296,7 @@ class RegionChanges { const StoreManager::InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> Explicits, ArrayRef<const MemRegion *> Regions, - const CallOrObjCMessage *Call) { + const CallEvent *Call) { return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated, Explicits, Regions, Call); } @@ -372,16 +402,14 @@ template <typename CHECK1, typename CHECK2=check::_VoidCheck, typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck, typename CHECK13=check::_VoidCheck,typename CHECK14=check::_VoidCheck, typename CHECK15=check::_VoidCheck,typename CHECK16=check::_VoidCheck, - typename CHECK17=check::_VoidCheck,typename CHECK18=check::_VoidCheck> + typename CHECK17=check::_VoidCheck,typename CHECK18=check::_VoidCheck, + typename CHECK19=check::_VoidCheck,typename CHECK20=check::_VoidCheck, + typename CHECK21=check::_VoidCheck,typename CHECK22=check::_VoidCheck, + typename CHECK23=check::_VoidCheck,typename CHECK24=check::_VoidCheck> class Checker; template <> -class Checker<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, - check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, - check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, - check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, - check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, - check::_VoidCheck, check::_VoidCheck, check::_VoidCheck> +class Checker<check::_VoidCheck> : public CheckerBase { virtual void anchor(); @@ -393,19 +421,22 @@ template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4, typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8, typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12, typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16, - typename CHECK17,typename CHECK18> + typename CHECK17,typename CHECK18,typename CHECK19,typename CHECK20, + typename CHECK21,typename CHECK22,typename CHECK23,typename CHECK24> class Checker : public CHECK1, - public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, - CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15, - CHECK16,CHECK17,CHECK18> { + public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, + CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13, + CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19, + CHECK20,CHECK21,CHECK22,CHECK23,CHECK24> { public: template <typename CHECKER> static void _register(CHECKER *checker, CheckerManager &mgr) { CHECK1::_register(checker, mgr); - Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, - CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15, - CHECK16,CHECK17,CHECK18>::_register(checker, mgr); + Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, + CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13, + CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19, + CHECK20,CHECK21,CHECK22,CHECK23,CHECK24>::_register(checker, mgr); } }; diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h index d215f99..e11b6d5 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -33,7 +33,8 @@ namespace ento { class AnalysisManager; class BugReporter; class CheckerContext; - class ObjCMessage; + class SimpleCall; + class ObjCMethodCall; class SVal; class ExplodedNode; class ExplodedNodeSet; @@ -44,12 +45,6 @@ namespace ento { class MemRegion; class SymbolReaper; -class GraphExpander { -public: - virtual ~GraphExpander(); - virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) = 0; -}; - template <typename T> class CheckerFn; template <typename RET, typename P1, typename P2, typename P3, typename P4, @@ -207,7 +202,7 @@ public: /// \brief Run checkers for pre-visiting obj-c messages. void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, - const ObjCMessage &msg, + const ObjCMethodCall &msg, ExprEngine &Eng) { runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng); } @@ -215,16 +210,39 @@ public: /// \brief Run checkers for post-visiting obj-c messages. void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, - const ObjCMessage &msg, - ExprEngine &Eng) { - runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng); + const ObjCMethodCall &msg, + ExprEngine &Eng, + bool wasInlined = false) { + runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng, + wasInlined); } /// \brief Run checkers for visiting obj-c messages. void runCheckersForObjCMessage(bool isPreVisit, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, - const ObjCMessage &msg, ExprEngine &Eng); + const ObjCMethodCall &msg, ExprEngine &Eng, + bool wasInlined = false); + + /// \brief Run checkers for pre-visiting obj-c messages. + void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, + const CallEvent &Call, ExprEngine &Eng) { + runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng); + } + + /// \brief Run checkers for post-visiting obj-c messages. + void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, + const CallEvent &Call, ExprEngine &Eng, + bool wasInlined = false) { + runCheckersForCallEvent(/*isPreVisit=*/false, Dst, Src, Call, Eng, + wasInlined); + } + + /// \brief Run checkers for visiting obj-c messages. + void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst, + const ExplodedNodeSet &Src, + const CallEvent &Call, ExprEngine &Eng, + bool wasInlined = false); /// \brief Run checkers for load/store of a location. void runCheckersForLocation(ExplodedNodeSet &Dst, @@ -272,7 +290,8 @@ public: void runCheckersForDeadSymbols(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SymbolReaper &SymReaper, const Stmt *S, - ExprEngine &Eng); + ExprEngine &Eng, + ProgramPoint::Kind K); /// \brief True if at least one checker wants to check region changes. bool wantsRegionChangeUpdate(ProgramStateRef state); @@ -286,24 +305,25 @@ public: /// For example, in the case of a function call, these would be arguments. /// \param Regions The transitive closure of accessible regions, /// i.e. all regions that may have been touched by this change. - /// \param The call expression wrapper if the regions are invalidated by a - /// call. - ProgramStateRef + /// \param Call The call expression wrapper if the regions are invalidated + /// by a call. + ProgramStateRef runCheckersForRegionChanges(ProgramStateRef state, const StoreManager::InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> ExplicitRegions, ArrayRef<const MemRegion *> Regions, - const CallOrObjCMessage *Call); + const CallEvent *Call); /// \brief Run checkers for handling assumptions on symbolic values. ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state, SVal Cond, bool Assumption); /// \brief Run checkers for evaluating a call. + /// + /// Warning: Currently, the CallEvent MUST come from a CallExpr! void runCheckersForEvalCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, - const CallExpr *CE, ExprEngine &Eng, - GraphExpander *defaultEval = 0); + const CallEvent &CE, ExprEngine &Eng); /// \brief Run checkers for the entire Translation Unit. void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU, @@ -342,8 +362,11 @@ public: typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc; - typedef CheckerFn<void (const ObjCMessage &, CheckerContext &)> + typedef CheckerFn<void (const ObjCMethodCall &, CheckerContext &)> CheckObjCMessageFunc; + + typedef CheckerFn<void (const CallEvent &, CheckerContext &)> + CheckCallFunc; typedef CheckerFn<void (const SVal &location, bool isLoad, const Stmt *S, @@ -372,7 +395,7 @@ public: const StoreManager::InvalidatedSymbols *symbols, ArrayRef<const MemRegion *> ExplicitRegions, ArrayRef<const MemRegion *> Regions, - const CallOrObjCMessage *Call)> + const CallEvent *Call)> CheckRegionChangesFunc; typedef CheckerFn<bool (ProgramStateRef)> WantsRegionChangeUpdateFunc; @@ -402,6 +425,9 @@ public: void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn); void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn); + void _registerForPreCall(CheckCallFunc checkfn); + void _registerForPostCall(CheckCallFunc checkfn); + void _registerForLocation(CheckLocationFunc checkfn); void _registerForBind(CheckBindFunc checkfn); @@ -523,6 +549,9 @@ private: std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers; std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers; + std::vector<CheckCallFunc> PreCallCheckers; + std::vector<CheckCallFunc> PostCallCheckers; + std::vector<CheckLocationFunc> LocationCheckers; std::vector<CheckBindFunc> BindCheckers; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h new file mode 100644 index 0000000..e1ff17b --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h @@ -0,0 +1,106 @@ +//== APSIntType.h - Simple record of the type of APSInts --------*- 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_SA_CORE_APSINTTYPE_H +#define LLVM_CLANG_SA_CORE_APSINTTYPE_H + +#include "llvm/ADT/APSInt.h" + +namespace clang { +namespace ento { + +/// \brief A record of the "type" of an APSInt, used for conversions. +class APSIntType { + uint32_t BitWidth; + bool IsUnsigned; + +public: + APSIntType(uint32_t Width, bool Unsigned) + : BitWidth(Width), IsUnsigned(Unsigned) {} + + /* implicit */ APSIntType(const llvm::APSInt &Value) + : BitWidth(Value.getBitWidth()), IsUnsigned(Value.isUnsigned()) {} + + uint32_t getBitWidth() const { return BitWidth; } + bool isUnsigned() const { return IsUnsigned; } + + /// \brief Convert a given APSInt, in place, to match this type. + /// + /// This behaves like a C cast: converting 255u8 (0xFF) to s16 gives + /// 255 (0x00FF), and converting -1s8 (0xFF) to u16 gives 65535 (0xFFFF). + void apply(llvm::APSInt &Value) const { + // Note the order here. We extend first to preserve the sign, if this value + // is signed, /then/ match the signedness of the result type. + Value = Value.extOrTrunc(BitWidth); + Value.setIsUnsigned(IsUnsigned); + } + + /// Convert and return a new APSInt with the given value, but this + /// type's bit width and signedness. + /// + /// \see apply + llvm::APSInt convert(const llvm::APSInt &Value) const LLVM_READONLY { + llvm::APSInt Result(Value, Value.isUnsigned()); + apply(Result); + return Result; + } + + /// Returns an all-zero value for this type. + llvm::APSInt getZeroValue() const LLVM_READONLY { + return llvm::APSInt(BitWidth, IsUnsigned); + } + + /// Returns the minimum value for this type. + llvm::APSInt getMinValue() const LLVM_READONLY { + return llvm::APSInt::getMinValue(BitWidth, IsUnsigned); + } + + /// Returns the maximum value for this type. + llvm::APSInt getMaxValue() const LLVM_READONLY { + return llvm::APSInt::getMaxValue(BitWidth, IsUnsigned); + } + + /// Used to classify whether a value is representable using this type. + /// + /// \see testInRange + enum RangeTestResultKind { + RTR_Below = -1, ///< Value is less than the minimum representable value. + RTR_Within = 0, ///< Value is representable using this type. + RTR_Above = 1 ///< Value is greater than the maximum representable value. + }; + + /// Tests whether a given value is losslessly representable using this type. + /// + /// Note that signedness conversions will be rejected, even with the same bit + /// pattern. For example, -1s8 is not in range for 'unsigned char' (u8). + RangeTestResultKind testInRange(const llvm::APSInt &Val) const LLVM_READONLY; + + bool operator==(const APSIntType &Other) const { + return BitWidth == Other.BitWidth && IsUnsigned == Other.IsUnsigned; + } + + /// \brief Provide an ordering for finding a common conversion type. + /// + /// Unsigned integers are considered to be better conversion types than + /// signed integers of the same width. + bool operator<(const APSIntType &Other) const { + if (BitWidth < Other.BitWidth) + return true; + if (BitWidth > Other.BitWidth) + return false; + if (!IsUnsigned && Other.IsUnsigned) + return true; + return false; + } +}; + +} // end ento namespace +} // end clang namespace + +#endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h index d01644ba..1cc53d4 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h @@ -41,8 +41,6 @@ class AnalysisManager : public BugReporterData { CheckerManager *CheckerMgr; - enum AnalysisScope { ScopeTU, ScopeDecl } AScope; - /// \brief The maximum number of exploded nodes the analyzer will generate. unsigned MaxNodes; @@ -93,7 +91,7 @@ public: bool vizdot, bool vizubi, AnalysisPurgeMode purge, bool eager, bool trim, bool useUnoptimizedCFG, - bool addImplicitDtors, bool addInitializers, + bool addImplicitDtors, bool eagerlyTrimEGraph, AnalysisIPAMode ipa, unsigned inlineMaxStack, @@ -171,7 +169,7 @@ public: bool shouldEagerlyAssume() const { return EagerlyAssume; } - bool shouldInlineCall() const { return (IPAMode == Inlining); } + bool shouldInlineCall() const { return (IPAMode != None); } CFG *getCFG(Decl const *D) { return AnaCtxMgr.getContext(D)->getCFG(); @@ -190,10 +188,6 @@ public: return AnaCtxMgr.getContext(D); } - AnalysisDeclContext *getAnalysisDeclContext(const Decl *D, idx::TranslationUnit *TU) { - return AnaCtxMgr.getContext(D, TU); - } - }; } // enAnaCtxMgrspace diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index 9a699f9..b4a9de7 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -16,6 +16,7 @@ #ifndef LLVM_CLANG_GR_BASICVALUEFACTORY_H #define LLVM_CLANG_GR_BASICVALUEFACTORY_H +#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h" #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" @@ -86,28 +87,30 @@ public: const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned); const llvm::APSInt& getValue(uint64_t X, QualType T); + /// Returns the type of the APSInt used to store values of the given QualType. + APSIntType getAPSIntType(QualType T) const { + assert(T->isIntegerType() || Loc::isLocType(T)); + return APSIntType(Ctx.getTypeSize(T), + !T->isSignedIntegerOrEnumerationType()); + } + /// Convert - Create a new persistent APSInt with the same value as 'From' /// but with the bitwidth and signedness of 'To'. const llvm::APSInt &Convert(const llvm::APSInt& To, const llvm::APSInt& From) { - - if (To.isUnsigned() == From.isUnsigned() && - To.getBitWidth() == From.getBitWidth()) + APSIntType TargetType(To); + if (TargetType == APSIntType(From)) return From; - return getValue(From.getSExtValue(), To.getBitWidth(), To.isUnsigned()); + return getValue(TargetType.convert(From)); } const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) { - assert(T->isIntegerType() || Loc::isLocType(T)); - unsigned bitwidth = Ctx.getTypeSize(T); - bool isUnsigned - = T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T); - - if (isUnsigned == From.isUnsigned() && bitwidth == From.getBitWidth()) + APSIntType TargetType = getAPSIntType(T); + if (TargetType == APSIntType(From)) return From; - return getValue(From.getSExtValue(), bitwidth, isUnsigned); + return getValue(TargetType.convert(From)); } const llvm::APSInt& getIntValue(uint64_t X, bool isUnsigned) { @@ -116,25 +119,19 @@ public: } inline const llvm::APSInt& getMaxValue(const llvm::APSInt &v) { - return getValue(llvm::APSInt::getMaxValue(v.getBitWidth(), v.isUnsigned())); + return getValue(APSIntType(v).getMaxValue()); } inline const llvm::APSInt& getMinValue(const llvm::APSInt &v) { - return getValue(llvm::APSInt::getMinValue(v.getBitWidth(), v.isUnsigned())); + return getValue(APSIntType(v).getMinValue()); } inline const llvm::APSInt& getMaxValue(QualType T) { - assert(T->isIntegerType() || Loc::isLocType(T)); - bool isUnsigned - = T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T); - return getValue(llvm::APSInt::getMaxValue(Ctx.getTypeSize(T), isUnsigned)); + return getValue(getAPSIntType(T).getMaxValue()); } inline const llvm::APSInt& getMinValue(QualType T) { - assert(T->isIntegerType() || Loc::isLocType(T)); - bool isUnsigned - = T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T); - return getValue(llvm::APSInt::getMinValue(Ctx.getTypeSize(T), isUnsigned)); + return getValue(getAPSIntType(T).getMinValue()); } inline const llvm::APSInt& Add1(const llvm::APSInt& V) { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h new file mode 100644 index 0000000..47edfe9 --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -0,0 +1,962 @@ +//===- CallEvent.h - Wrapper for all function and method calls ----*- C++ -*--// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// \file This file defines CallEvent and its subclasses, which represent path- +/// sensitive instances of different kinds of function and method calls +/// (C, C++, and Objective-C). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_CALL +#define LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_CALL + +#include "clang/Basic/SourceManager.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "llvm/ADT/PointerIntPair.h" + +namespace clang { +class ProgramPoint; +class ProgramPointTag; + +namespace ento { + +enum CallEventKind { + CE_Function, + CE_Block, + CE_BEG_SIMPLE_CALLS = CE_Function, + CE_END_SIMPLE_CALLS = CE_Block, + CE_CXXMember, + CE_CXXMemberOperator, + CE_CXXDestructor, + CE_BEG_CXX_INSTANCE_CALLS = CE_CXXMember, + CE_END_CXX_INSTANCE_CALLS = CE_CXXDestructor, + CE_CXXConstructor, + CE_CXXAllocator, + CE_BEG_FUNCTION_CALLS = CE_Function, + CE_END_FUNCTION_CALLS = CE_CXXAllocator, + CE_ObjCMessage +}; + +class CallEvent; +class CallEventManager; + +template<typename T = CallEvent> +class CallEventRef : public IntrusiveRefCntPtr<const T> { +public: + CallEventRef(const T *Call) : IntrusiveRefCntPtr<const T>(Call) {} + CallEventRef(const CallEventRef &Orig) : IntrusiveRefCntPtr<const T>(Orig) {} + + CallEventRef<T> cloneWithState(ProgramStateRef State) const { + return this->getPtr()->template cloneWithState<T>(State); + } + + // Allow implicit conversions to a superclass type, since CallEventRef + // behaves like a pointer-to-const. + template <typename SuperT> + operator CallEventRef<SuperT> () const { + return this->getPtr(); + } +}; + +/// \brief Defines the runtime definition of the called function. +class RuntimeDefinition { + /// The Declaration of the function which will be called at runtime. + /// 0 if not available. + const Decl *D; + + /// The region representing an object (ObjC/C++) on which the method is + /// called. With dynamic dispatch, the method definition depends on the + /// runtime type of this object. 0 when there is no dynamic dispatch. + const MemRegion *R; + +public: + RuntimeDefinition(): D(0), R(0) {} + RuntimeDefinition(const Decl *InD): D(InD), R(0) {} + RuntimeDefinition(const Decl *InD, const MemRegion *InR): D(InD), R(InR) {} + const Decl *getDecl() { return D; } + const MemRegion *getDispatchRegion() { return R; } + bool mayHaveOtherDefinitions() { return R != 0; } +}; + +/// \brief Represents an abstract call to a function or method along a +/// particular path. +/// +/// CallEvents are created through the factory methods of CallEventManager. +/// +/// CallEvents should always be cheap to create and destroy. In order for +/// CallEventManager to be able to re-use CallEvent-sized memory blocks, +/// subclasses of CallEvent may not add any data members to the base class. +/// Use the "Data" and "Location" fields instead. +class CallEvent { +public: + typedef CallEventKind Kind; + +private: + ProgramStateRef State; + const LocationContext *LCtx; + llvm::PointerUnion<const Expr *, const Decl *> Origin; + + // DO NOT IMPLEMENT + CallEvent &operator=(const CallEvent &); + +protected: + // This is user data for subclasses. + const void *Data; + + // This is user data for subclasses. + // This should come right before RefCount, so that the two fields can be + // packed together on LP64 platforms. + SourceLocation Location; + +private: + mutable unsigned RefCount; + + template <typename T> friend struct llvm::IntrusiveRefCntPtrInfo; + void Retain() const { ++RefCount; } + void Release() const; + +protected: + friend class CallEventManager; + + CallEvent(const Expr *E, ProgramStateRef state, const LocationContext *lctx) + : State(state), LCtx(lctx), Origin(E), RefCount(0) {} + + CallEvent(const Decl *D, ProgramStateRef state, const LocationContext *lctx) + : State(state), LCtx(lctx), Origin(D), RefCount(0) {} + + // DO NOT MAKE PUBLIC + CallEvent(const CallEvent &Original) + : State(Original.State), LCtx(Original.LCtx), Origin(Original.Origin), + Data(Original.Data), Location(Original.Location), RefCount(0) {} + + + ProgramStateRef getState() const { + return State; + } + + const LocationContext *getLocationContext() const { + return LCtx; + } + + + /// Copies this CallEvent, with vtable intact, into a new block of memory. + virtual void cloneTo(void *Dest) const = 0; + + /// \brief Get the value of arbitrary expressions at this point in the path. + SVal getSVal(const Stmt *S) const { + return getState()->getSVal(S, getLocationContext()); + } + + + typedef SmallVectorImpl<const MemRegion *> RegionList; + + /// \brief Used to specify non-argument regions that will be invalidated as a + /// result of this call. + virtual void getExtraInvalidatedRegions(RegionList &Regions) const {} + + virtual QualType getDeclaredResultType() const = 0; + +public: + virtual ~CallEvent() {} + + /// \brief Returns the kind of call this is. + virtual Kind getKind() const = 0; + + /// \brief Returns the declaration of the function or method that will be + /// called. May be null. + virtual const Decl *getDecl() const { + return Origin.dyn_cast<const Decl *>(); + } + + /// \brief Returns the definition of the function or method that will be + /// called. + virtual RuntimeDefinition getRuntimeDefinition() const = 0; + + /// \brief Returns the expression whose value will be the result of this call. + /// May be null. + const Expr *getOriginExpr() const { + return Origin.dyn_cast<const Expr *>(); + } + + /// \brief Returns the number of arguments (explicit and implicit). + /// + /// Note that this may be greater than the number of parameters in the + /// callee's declaration, and that it may include arguments not written in + /// the source. + virtual unsigned getNumArgs() const = 0; + + /// \brief Returns true if the callee is known to be from a system header. + bool isInSystemHeader() const { + const Decl *D = getDecl(); + if (!D) + return false; + + SourceLocation Loc = D->getLocation(); + if (Loc.isValid()) { + const SourceManager &SM = + getState()->getStateManager().getContext().getSourceManager(); + return SM.isInSystemHeader(D->getLocation()); + } + + // Special case for implicitly-declared global operator new/delete. + // These should be considered system functions. + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + return FD->isOverloadedOperator() && FD->isImplicit() && FD->isGlobal(); + + return false; + } + + /// \brief Returns a source range for the entire call, suitable for + /// outputting in diagnostics. + virtual SourceRange getSourceRange() const { + return getOriginExpr()->getSourceRange(); + } + + /// \brief Returns the value of a given argument at the time of the call. + virtual SVal getArgSVal(unsigned Index) const; + + /// \brief Returns the expression associated with a given argument. + /// May be null if this expression does not appear in the source. + virtual const Expr *getArgExpr(unsigned Index) const { return 0; } + + /// \brief Returns the source range for errors associated with this argument. + /// + /// May be invalid if the argument is not written in the source. + virtual SourceRange getArgSourceRange(unsigned Index) const; + + /// \brief Returns the result type, adjusted for references. + QualType getResultType() const; + + /// \brief Returns true if any of the arguments appear to represent callbacks. + bool hasNonZeroCallbackArg() const; + + /// \brief Returns true if any of the arguments are known to escape to long- + /// term storage, even if this method will not modify them. + // NOTE: The exact semantics of this are still being defined! + // We don't really want a list of hardcoded exceptions in the long run, + // but we don't want duplicated lists of known APIs in the short term either. + virtual bool argumentsMayEscape() const { + return hasNonZeroCallbackArg(); + } + + /// \brief Returns an appropriate ProgramPoint for this call. + ProgramPoint getProgramPoint(bool IsPreVisit = false, + const ProgramPointTag *Tag = 0) const; + + /// \brief Returns a new state with all argument regions invalidated. + /// + /// This accepts an alternate state in case some processing has already + /// occurred. + ProgramStateRef invalidateRegions(unsigned BlockCount, + ProgramStateRef Orig = 0) const; + + typedef std::pair<Loc, SVal> FrameBindingTy; + typedef SmallVectorImpl<FrameBindingTy> BindingsTy; + + /// Populates the given SmallVector with the bindings in the callee's stack + /// frame at the start of this call. + virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const = 0; + + /// Returns a copy of this CallEvent, but using the given state. + template <typename T> + CallEventRef<T> cloneWithState(ProgramStateRef NewState) const; + + /// Returns a copy of this CallEvent, but using the given state. + CallEventRef<> cloneWithState(ProgramStateRef NewState) const { + return cloneWithState<CallEvent>(NewState); + } + + /// \brief Returns true if this is a statement that can be considered for + /// inlining. + /// + /// FIXME: This should go away once CallEvents are cheap and easy to + /// construct from ExplodedNodes. + static bool mayBeInlined(const Stmt *S); + + // Iterator access to formal parameters and their types. +private: + typedef std::const_mem_fun_t<QualType, ParmVarDecl> get_type_fun; + +public: + typedef const ParmVarDecl * const *param_iterator; + + /// Returns an iterator over the call's formal parameters. + /// + /// If UseDefinitionParams is set, this will return the parameter decls + /// used in the callee's definition (suitable for inlining). Most of the + /// time it is better to use the decl found by name lookup, which likely + /// carries more annotations. + /// + /// Remember that the number of formal parameters may not match the number + /// of arguments for all calls. However, the first parameter will always + /// correspond with the argument value returned by \c getArgSVal(0). + /// + /// If the call has no accessible declaration (or definition, if + /// \p UseDefinitionParams is set), \c param_begin() will be equal to + /// \c param_end(). + virtual param_iterator param_begin() const =0; + /// \sa param_begin() + virtual param_iterator param_end() const = 0; + + typedef llvm::mapped_iterator<param_iterator, get_type_fun> + param_type_iterator; + + /// Returns an iterator over the types of the call's formal parameters. + /// + /// This uses the callee decl found by default name lookup rather than the + /// definition because it represents a public interface, and probably has + /// more annotations. + param_type_iterator param_type_begin() const { + return llvm::map_iterator(param_begin(), + get_type_fun(&ParmVarDecl::getType)); + } + /// \sa param_type_begin() + param_type_iterator param_type_end() const { + return llvm::map_iterator(param_end(), get_type_fun(&ParmVarDecl::getType)); + } + + // For debugging purposes only + void dump(raw_ostream &Out) const; + LLVM_ATTRIBUTE_USED void dump() const { dump(llvm::errs()); } + + static bool classof(const CallEvent *) { return true; } +}; + + +/// \brief Represents a call to any sort of function that might have a +/// FunctionDecl. +class AnyFunctionCall : public CallEvent { +protected: + AnyFunctionCall(const Expr *E, ProgramStateRef St, + const LocationContext *LCtx) + : CallEvent(E, St, LCtx) {} + AnyFunctionCall(const Decl *D, ProgramStateRef St, + const LocationContext *LCtx) + : CallEvent(D, St, LCtx) {} + AnyFunctionCall(const AnyFunctionCall &Other) : CallEvent(Other) {} + + virtual QualType getDeclaredResultType() const; + +public: + // This function is overridden by subclasses, but they must return + // a FunctionDecl. + virtual const FunctionDecl *getDecl() const { + return cast<FunctionDecl>(CallEvent::getDecl()); + } + + virtual RuntimeDefinition getRuntimeDefinition() const { + const FunctionDecl *FD = getDecl(); + // Note that hasBody() will fill FD with the definition FunctionDecl. + if (FD && FD->hasBody(FD)) + return RuntimeDefinition(FD); + return RuntimeDefinition(); + } + + virtual bool argumentsMayEscape() const; + + virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const; + + virtual param_iterator param_begin() const; + virtual param_iterator param_end() const; + + static bool classof(const CallEvent *CA) { + return CA->getKind() >= CE_BEG_FUNCTION_CALLS && + CA->getKind() <= CE_END_FUNCTION_CALLS; + } +}; + +/// \brief Represents a call to a non-C++ function, written as a CallExpr. +class SimpleCall : public AnyFunctionCall { +protected: + SimpleCall(const CallExpr *CE, ProgramStateRef St, + const LocationContext *LCtx) + : AnyFunctionCall(CE, St, LCtx) {} + SimpleCall(const SimpleCall &Other) : AnyFunctionCall(Other) {} + +public: + virtual const CallExpr *getOriginExpr() const { + return cast<CallExpr>(AnyFunctionCall::getOriginExpr()); + } + + virtual const FunctionDecl *getDecl() const; + + virtual unsigned getNumArgs() const { return getOriginExpr()->getNumArgs(); } + + virtual const Expr *getArgExpr(unsigned Index) const { + return getOriginExpr()->getArg(Index); + } + + static bool classof(const CallEvent *CA) { + return CA->getKind() >= CE_BEG_SIMPLE_CALLS && + CA->getKind() <= CE_END_SIMPLE_CALLS; + } +}; + +/// \brief Represents a C function or static C++ member function call. +/// +/// Example: \c fun() +class FunctionCall : public SimpleCall { + friend class CallEventManager; + +protected: + FunctionCall(const CallExpr *CE, ProgramStateRef St, + const LocationContext *LCtx) + : SimpleCall(CE, St, LCtx) {} + + FunctionCall(const FunctionCall &Other) : SimpleCall(Other) {} + virtual void cloneTo(void *Dest) const { new (Dest) FunctionCall(*this); } + +public: + virtual Kind getKind() const { return CE_Function; } + + static bool classof(const CallEvent *CA) { + return CA->getKind() == CE_Function; + } +}; + +/// \brief Represents a call to a block. +/// +/// Example: <tt>^{ /* ... */ }()</tt> +class BlockCall : public SimpleCall { + friend class CallEventManager; + +protected: + BlockCall(const CallExpr *CE, ProgramStateRef St, + const LocationContext *LCtx) + : SimpleCall(CE, St, LCtx) {} + + BlockCall(const BlockCall &Other) : SimpleCall(Other) {} + virtual void cloneTo(void *Dest) const { new (Dest) BlockCall(*this); } + + virtual void getExtraInvalidatedRegions(RegionList &Regions) const; + + virtual QualType getDeclaredResultType() const; + +public: + /// \brief Returns the region associated with this instance of the block. + /// + /// This may be NULL if the block's origin is unknown. + const BlockDataRegion *getBlockRegion() const; + + /// \brief Gets the declaration of the block. + /// + /// This is not an override of getDecl() because AnyFunctionCall has already + /// assumed that it's a FunctionDecl. + const BlockDecl *getBlockDecl() const { + const BlockDataRegion *BR = getBlockRegion(); + if (!BR) + return 0; + return BR->getDecl(); + } + + virtual RuntimeDefinition getRuntimeDefinition() const { + return RuntimeDefinition(getBlockDecl()); + } + + virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const; + + virtual param_iterator param_begin() const; + virtual param_iterator param_end() const; + + virtual Kind getKind() const { return CE_Block; } + + static bool classof(const CallEvent *CA) { + return CA->getKind() == CE_Block; + } +}; + +/// \brief Represents a non-static C++ member function call, no matter how +/// it is written. +class CXXInstanceCall : public AnyFunctionCall { +protected: + virtual void getExtraInvalidatedRegions(RegionList &Regions) const; + + CXXInstanceCall(const CallExpr *CE, ProgramStateRef St, + const LocationContext *LCtx) + : AnyFunctionCall(CE, St, LCtx) {} + CXXInstanceCall(const FunctionDecl *D, ProgramStateRef St, + const LocationContext *LCtx) + : AnyFunctionCall(D, St, LCtx) {} + + + CXXInstanceCall(const CXXInstanceCall &Other) : AnyFunctionCall(Other) {} + +public: + /// \brief Returns the expression representing the implicit 'this' object. + virtual const Expr *getCXXThisExpr() const { return 0; } + + /// \brief Returns the value of the implicit 'this' object. + virtual SVal getCXXThisVal() const { + const Expr *Base = getCXXThisExpr(); + // FIXME: This doesn't handle an overloaded ->* operator. + if (!Base) + return UnknownVal(); + return getSVal(Base); + } + + virtual const FunctionDecl *getDecl() const; + + virtual RuntimeDefinition getRuntimeDefinition() const; + + virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const; + + static bool classof(const CallEvent *CA) { + return CA->getKind() >= CE_BEG_CXX_INSTANCE_CALLS && + CA->getKind() <= CE_END_CXX_INSTANCE_CALLS; + } +}; + +/// \brief Represents a non-static C++ member function call. +/// +/// Example: \c obj.fun() +class CXXMemberCall : public CXXInstanceCall { + friend class CallEventManager; + +protected: + CXXMemberCall(const CXXMemberCallExpr *CE, ProgramStateRef St, + const LocationContext *LCtx) + : CXXInstanceCall(CE, St, LCtx) {} + + CXXMemberCall(const CXXMemberCall &Other) : CXXInstanceCall(Other) {} + virtual void cloneTo(void *Dest) const { new (Dest) CXXMemberCall(*this); } + +public: + virtual const CXXMemberCallExpr *getOriginExpr() const { + return cast<CXXMemberCallExpr>(CXXInstanceCall::getOriginExpr()); + } + + virtual unsigned getNumArgs() const { + if (const CallExpr *CE = getOriginExpr()) + return CE->getNumArgs(); + return 0; + } + + virtual const Expr *getArgExpr(unsigned Index) const { + return getOriginExpr()->getArg(Index); + } + + virtual const Expr *getCXXThisExpr() const; + + virtual Kind getKind() const { return CE_CXXMember; } + + static bool classof(const CallEvent *CA) { + return CA->getKind() == CE_CXXMember; + } +}; + +/// \brief Represents a C++ overloaded operator call where the operator is +/// implemented as a non-static member function. +/// +/// Example: <tt>iter + 1</tt> +class CXXMemberOperatorCall : public CXXInstanceCall { + friend class CallEventManager; + +protected: + CXXMemberOperatorCall(const CXXOperatorCallExpr *CE, ProgramStateRef St, + const LocationContext *LCtx) + : CXXInstanceCall(CE, St, LCtx) {} + + CXXMemberOperatorCall(const CXXMemberOperatorCall &Other) + : CXXInstanceCall(Other) {} + virtual void cloneTo(void *Dest) const { + new (Dest) CXXMemberOperatorCall(*this); + } + +public: + virtual const CXXOperatorCallExpr *getOriginExpr() const { + return cast<CXXOperatorCallExpr>(CXXInstanceCall::getOriginExpr()); + } + + virtual unsigned getNumArgs() const { + return getOriginExpr()->getNumArgs() - 1; + } + virtual const Expr *getArgExpr(unsigned Index) const { + return getOriginExpr()->getArg(Index + 1); + } + + virtual const Expr *getCXXThisExpr() const; + + virtual Kind getKind() const { return CE_CXXMemberOperator; } + + static bool classof(const CallEvent *CA) { + return CA->getKind() == CE_CXXMemberOperator; + } +}; + +/// \brief Represents an implicit call to a C++ destructor. +/// +/// This can occur at the end of a scope (for automatic objects), at the end +/// of a full-expression (for temporaries), or as part of a delete. +class CXXDestructorCall : public CXXInstanceCall { + friend class CallEventManager; + +protected: + /// Creates an implicit destructor. + /// + /// \param DD The destructor that will be called. + /// \param Trigger The statement whose completion causes this destructor call. + /// \param Target The object region to be destructed. + /// \param St The path-sensitive state at this point in the program. + /// \param LCtx The location context at this point in the program. + CXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger, + const MemRegion *Target, ProgramStateRef St, + const LocationContext *LCtx) + : CXXInstanceCall(DD, St, LCtx) { + Data = Target; + Location = Trigger->getLocEnd(); + } + + CXXDestructorCall(const CXXDestructorCall &Other) : CXXInstanceCall(Other) {} + virtual void cloneTo(void *Dest) const { new (Dest) CXXDestructorCall(*this); } + +public: + virtual SourceRange getSourceRange() const { return Location; } + virtual unsigned getNumArgs() const { return 0; } + + /// \brief Returns the value of the implicit 'this' object. + virtual SVal getCXXThisVal() const; + + virtual Kind getKind() const { return CE_CXXDestructor; } + + static bool classof(const CallEvent *CA) { + return CA->getKind() == CE_CXXDestructor; + } +}; + +/// \brief Represents a call to a C++ constructor. +/// +/// Example: \c T(1) +class CXXConstructorCall : public AnyFunctionCall { + friend class CallEventManager; + +protected: + /// Creates a constructor call. + /// + /// \param CE The constructor expression as written in the source. + /// \param Target The region where the object should be constructed. If NULL, + /// a new symbolic region will be used. + /// \param St The path-sensitive state at this point in the program. + /// \param LCtx The location context at this point in the program. + CXXConstructorCall(const CXXConstructExpr *CE, const MemRegion *target, + ProgramStateRef St, const LocationContext *LCtx) + : AnyFunctionCall(CE, St, LCtx) { + Data = target; + } + + CXXConstructorCall(const CXXConstructorCall &Other) : AnyFunctionCall(Other){} + virtual void cloneTo(void *Dest) const { new (Dest) CXXConstructorCall(*this); } + + virtual void getExtraInvalidatedRegions(RegionList &Regions) const; + +public: + virtual const CXXConstructExpr *getOriginExpr() const { + return cast<CXXConstructExpr>(AnyFunctionCall::getOriginExpr()); + } + + virtual const CXXConstructorDecl *getDecl() const { + return getOriginExpr()->getConstructor(); + } + + virtual unsigned getNumArgs() const { return getOriginExpr()->getNumArgs(); } + + virtual const Expr *getArgExpr(unsigned Index) const { + return getOriginExpr()->getArg(Index); + } + + /// \brief Returns the value of the implicit 'this' object. + SVal getCXXThisVal() const; + + virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const; + + virtual Kind getKind() const { return CE_CXXConstructor; } + + static bool classof(const CallEvent *CA) { + return CA->getKind() == CE_CXXConstructor; + } +}; + +/// \brief Represents the memory allocation call in a C++ new-expression. +/// +/// This is a call to "operator new". +class CXXAllocatorCall : public AnyFunctionCall { + friend class CallEventManager; + +protected: + CXXAllocatorCall(const CXXNewExpr *E, ProgramStateRef St, + const LocationContext *LCtx) + : AnyFunctionCall(E, St, LCtx) {} + + CXXAllocatorCall(const CXXAllocatorCall &Other) : AnyFunctionCall(Other) {} + virtual void cloneTo(void *Dest) const { new (Dest) CXXAllocatorCall(*this); } + +public: + virtual const CXXNewExpr *getOriginExpr() const { + return cast<CXXNewExpr>(AnyFunctionCall::getOriginExpr()); + } + + virtual const FunctionDecl *getDecl() const { + return getOriginExpr()->getOperatorNew(); + } + + virtual unsigned getNumArgs() const { + return getOriginExpr()->getNumPlacementArgs() + 1; + } + + virtual const Expr *getArgExpr(unsigned Index) const { + // The first argument of an allocator call is the size of the allocation. + if (Index == 0) + return 0; + return getOriginExpr()->getPlacementArg(Index - 1); + } + + virtual Kind getKind() const { return CE_CXXAllocator; } + + static bool classof(const CallEvent *CE) { + return CE->getKind() == CE_CXXAllocator; + } +}; + +/// \brief Represents the ways an Objective-C message send can occur. +// +// Note to maintainers: OCM_Message should always be last, since it does not +// need to fit in the Data field's low bits. +enum ObjCMessageKind { + OCM_PropertyAccess, + OCM_Subscript, + OCM_Message +}; + +/// \brief Represents any expression that calls an Objective-C method. +/// +/// This includes all of the kinds listed in ObjCMessageKind. +class ObjCMethodCall : public CallEvent { + friend class CallEventManager; + + const PseudoObjectExpr *getContainingPseudoObjectExpr() const; + +protected: + ObjCMethodCall(const ObjCMessageExpr *Msg, ProgramStateRef St, + const LocationContext *LCtx) + : CallEvent(Msg, St, LCtx) { + Data = 0; + } + + ObjCMethodCall(const ObjCMethodCall &Other) : CallEvent(Other) {} + virtual void cloneTo(void *Dest) const { new (Dest) ObjCMethodCall(*this); } + + virtual void getExtraInvalidatedRegions(RegionList &Regions) const; + + virtual QualType getDeclaredResultType() const; + + /// Check if the selector may have multiple definitions (may have overrides). + virtual bool canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl, + Selector Sel) const; + +public: + virtual const ObjCMessageExpr *getOriginExpr() const { + return cast<ObjCMessageExpr>(CallEvent::getOriginExpr()); + } + virtual const ObjCMethodDecl *getDecl() const { + return getOriginExpr()->getMethodDecl(); + } + virtual unsigned getNumArgs() const { + return getOriginExpr()->getNumArgs(); + } + virtual const Expr *getArgExpr(unsigned Index) const { + return getOriginExpr()->getArg(Index); + } + + bool isInstanceMessage() const { + return getOriginExpr()->isInstanceMessage(); + } + ObjCMethodFamily getMethodFamily() const { + return getOriginExpr()->getMethodFamily(); + } + Selector getSelector() const { + return getOriginExpr()->getSelector(); + } + + virtual SourceRange getSourceRange() const; + + /// \brief Returns the value of the receiver at the time of this call. + SVal getReceiverSVal() const; + + /// \brief Get the interface for the receiver. + /// + /// This works whether this is an instance message or a class message. + /// However, it currently just uses the static type of the receiver. + const ObjCInterfaceDecl *getReceiverInterface() const { + return getOriginExpr()->getReceiverInterface(); + } + + ObjCMessageKind getMessageKind() const; + + bool isSetter() const { + switch (getMessageKind()) { + case OCM_Message: + llvm_unreachable("This is not a pseudo-object access!"); + case OCM_PropertyAccess: + return getNumArgs() > 0; + case OCM_Subscript: + return getNumArgs() > 1; + } + llvm_unreachable("Unknown message kind"); + } + + virtual RuntimeDefinition getRuntimeDefinition() const; + + virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const; + + virtual param_iterator param_begin() const; + virtual param_iterator param_end() const; + + virtual Kind getKind() const { return CE_ObjCMessage; } + + static bool classof(const CallEvent *CA) { + return CA->getKind() == CE_ObjCMessage; + } +}; + + +/// \brief Manages the lifetime of CallEvent objects. +/// +/// CallEventManager provides a way to create arbitrary CallEvents "on the +/// stack" as if they were value objects by keeping a cache of CallEvent-sized +/// memory blocks. The CallEvents created by CallEventManager are only valid +/// for the lifetime of the OwnedCallEvent that holds them; right now these +/// objects cannot be copied and ownership cannot be transferred. +class CallEventManager { + friend class CallEvent; + + llvm::BumpPtrAllocator &Alloc; + SmallVector<void *, 8> Cache; + + void reclaim(const void *Memory) { + Cache.push_back(const_cast<void *>(Memory)); + } + + /// Returns memory that can be initialized as a CallEvent. + void *allocate() { + if (Cache.empty()) + return Alloc.Allocate<FunctionCall>(); + else + return Cache.pop_back_val(); + } + + template <typename T, typename Arg> + T *create(Arg A, ProgramStateRef St, const LocationContext *LCtx) { + return new (allocate()) T(A, St, LCtx); + } + + template <typename T, typename Arg1, typename Arg2> + T *create(Arg1 A1, Arg2 A2, ProgramStateRef St, const LocationContext *LCtx) { + return new (allocate()) T(A1, A2, St, LCtx); + } + + template <typename T, typename Arg1, typename Arg2, typename Arg3> + T *create(Arg1 A1, Arg2 A2, Arg3 A3, ProgramStateRef St, + const LocationContext *LCtx) { + return new (allocate()) T(A1, A2, A3, St, LCtx); + } + +public: + CallEventManager(llvm::BumpPtrAllocator &alloc) : Alloc(alloc) {} + + + CallEventRef<> + getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State); + + + CallEventRef<> + getSimpleCall(const CallExpr *E, ProgramStateRef State, + const LocationContext *LCtx); + + CallEventRef<ObjCMethodCall> + getObjCMethodCall(const ObjCMessageExpr *E, ProgramStateRef State, + const LocationContext *LCtx) { + return create<ObjCMethodCall>(E, State, LCtx); + } + + CallEventRef<CXXConstructorCall> + getCXXConstructorCall(const CXXConstructExpr *E, const MemRegion *Target, + ProgramStateRef State, const LocationContext *LCtx) { + return create<CXXConstructorCall>(E, Target, State, LCtx); + } + + CallEventRef<CXXDestructorCall> + getCXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger, + const MemRegion *Target, ProgramStateRef State, + const LocationContext *LCtx) { + return create<CXXDestructorCall>(DD, Trigger, Target, State, LCtx); + } + + CallEventRef<CXXAllocatorCall> + getCXXAllocatorCall(const CXXNewExpr *E, ProgramStateRef State, + const LocationContext *LCtx) { + return create<CXXAllocatorCall>(E, State, LCtx); + } +}; + + +template <typename T> +CallEventRef<T> CallEvent::cloneWithState(ProgramStateRef NewState) const { + assert(isa<T>(*this) && "Cloning to unrelated type"); + assert(sizeof(T) == sizeof(CallEvent) && "Subclasses may not add fields"); + + if (NewState == State) + return cast<T>(this); + + CallEventManager &Mgr = State->getStateManager().getCallEventManager(); + T *Copy = static_cast<T *>(Mgr.allocate()); + cloneTo(Copy); + assert(Copy->getKind() == this->getKind() && "Bad copy"); + + Copy->State = NewState; + return Copy; +} + +inline void CallEvent::Release() const { + assert(RefCount > 0 && "Reference count is already zero."); + --RefCount; + + if (RefCount > 0) + return; + + CallEventManager &Mgr = State->getStateManager().getCallEventManager(); + Mgr.reclaim(this); + + this->~CallEvent(); +} + +} // end namespace ento +} // end namespace clang + +namespace llvm { + // Support isa<>, cast<>, and dyn_cast<> for CallEventRef. + template<class T> struct simplify_type< clang::ento::CallEventRef<T> > { + typedef const T *SimpleType; + + static SimpleType + getSimplifiedValue(const clang::ento::CallEventRef<T>& Val) { + return Val.getPtr(); + } + }; +} + +#endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index b051d33..8c8e82c 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -92,6 +92,10 @@ public: return Pred->getLocationContext(); } + const StackFrameContext *getStackFrame() const { + return Pred->getStackFrame(); + } + BugReporter &getBugReporter() { return Eng.getBugReporter(); } @@ -132,6 +136,11 @@ public: return 0; } + /// \brief Get the value of arbitrary expressions at this point in the path. + SVal getSVal(const Stmt *S) const { + return getState()->getSVal(S, getLocationContext()); + } + /// \brief Generates a new transition in the program state graph /// (ExplodedGraph). Uses the default CheckerContext predecessor node. /// diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 59136fc..e75cdd8 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -65,7 +65,7 @@ private: /// WList - A set of queued nodes that need to be processed by the /// worklist algorithm. It is up to the implementation of WList to decide /// the order that nodes are processed. - WorkList* WList; + OwningPtr<WorkList> WList; /// BCounterFactory - A factory object for created BlockCounter objects. /// These are used to record for key nodes in the ExplodedGraph the @@ -104,23 +104,18 @@ private: CoreEngine(const CoreEngine&); // Do not implement. CoreEngine& operator=(const CoreEngine&); - ExplodedNode *generateCallExitNode(ExplodedNode *N); + ExplodedNode *generateCallExitBeginNode(ExplodedNode *N); public: - /// Construct a CoreEngine object to analyze the provided CFG using - /// a DFS exploration of the exploded graph. + /// Construct a CoreEngine object to analyze the provided CFG. CoreEngine(SubEngine& subengine, SetOfConstDecls *VisitedCallees, FunctionSummariesTy *FS) : SubEng(subengine), G(new ExplodedGraph()), - WList(WorkList::makeBFS()), + WList(WorkList::makeDFS()), BCounterFactory(G->getAllocator()), AnalyzedCallees(VisitedCallees), FunctionSummaries(FS){} - ~CoreEngine() { - delete WList; - } - /// getGraph - Returns the exploded graph. ExplodedGraph& getGraph() { return *G.get(); } @@ -156,7 +151,7 @@ public: blocksAborted.push_back(std::make_pair(block, node)); } - WorkList *getWorkList() const { return WList; } + WorkList *getWorkList() const { return WList.get(); } BlocksExhausted::const_iterator blocks_exhausted_begin() const { return blocksExhausted.begin(); @@ -188,10 +183,10 @@ public: // TODO: Turn into a calss. struct NodeBuilderContext { - CoreEngine &Eng; + const CoreEngine &Eng; const CFGBlock *Block; ExplodedNode *Pred; - NodeBuilderContext(CoreEngine &E, const CFGBlock *B, ExplodedNode *N) + NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, ExplodedNode *N) : Eng(E), Block(B), Pred(N) { assert(B); assert(!N->isSink()); } ExplodedNode *getPred() const { return Pred; } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h index 46fbb88..1052d94 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h @@ -133,6 +133,10 @@ public: return getLocation().getLocationContext(); } + const StackFrameContext *getStackFrame() const { + return getLocationContext()->getCurrentStackFrame(); + } + const Decl &getCodeDecl() const { return *getLocationContext()->getDecl(); } CFG &getCFG() const { return *getLocationContext()->getCFG(); } @@ -151,7 +155,7 @@ public: static void Profile(llvm::FoldingSetNodeID &ID, const ProgramPoint &Loc, - ProgramStateRef state, + const ProgramStateRef &state, bool IsSink) { ID.Add(Loc); ID.AddPointer(state.getPtr()); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 2a21a03..4addb9d 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -41,8 +41,8 @@ class ObjCForCollectionStmt; namespace ento { class AnalysisManager; -class CallOrObjCMessage; -class ObjCMessage; +class CallEvent; +class SimpleCall; class ExprEngine : public SubEngine { AnalysisManager &AMgr; @@ -151,6 +151,25 @@ public: ExplodedGraph& getGraph() { return G; } const ExplodedGraph& getGraph() const { return G; } + /// \brief Run the analyzer's garbage collection - remove dead symbols and + /// bindings. + /// + /// \param Node - The predecessor node, from which the processing should + /// start. + /// \param Out - The returned set of output nodes. + /// \param ReferenceStmt - Run garbage collection using the symbols, + /// which are live before the given statement. + /// \param LC - The location context of the ReferenceStmt. + /// \param DiagnosticStmt - the statement used to associate the diagnostic + /// message, if any warnings should occur while removing the dead (leaks + /// are usually reported here). + /// \param K - In some cases it is possible to use PreStmt kind. (Do + /// not use it unless you know what you are doing.) + void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out, + const Stmt *ReferenceStmt, const LocationContext *LC, + const Stmt *DiagnosticStmt, + ProgramPoint::Kind K = ProgramPoint::PreStmtPurgeDeadSymbolsKind); + /// processCFGElement - Called by CoreEngine. Used to generate new successor /// nodes by processing the 'effects' of a CFG element. void processCFGElement(const CFGElement E, ExplodedNode *Pred, @@ -199,7 +218,8 @@ public: /// Generate the entry node of the callee. void processCallEnter(CallEnter CE, ExplodedNode *Pred); - /// Generate the first post callsite node. + /// Generate the sequence of nodes that simulate the call exit and the post + /// visit for CallExpr. void processCallExit(ExplodedNode *Pred); /// Called by CoreEngine when the analysis worklist has terminated. @@ -220,7 +240,7 @@ public: const StoreManager::InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> ExplicitRegions, ArrayRef<const MemRegion *> Regions, - const CallOrObjCMessage *Call); + const CallEvent *Call); /// printState - Called by ProgramStateManager to print checker-specific data. void printState(raw_ostream &Out, ProgramStateRef State, @@ -265,6 +285,10 @@ public: /// VisitAsmStmt - Transfer function logic for inline asm. void VisitAsmStmt(const AsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst); + + /// VisitMSAsmStmt - Transfer function logic for MS inline asm. + void VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred, + ExplodedNodeSet &Dst); /// VisitBlockExpr - Transfer function logic for BlockExprs. void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, @@ -323,7 +347,7 @@ public: void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst); - void VisitObjCMessage(const ObjCMessage &msg, ExplodedNode *Pred, + void VisitObjCMessage(const ObjCMessageExpr *ME, ExplodedNode *Pred, ExplodedNodeSet &Dst); /// VisitReturnStmt - Transfer function logic for return statements. @@ -353,13 +377,10 @@ public: void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, ExplodedNodeSet & Dst); - void VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr, - ExplodedNode *Pred, ExplodedNodeSet &Dst); - - void VisitCXXConstructExpr(const CXXConstructExpr *E, const MemRegion *Dest, - ExplodedNode *Pred, ExplodedNodeSet &Dst); + void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred, + ExplodedNodeSet &Dst); - void VisitCXXDestructor(const CXXDestructorDecl *DD, + void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest, const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst); @@ -373,13 +394,6 @@ public: void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, ExplodedNode *Pred, ExplodedNodeSet &Dst); - - /// Synthesize CXXThisRegion. - const CXXThisRegion *getCXXThisRegion(const CXXRecordDecl *RD, - const StackFrameContext *SFC); - - const CXXThisRegion *getCXXThisRegion(const CXXMethodDecl *decl, - const StackFrameContext *frameCtx); /// evalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic /// expressions of the form 'x != 0' and generate new nodes (stored in Dst) @@ -416,19 +430,6 @@ public: } protected: - void evalObjCMessage(StmtNodeBuilder &Bldr, const ObjCMessage &msg, - ExplodedNode *Pred, ProgramStateRef state, - bool GenSink); - - ProgramStateRef invalidateArguments(ProgramStateRef State, - const CallOrObjCMessage &Call, - const LocationContext *LC); - - ProgramStateRef MarkBranch(ProgramStateRef state, - const Stmt *Terminator, - const LocationContext *LCtx, - bool branchTaken); - /// evalBind - Handle the semantics of binding a value to a specific location. /// This method is used by evalStore, VisitDeclStmt, and others. void evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, ExplodedNode *Pred, @@ -455,6 +456,21 @@ public: void evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE, ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val, const ProgramPointTag *tag = 0); + + /// \brief Create a new state in which the call return value is binded to the + /// call origin expression. + ProgramStateRef bindReturnValue(const CallEvent &Call, + const LocationContext *LCtx, + ProgramStateRef State); + + /// Evaluate a call, running pre- and post-call checks and allowing checkers + /// to be responsible for handling the evaluation of the call itself. + void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred, + const CallEvent &Call); + + /// \brief Default implementation of call evaluation. + void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred, + const CallEvent &Call); private: void evalLoadCommon(ExplodedNodeSet &Dst, const Expr *NodeEx, /* Eventually will be a CFGStmt */ @@ -474,8 +490,20 @@ private: ProgramStateRef St, SVal location, const ProgramPointTag *tag, bool isLoad); - bool shouldInlineDecl(const FunctionDecl *FD, ExplodedNode *Pred); - bool InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, ExplodedNode *Pred); + bool shouldInlineDecl(const Decl *D, ExplodedNode *Pred); + bool inlineCall(const CallEvent &Call, const Decl *D, NodeBuilder &Bldr, + ExplodedNode *Pred, ProgramStateRef State); + + /// \brief Conservatively evaluate call by invalidating regions and binding + /// a conjured return value. + void conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr, + ExplodedNode *Pred, ProgramStateRef State); + + /// \brief Either inline or process the call conservatively (or both), based + /// on DynamicDispatchBifurcation data. + void BifurcateCall(const MemRegion *BifurReg, + const CallEvent &Call, const Decl *D, NodeBuilder &Bldr, + ExplodedNode *Pred); bool replayWithoutInlining(ExplodedNode *P, const LocationContext *CalleeLC); }; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h b/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h index 42adff3..cf4a692 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h @@ -14,15 +14,16 @@ #ifndef LLVM_CLANG_GR_FUNCTIONSUMMARY_H #define LLVM_CLANG_GR_FUNCTIONSUMMARY_H +#include <deque> #include "clang/AST/Decl.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/BitVector.h" namespace clang { namespace ento { -typedef llvm::SmallPtrSet<Decl*, 24> SetOfDecls; -typedef llvm::SmallPtrSet<const Decl*, 24> SetOfConstDecls; +typedef std::deque<Decl*> SetOfDecls; +typedef llvm::DenseSet<const Decl*> SetOfConstDecls; class FunctionSummariesTy { struct FunctionSummary { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index 87bc0df..01218ef 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -16,6 +16,7 @@ #ifndef LLVM_CLANG_GR_MEMREGION_H #define LLVM_CLANG_GR_MEMREGION_H +#include "clang/AST/ASTContext.h" #include "clang/AST/CharUnits.h" #include "clang/AST/Decl.h" #include "clang/AST/ExprObjC.h" @@ -51,11 +52,21 @@ class RegionOffset { int64_t Offset; public: - RegionOffset(const MemRegion *r) : R(r), Offset(0) {} + enum { Symbolic = INT64_MAX }; + + RegionOffset() : R(0) {} RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {} const MemRegion *getRegion() const { return R; } - int64_t getOffset() const { return Offset; } + + bool hasSymbolicOffset() const { return Offset == Symbolic; } + + int64_t getOffset() const { + assert(!hasSymbolicOffset()); + return Offset; + } + + bool isValid() const { return R; } }; //===----------------------------------------------------------------------===// @@ -127,7 +138,7 @@ public: const MemRegion *getBaseRegion() const; - const MemRegion *StripCasts() const; + const MemRegion *StripCasts(bool StripBaseCasts = true) const; bool hasGlobalsOrParametersStorage() const; @@ -147,8 +158,11 @@ public: void dump() const; + /// \brief Returns true if this region can be printed in a user-friendly way. + virtual bool canPrintPretty() const; + /// \brief Print the region for use in diagnostics. - virtual void dumpPretty(raw_ostream &os) const; + virtual void printPretty(raw_ostream &os) const; Kind getKind() const { return kind; } @@ -197,8 +211,9 @@ public: } }; -/// \class The region of the static variables within the current CodeTextRegion +/// \brief The region of the static variables within the current CodeTextRegion /// scope. +/// /// Currently, only the static locals are placed there, so we know that these /// variables do not get invalidated by calls to other functions. class StaticGlobalSpaceRegion : public GlobalsSpaceRegion { @@ -221,7 +236,7 @@ public: } }; -/// \class The region for all the non-static global variables. +/// \brief The region for all the non-static global variables. /// /// This class is further split into subclasses for efficient implementation of /// invalidating a set of related global values as is done in @@ -236,8 +251,6 @@ protected: public: - void dumpToStream(raw_ostream &os) const; - static bool classof(const MemRegion *R) { Kind k = R->getKind(); return k >= BEG_NON_STATIC_GLOBAL_MEMSPACES && @@ -245,7 +258,7 @@ public: } }; -/// \class The region containing globals which are defined in system/external +/// \brief The region containing globals which are defined in system/external /// headers and are considered modifiable by system calls (ex: errno). class GlobalSystemSpaceRegion : public NonStaticGlobalSpaceRegion { friend class MemRegionManager; @@ -262,7 +275,7 @@ public: } }; -/// \class The region containing globals which are considered not to be modified +/// \brief The region containing globals which are considered not to be modified /// or point to data which could be modified as a result of a function call /// (system or internal). Ex: Const global scalars would be modeled as part of /// this region. This region also includes most system globals since they have @@ -282,7 +295,7 @@ public: } }; -/// \class The region containing globals which can be modified by calls to +/// \brief The region containing globals which can be modified by calls to /// "internally" defined functions - (for now just) functions other then system /// calls. class GlobalInternalSpaceRegion : public NonStaticGlobalSpaceRegion { @@ -307,6 +320,9 @@ class HeapSpaceRegion : public MemSpaceRegion { HeapSpaceRegion(MemRegionManager *mgr) : MemSpaceRegion(mgr, HeapSpaceRegionKind) {} public: + + void dumpToStream(raw_ostream &os) const; + static bool classof(const MemRegion *R) { return R->getKind() == HeapSpaceRegionKind; } @@ -318,6 +334,9 @@ class UnknownSpaceRegion : public MemSpaceRegion { UnknownSpaceRegion(MemRegionManager *mgr) : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {} public: + + void dumpToStream(raw_ostream &os) const; + static bool classof(const MemRegion *R) { return R->getKind() == UnknownSpaceRegionKind; } @@ -351,6 +370,9 @@ class StackLocalsSpaceRegion : public StackSpaceRegion { StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc) : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {} public: + + void dumpToStream(raw_ostream &os) const; + static bool classof(const MemRegion *R) { return R->getKind() == StackLocalsSpaceRegionKind; } @@ -363,6 +385,9 @@ private: StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc) : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {} public: + + void dumpToStream(raw_ostream &os) const; + static bool classof(const MemRegion *R) { return R->getKind() == StackArgumentsSpaceRegionKind; } @@ -478,6 +503,8 @@ public: return T.getTypePtrOrNull() ? T.getDesugaredType(Context) : T; } + DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const; + static bool classof(const MemRegion* R) { unsigned k = R->getKind(); return k >= BEG_TYPED_VALUE_REGIONS && k <= END_TYPED_VALUE_REGIONS; @@ -579,25 +606,37 @@ class BlockDataRegion : public SubRegion { const BlockTextRegion *BC; const LocationContext *LC; // Can be null */ void *ReferencedVars; + void *OriginalVars; BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc, const MemRegion *sreg) - : SubRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), ReferencedVars(0) {} + : SubRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), + ReferencedVars(0), OriginalVars(0) {} -public: +public: const BlockTextRegion *getCodeRegion() const { return BC; } const BlockDecl *getDecl() const { return BC->getDecl(); } class referenced_vars_iterator { const MemRegion * const *R; + const MemRegion * const *OriginalR; public: - explicit referenced_vars_iterator(const MemRegion * const *r) : R(r) {} + explicit referenced_vars_iterator(const MemRegion * const *r, + const MemRegion * const *originalR) + : R(r), OriginalR(originalR) {} operator const MemRegion * const *() const { return R; } - + + const MemRegion *getCapturedRegion() const { + return *R; + } + const MemRegion *getOriginalRegion() const { + return *OriginalR; + } + const VarRegion* operator*() const { return cast<VarRegion>(*R); } @@ -610,6 +649,7 @@ public: } referenced_vars_iterator &operator++() { ++R; + ++OriginalR; return *this; } }; @@ -781,8 +821,6 @@ public: const Decl *getDecl() const { return D; } void Profile(llvm::FoldingSetNodeID& ID) const; - DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const; - static bool classof(const MemRegion* R) { unsigned k = R->getKind(); return k >= BEG_DECL_REGIONS && k <= END_DECL_REGIONS; @@ -819,7 +857,8 @@ public: return R->getKind() == VarRegionKind; } - void dumpPretty(raw_ostream &os) const; + bool canPrintPretty() const; + void printPretty(raw_ostream &os) const; }; /// CXXThisRegion - Represents the region for the implicit 'this' parameter @@ -878,7 +917,9 @@ public: } void dumpToStream(raw_ostream &os) const; - void dumpPretty(raw_ostream &os) const; + + bool canPrintPretty() const; + void printPretty(raw_ostream &os) const; }; class ObjCIvarRegion : public DeclRegion { @@ -1106,8 +1147,11 @@ public: const CXXThisRegion *getCXXThisRegion(QualType thisPointerTy, const LocationContext *LC); - /// getSymbolicRegion - Retrieve or create a "symbolic" memory region. - const SymbolicRegion* getSymbolicRegion(SymbolRef sym); + /// \brief Retrieve or create a "symbolic" memory region. + const SymbolicRegion* getSymbolicRegion(SymbolRef Sym); + + /// \brief Return a unique symbolic region belonging to heap memory space. + const SymbolicRegion *getSymbolicHeapRegion(SymbolRef sym); const StringRegion *getStringRegion(const StringLiteral* Str); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h deleted file mode 100644 index d8aec09..0000000 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h +++ /dev/null @@ -1,293 +0,0 @@ -//===- ObjCMessage.h - Wrapper for ObjC messages and dot syntax ---*- 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 ObjCMessage which serves as a common wrapper for ObjC -// message expressions or implicit messages for loading/storing ObjC properties. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE -#define LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE - -#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" -#include "clang/AST/ExprObjC.h" -#include "clang/AST/ExprCXX.h" -#include "clang/Basic/SourceManager.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Support/Compiler.h" - -namespace clang { -namespace ento { -using llvm::StrInStrNoCase; - -/// \brief Represents both explicit ObjC message expressions and implicit -/// messages that are sent for handling properties in dot syntax. -class ObjCMessage { - const ObjCMessageExpr *Msg; - const ObjCPropertyRefExpr *PE; - const bool IsPropSetter; -public: - ObjCMessage() : Msg(0), PE(0), IsPropSetter(false) {} - - ObjCMessage(const ObjCMessageExpr *E, const ObjCPropertyRefExpr *pe = 0, - bool isSetter = false) - : Msg(E), PE(pe), IsPropSetter(isSetter) { - assert(E && "should not be initialized with null expression"); - } - - bool isValid() const { return Msg; } - - bool isPureMessageExpr() const { return !PE; } - - bool isPropertyGetter() const { return PE && !IsPropSetter; } - - bool isPropertySetter() const { - return IsPropSetter; - } - - const Expr *getMessageExpr() const { - return Msg; - } - - QualType getType(ASTContext &ctx) const { - return Msg->getType(); - } - - QualType getResultType(ASTContext &ctx) const { - if (const ObjCMethodDecl *MD = Msg->getMethodDecl()) - return MD->getResultType(); - return getType(ctx); - } - - ObjCMethodFamily getMethodFamily() const { - return Msg->getMethodFamily(); - } - - Selector getSelector() const { - return Msg->getSelector(); - } - - const Expr *getInstanceReceiver() const { - return Msg->getInstanceReceiver(); - } - - SVal getInstanceReceiverSVal(ProgramStateRef State, - const LocationContext *LC) const { - if (!isInstanceMessage()) - return UndefinedVal(); - if (const Expr *Ex = getInstanceReceiver()) - return State->getSValAsScalarOrLoc(Ex, LC); - - // An instance message with no expression means we are sending to super. - // In this case the object reference is the same as 'self'. - const ImplicitParamDecl *SelfDecl = LC->getSelfDecl(); - assert(SelfDecl && "No message receiver Expr, but not in an ObjC method"); - return State->getSVal(State->getRegion(SelfDecl, LC)); - } - - bool isInstanceMessage() const { - return Msg->isInstanceMessage(); - } - - const ObjCMethodDecl *getMethodDecl() const { - return Msg->getMethodDecl(); - } - - const ObjCInterfaceDecl *getReceiverInterface() const { - return Msg->getReceiverInterface(); - } - - SourceLocation getSuperLoc() const { - if (PE) - return PE->getReceiverLocation(); - return Msg->getSuperLoc(); - } - - SourceRange getSourceRange() const LLVM_READONLY { - if (PE) - return PE->getSourceRange(); - return Msg->getSourceRange(); - } - - unsigned getNumArgs() const { - return Msg->getNumArgs(); - } - - SVal getArgSVal(unsigned i, - const LocationContext *LCtx, - ProgramStateRef state) const { - assert(i < getNumArgs() && "Invalid index for argument"); - return state->getSVal(Msg->getArg(i), LCtx); - } - - QualType getArgType(unsigned i) const { - assert(i < getNumArgs() && "Invalid index for argument"); - return Msg->getArg(i)->getType(); - } - - const Expr *getArgExpr(unsigned i) const { - assert(i < getNumArgs() && "Invalid index for argument"); - return Msg->getArg(i); - } - - SourceRange getArgSourceRange(unsigned i) const { - const Expr *argE = getArgExpr(i); - return argE->getSourceRange(); - } - - SourceRange getReceiverSourceRange() const { - if (PE) { - if (PE->isObjectReceiver()) - return PE->getBase()->getSourceRange(); - } - else { - return Msg->getReceiverRange(); - } - - // FIXME: This isn't a range. - return PE->getReceiverLocation(); - } -}; - -/// \brief Common wrapper for a call expression, ObjC message, or C++ -/// constructor, mainly to provide a common interface for their arguments. -class CallOrObjCMessage { - llvm::PointerUnion<const CallExpr *, const CXXConstructExpr *> CallE; - ObjCMessage Msg; - ProgramStateRef State; - const LocationContext *LCtx; -public: - CallOrObjCMessage(const CallExpr *callE, ProgramStateRef state, - const LocationContext *lctx) - : CallE(callE), State(state), LCtx(lctx) {} - CallOrObjCMessage(const CXXConstructExpr *consE, ProgramStateRef state, - const LocationContext *lctx) - : CallE(consE), State(state), LCtx(lctx) {} - CallOrObjCMessage(const ObjCMessage &msg, ProgramStateRef state, - const LocationContext *lctx) - : CallE((CallExpr *)0), Msg(msg), State(state), LCtx(lctx) {} - - QualType getResultType(ASTContext &ctx) const; - - bool isFunctionCall() const { - return CallE && CallE.is<const CallExpr *>(); - } - - bool isCXXConstructExpr() const { - return CallE && CallE.is<const CXXConstructExpr *>(); - } - - bool isObjCMessage() const { - return !CallE; - } - - bool isCXXCall() const { - const CallExpr *ActualCallE = CallE.dyn_cast<const CallExpr *>(); - return ActualCallE && isa<CXXMemberCallExpr>(ActualCallE); - } - - /// Check if the callee is declared in the system header. - bool isInSystemHeader() const { - if (const Decl *FD = getDecl()) { - const SourceManager &SM = - State->getStateManager().getContext().getSourceManager(); - return SM.isInSystemHeader(FD->getLocation()); - } - return false; - } - - const Expr *getOriginExpr() const { - if (!CallE) - return Msg.getMessageExpr(); - if (const CXXConstructExpr *Ctor = - CallE.dyn_cast<const CXXConstructExpr *>()) - return Ctor; - return CallE.get<const CallExpr *>(); - } - - SVal getFunctionCallee() const; - SVal getCXXCallee() const; - SVal getInstanceMessageReceiver(const LocationContext *LC) const; - - /// Get the declaration of the function or method. - const Decl *getDecl() const; - - unsigned getNumArgs() const { - if (!CallE) - return Msg.getNumArgs(); - if (const CXXConstructExpr *Ctor = - CallE.dyn_cast<const CXXConstructExpr *>()) - return Ctor->getNumArgs(); - return CallE.get<const CallExpr *>()->getNumArgs(); - } - - SVal getArgSVal(unsigned i) const { - assert(i < getNumArgs()); - if (!CallE) - return Msg.getArgSVal(i, LCtx, State); - return State->getSVal(getArg(i), LCtx); - } - - const Expr *getArg(unsigned i) const { - assert(i < getNumArgs()); - if (!CallE) - return Msg.getArgExpr(i); - if (const CXXConstructExpr *Ctor = - CallE.dyn_cast<const CXXConstructExpr *>()) - return Ctor->getArg(i); - return CallE.get<const CallExpr *>()->getArg(i); - } - - SourceRange getArgSourceRange(unsigned i) const { - assert(i < getNumArgs()); - if (CallE) - return getArg(i)->getSourceRange(); - return Msg.getArgSourceRange(i); - } - - SourceRange getReceiverSourceRange() const { - assert(isObjCMessage()); - return Msg.getReceiverSourceRange(); - } - - /// \brief Check if the name corresponds to a CoreFoundation or CoreGraphics - /// function that allows objects to escape. - /// - /// Many methods allow a tracked object to escape. For example: - /// - /// CFMutableDictionaryRef x = CFDictionaryCreateMutable(..., customDeallocator); - /// CFDictionaryAddValue(y, key, x); - /// - /// We handle this and similar cases with the following heuristic. If the - /// function name contains "InsertValue", "SetValue", "AddValue", - /// "AppendValue", or "SetAttribute", then we assume that arguments may - /// escape. - // - // TODO: To reduce false negatives here, we should track the container - // allocation site and check if a proper deallocator was set there. - static bool isCFCGAllowingEscape(StringRef FName) { - if (FName[0] == 'C' && (FName[1] == 'F' || FName[1] == 'G')) - if (StrInStrNoCase(FName, "InsertValue") != StringRef::npos|| - StrInStrNoCase(FName, "AddValue") != StringRef::npos || - StrInStrNoCase(FName, "SetValue") != StringRef::npos || - StrInStrNoCase(FName, "WithData") != StringRef::npos || - StrInStrNoCase(FName, "AppendValue") != StringRef::npos|| - StrInStrNoCase(FName, "SetAttribute") != StringRef::npos) { - return true; - } - return false; - } -}; - -} -} - -#endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 360d648..d36aa1b 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -35,7 +35,8 @@ class ASTContext; namespace ento { -class CallOrObjCMessage; +class CallEvent; +class CallEventManager; typedef ConstraintManager* (*ConstraintManagerCreator)(ProgramStateManager&, SubEngine&); @@ -49,13 +50,34 @@ template <typename T> struct ProgramStatePartialTrait; template <typename T> struct ProgramStateTrait { typedef typename T::data_type data_type; - static inline void *GDMIndex() { return &T::TagInt; } static inline void *MakeVoidPtr(data_type D) { return (void*) D; } static inline data_type MakeData(void *const* P) { return P ? (data_type) *P : (data_type) 0; } }; +/// \class Stores the dynamic type information. +/// Information about type of an object at runtime. This is used by dynamic +/// dispatch implementation. +class DynamicTypeInfo { + QualType T; + bool CanBeASubClass; + +public: + DynamicTypeInfo() : T(QualType()) {} + DynamicTypeInfo(QualType WithType, bool CanBeSub = true): + T(WithType), CanBeASubClass(CanBeSub) {} + QualType getType() { return T; } + bool canBeASubClass() { return CanBeASubClass; } + void Profile(llvm::FoldingSetNodeID &ID) const { + T.Profile(ID); + ID.AddInteger((unsigned)CanBeASubClass); + } + bool operator==(const DynamicTypeInfo &X) const { + return T == X.T && CanBeASubClass == X.CanBeASubClass; + } +}; + /// \class ProgramState /// ProgramState - This class encapsulates: /// @@ -220,12 +242,12 @@ public: const Expr *E, unsigned BlockCount, const LocationContext *LCtx, StoreManager::InvalidatedSymbols *IS = 0, - const CallOrObjCMessage *Call = 0) const; + const CallEvent *Call = 0) const; /// enterStackFrame - Returns the state for entry to the given stack frame, /// preserving the current state. - ProgramStateRef enterStackFrame(const LocationContext *callerCtx, - const StackFrameContext *calleeCtx) const; + ProgramStateRef enterStackFrame(const CallEvent &Call, + const StackFrameContext *CalleeCtx) const; /// Get the lvalue for a variable reference. Loc getLValue(const VarDecl *D, const LocationContext *LC) const; @@ -239,6 +261,9 @@ public: /// Get the lvalue for a field reference. SVal getLValue(const FieldDecl *decl, SVal Base) const; + /// Get the lvalue for an indirect field reference. + SVal getLValue(const IndirectFieldDecl *decl, SVal Base) const; + /// Get the lvalue for an array index. SVal getLValue(QualType ElementType, SVal Idx, SVal Base) const; @@ -310,6 +335,20 @@ public: bool isTainted(SymbolRef Sym, TaintTagType Kind = TaintTagGeneric) const; bool isTainted(const MemRegion *Reg, TaintTagType Kind=TaintTagGeneric) const; + /// \brief Get dynamic type information for a region. + DynamicTypeInfo getDynamicTypeInfo(const MemRegion *Reg) const; + + /// \brief Set dynamic type information of the region; return the new state. + ProgramStateRef setDynamicTypeInfo(const MemRegion *Reg, + DynamicTypeInfo NewTy) const; + + /// \brief Set dynamic type information of the region; return the new state. + ProgramStateRef setDynamicTypeInfo(const MemRegion *Reg, + QualType NewTy, + bool CanBeSubClassed = true) const { + return setDynamicTypeInfo(Reg, DynamicTypeInfo(NewTy, CanBeSubClassed)); + } + //==---------------------------------------------------------------------==// // Accessing the Generic Data Map (GDM). //==---------------------------------------------------------------------==// @@ -382,7 +421,7 @@ private: const Expr *E, unsigned BlockCount, const LocationContext *LCtx, StoreManager::InvalidatedSymbols &IS, - const CallOrObjCMessage *Call) const; + const CallEvent *Call) const; }; //===----------------------------------------------------------------------===// @@ -412,6 +451,9 @@ private: /// Object that manages the data for all created SVals. OwningPtr<SValBuilder> svalBuilder; + /// Manages memory for created CallEvents. + OwningPtr<CallEventManager> CallEventMgr; + /// A BumpPtrAllocator to allocate states. llvm::BumpPtrAllocator &Alloc; @@ -423,28 +465,7 @@ public: StoreManagerCreator CreateStoreManager, ConstraintManagerCreator CreateConstraintManager, llvm::BumpPtrAllocator& alloc, - SubEngine &subeng) - : Eng(&subeng), - EnvMgr(alloc), - GDMFactory(alloc), - svalBuilder(createSimpleSValBuilder(alloc, Ctx, *this)), - Alloc(alloc) { - StoreMgr.reset((*CreateStoreManager)(*this)); - ConstraintMgr.reset((*CreateConstraintManager)(*this, subeng)); - } - - ProgramStateManager(ASTContext &Ctx, - StoreManagerCreator CreateStoreManager, - ConstraintManager* ConstraintManagerPtr, - llvm::BumpPtrAllocator& alloc) - : Eng(0), - EnvMgr(alloc), - GDMFactory(alloc), - svalBuilder(createSimpleSValBuilder(alloc, Ctx, *this)), - Alloc(alloc) { - StoreMgr.reset((*CreateStoreManager)(*this)); - ConstraintMgr.reset(ConstraintManagerPtr); - } + SubEngine &subeng); ~ProgramStateManager(); @@ -480,6 +501,8 @@ public: return svalBuilder->getRegionManager(); } + CallEventManager &getCallEventManager() { return *CallEventMgr; } + StoreManager& getStoreManager() { return *StoreMgr; } ConstraintManager& getConstraintManager() { return *ConstraintMgr; } SubEngine* getOwningEngine() { return Eng; } @@ -650,6 +673,18 @@ inline SVal ProgramState::getLValue(const FieldDecl *D, SVal Base) const { return getStateManager().StoreMgr->getLValueField(D, Base); } +inline SVal ProgramState::getLValue(const IndirectFieldDecl *D, + SVal Base) const { + StoreManager &SM = *getStateManager().StoreMgr; + for (IndirectFieldDecl::chain_iterator I = D->chain_begin(), + E = D->chain_end(); + I != E; ++I) { + Base = SM.getLValueField(cast<FieldDecl>(*I), Base); + } + + return Base; +} + inline SVal ProgramState::getLValue(QualType ElementType, SVal Idx, SVal Base) const{ if (NonLoc *N = dyn_cast<NonLoc>(&Idx)) return getStateManager().StoreMgr->getLValueElement(ElementType, *N, Base); @@ -672,7 +707,7 @@ ProgramState::getSValAsScalarOrLoc(const Stmt *S, const LocationContext *LCtx) const { if (const Expr *Ex = dyn_cast<Expr>(S)) { QualType T = Ex->getType(); - if (Ex->isLValue() || Loc::isLocType(T) || T->isIntegerType()) + if (Ex->isGLValue() || Loc::isLocType(T) || T->isIntegerType()) return getSVal(S, LCtx); } @@ -765,14 +800,12 @@ CB ProgramState::scanReachableSymbols(const MemRegion * const *beg, /// \class ScanReachableSymbols /// A Utility class that allows to visit the reachable symbols using a custom /// SymbolVisitor. -class ScanReachableSymbols : public SubRegionMap::Visitor { - virtual void anchor(); +class ScanReachableSymbols { typedef llvm::DenseMap<const void*, unsigned> VisitedItems; VisitedItems visited; ProgramStateRef state; SymbolVisitor &visitor; - OwningPtr<SubRegionMap> SRM; public: ScanReachableSymbols(ProgramStateRef st, SymbolVisitor& v) @@ -782,11 +815,6 @@ public: bool scan(SVal val); bool scan(const MemRegion *R); bool scan(const SymExpr *sym); - - // From SubRegionMap::Visitor. - bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) { - return scan(SubRegion); - } }; } // end GR namespace diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index 4ad36f9..83c3a56 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_GR_SVALBUILDER #define LLVM_CLANG_GR_SVALBUILDER +#include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" @@ -78,7 +79,7 @@ public: // FIXME: Remove the second disjunct when we support symbolic // truncation/extension. return (Context.getCanonicalType(Ty1) == Context.getCanonicalType(Ty2) || - (Ty2->isIntegerType() && Ty2->isIntegerType())); + (Ty1->isIntegerType() && Ty2->isIntegerType())); } SVal evalCast(SVal val, QualType castTy, QualType originalType); @@ -107,12 +108,9 @@ public: /// that value is returned. Otherwise, returns NULL. virtual const llvm::APSInt *getKnownValue(ProgramStateRef state, SVal val) = 0; - /// Handles generation of the value in case the builder is not smart enough to - /// handle the given binary expression. Depending on the state, decides to - /// either keep the expression or forget the history and generate an - /// UnknownVal. - SVal makeGenericVal(ProgramStateRef state, BinaryOperator::Opcode op, - NonLoc lhs, NonLoc rhs, QualType resultTy); + /// Constructs a symbolic expression for two non-location values. + SVal makeSymExprValNN(ProgramStateRef state, BinaryOperator::Opcode op, + NonLoc lhs, NonLoc rhs, QualType resultTy); SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type); @@ -185,6 +183,12 @@ public: const LocationContext *LCtx, QualType type, unsigned visitCount); + /// \brief Conjure a symbol representing heap allocated memory region. + /// + /// Note, the expression should represent a location. + DefinedOrUnknownSVal getConjuredHeapSymbolVal(const Expr *E, + const LocationContext *LCtx, + unsigned Count); DefinedOrUnknownSVal getDerivedRegionValueSymbolVal( SymbolRef parentSymbol, const TypedValueRegion *region); @@ -307,6 +311,13 @@ public: return loc::ConcreteInt(BasicVals.getValue(integer)); } + /// Return a memory region for the 'this' object reference. + loc::MemRegionVal getCXXThis(const CXXMethodDecl *D, + const StackFrameContext *SFC); + + /// Return a memory region for the 'this' object reference. + loc::MemRegionVal getCXXThis(const CXXRecordDecl *D, + const StackFrameContext *SFC); }; SValBuilder* createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc, diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index ce3eb1d..e0b5f64 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -68,7 +68,6 @@ protected: public: explicit SVal() : Data(0), Kind(0) {} - ~SVal() {} /// BufferTy - A temporary buffer to hold a set of SVals. typedef SmallVector<SVal,5> BufferTy; @@ -164,13 +163,10 @@ public: class UndefinedVal : public SVal { public: UndefinedVal() : SVal(UndefinedKind) {} - UndefinedVal(const void *D) : SVal(UndefinedKind, D) {} static inline bool classof(const SVal* V) { return V->getBaseKind() == UndefinedKind; } - - const void *getData() const { return Data; } }; class DefinedOrUnknownSVal : public SVal { @@ -326,16 +322,22 @@ class LocAsInteger : public NonLoc { public: Loc getLoc() const { - return cast<Loc>(((std::pair<SVal, uintptr_t>*) Data)->first); + const std::pair<SVal, uintptr_t> *D = + static_cast<const std::pair<SVal, uintptr_t> *>(Data); + return cast<Loc>(D->first); } const Loc& getPersistentLoc() const { - const SVal& V = ((std::pair<SVal, uintptr_t>*) Data)->first; + const std::pair<SVal, uintptr_t> *D = + static_cast<const std::pair<SVal, uintptr_t> *>(Data); + const SVal& V = D->first; return cast<Loc>(V); } unsigned getNumBits() const { - return ((std::pair<SVal, unsigned>*) Data)->second; + const std::pair<SVal, uintptr_t> *D = + static_cast<const std::pair<SVal, uintptr_t> *>(Data); + return D->second; } // Implement isa<T> support. @@ -401,7 +403,7 @@ public: namespace loc { -enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind, ObjCPropRefKind }; +enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind }; class GotoLabel : public Loc { public: @@ -431,7 +433,7 @@ public: } /// \brief Get the underlining region and strip casts. - const MemRegion* stripCasts() const; + const MemRegion* stripCasts(bool StripBaseCasts = true) const; template <typename REGION> const REGION* getRegionAs() const { @@ -480,28 +482,6 @@ public: } }; -/// \brief Pseudo-location SVal used by the ExprEngine to simulate a "load" or -/// "store" of an ObjC property for the dot syntax. -class ObjCPropRef : public Loc { -public: - explicit ObjCPropRef(const ObjCPropertyRefExpr *E) - : Loc(ObjCPropRefKind, E) {} - - const ObjCPropertyRefExpr *getPropRefExpr() const { - return static_cast<const ObjCPropertyRefExpr *>(Data); - } - - // Implement isa<T> support. - static inline bool classof(const SVal* V) { - return V->getBaseKind() == LocKind && - V->getSubKind() == ObjCPropRefKind; - } - - static inline bool classof(const Loc* V) { - return V->getSubKind() == ObjCPropRefKind; - } -}; - } // end ento::loc namespace } // end GR namespace diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index 5315f4b..138a590 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -29,10 +29,10 @@ class StackFrameContext; namespace ento { -class CallOrObjCMessage; +class CallEvent; class ProgramState; class ProgramStateManager; -class SubRegionMap; +class ScanReachableSymbols; class StoreManager { protected: @@ -49,7 +49,7 @@ public: virtual ~StoreManager() {} /// Return the value bound to specified location in a given state. - /// \param[in] state The analysis state. + /// \param[in] store The analysis state. /// \param[in] loc The symbolic memory location. /// \param[in] T An optional type that provides a hint indicating the /// expected type of the returned value. This is used if the value is @@ -58,12 +58,12 @@ public: virtual SVal getBinding(Store store, Loc loc, QualType T = QualType()) = 0; /// Return a state with the specified value bound to the given location. - /// \param[in] state The analysis state. + /// \param[in] store The analysis state. /// \param[in] loc The symbolic memory location. /// \param[in] val The value to bind to location \c loc. - /// \return A pointer to a ProgramState object that contains the same bindings as - /// \c state with the addition of having the value specified by \c val bound - /// to the location given for \c loc. + /// \return A pointer to a ProgramState object that contains the same + /// bindings as \c state with the addition of having the value specified + /// by \c val bound to the location given for \c loc. virtual StoreRef Bind(Store store, Loc loc, SVal val) = 0; virtual StoreRef BindDefault(Store store, const MemRegion *R, SVal V); @@ -85,11 +85,6 @@ public: /// used to query and manipulate MemRegion objects. MemRegionManager& getRegionManager() { return MRMgr; } - /// getSubRegionMap - Returns an opaque map object that clients can query - /// to get the subregions of a given MemRegion object. It is the - // caller's responsibility to 'delete' the returned map. - virtual SubRegionMap *getSubRegionMap(Store store) = 0; - virtual Loc getLValueVar(const VarDecl *VD, const LocationContext *LC) { return svalBuilder.makeLoc(MRMgr.getVarRegion(VD, LC)); } @@ -120,7 +115,10 @@ public: virtual SVal ArrayToPointer(Loc Array) = 0; /// Evaluates DerivedToBase casts. - virtual SVal evalDerivedToBase(SVal derived, QualType basePtrType) = 0; + SVal evalDerivedToBase(SVal derived, const CastExpr *Cast); + + /// Evaluates a derived-to-base cast through a single level of derivation. + virtual SVal evalDerivedToBase(SVal derived, QualType derivedPtrType) = 0; /// \brief Evaluates C++ dynamic_cast cast. /// The callback may result in the following 3 scenarios: @@ -133,15 +131,6 @@ public: virtual SVal evalDynamicCast(SVal base, QualType derivedPtrType, bool &Failed) = 0; - class CastResult { - ProgramStateRef state; - const MemRegion *region; - public: - ProgramStateRef getState() const { return state; } - const MemRegion* getRegion() const { return region; } - CastResult(ProgramStateRef s, const MemRegion* r = 0) : state(s), region(r){} - }; - const ElementRegion *GetElementZeroRegion(const MemRegion *R, QualType T); /// castRegion - Used by ExprEngine::VisitCast to handle casts from @@ -176,8 +165,7 @@ public: /// invalidate additional regions that may have changed based on accessing /// the given regions. Optionally, invalidates non-static globals as well. /// \param[in] store The initial store - /// \param[in] Begin A pointer to the first region to invalidate. - /// \param[in] End A pointer just past the last region to invalidate. + /// \param[in] Regions The regions to invalidate. /// \param[in] E The current statement being evaluated. Used to conjure /// symbols to mark the values of invalidated regions. /// \param[in] Count The current block count. Used to conjure @@ -186,7 +174,7 @@ public: /// accessible. Pass \c NULL if this information will not be used. /// \param[in] Call The call expression which will be used to determine which /// globals should get invalidated. - /// \param[in,out] Regions A vector to fill with any regions being + /// \param[in,out] Invalidated A vector to fill with any regions being /// invalidated. This should include any regions explicitly invalidated /// even if they do not currently have bindings. Pass \c NULL if this /// information will not be used. @@ -195,14 +183,20 @@ public: const Expr *E, unsigned Count, const LocationContext *LCtx, InvalidatedSymbols &IS, - const CallOrObjCMessage *Call, + const CallEvent *Call, InvalidatedRegions *Invalidated) = 0; /// enterStackFrame - Let the StoreManager to do something when execution /// engine is about to execute into a callee. - virtual StoreRef enterStackFrame(ProgramStateRef state, - const LocationContext *callerCtx, - const StackFrameContext *calleeCtx); + StoreRef enterStackFrame(Store store, + const CallEvent &Call, + const StackFrameContext *CalleeCtx); + + /// Finds the transitive closure of symbols within the given region. + /// + /// Returns false if the visitor aborted the scan. + virtual bool scanReachableSymbols(Store S, const MemRegion *R, + ScanReachableSymbols &Visitor) = 0; virtual void print(Store store, raw_ostream &Out, const char* nl, const char *sep) = 0; @@ -275,24 +269,6 @@ inline StoreRef &StoreRef::operator=(StoreRef const &newStore) { return *this; } -// FIXME: Do we still need this? -/// SubRegionMap - An abstract interface that represents a queryable map -/// between MemRegion objects and their subregions. -class SubRegionMap { - virtual void anchor(); -public: - virtual ~SubRegionMap() {} - - class Visitor { - virtual void anchor(); - public: - virtual ~Visitor() {} - virtual bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) = 0; - }; - - virtual bool iterSubRegions(const MemRegion *region, Visitor& V) const = 0; -}; - // FIXME: Do we need to pass ProgramStateManager anymore? StoreManager *CreateRegionStoreManager(ProgramStateManager& StMgr); StoreManager *CreateFieldsOnlyRegionStoreManager(ProgramStateManager& StMgr); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h index baf57d4..68b81f1 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -105,7 +105,7 @@ public: const StoreManager::InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> ExplicitRegions, ArrayRef<const MemRegion *> Regions, - const CallOrObjCMessage *Call) = 0; + const CallEvent *Call) = 0; inline ProgramStateRef diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index c7de7ef..5d27f86 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -94,6 +94,8 @@ public: return symbol_iterator(this); } static symbol_iterator symbol_end() { return symbol_iterator(); } + + unsigned computeComplexity() const; }; typedef const SymExpr* SymbolRef; @@ -553,6 +555,7 @@ public: BasicValueFactory &getBasicVals() { return BV; } }; +/// \brief A class responsible for cleaning up unused symbols. class SymbolReaper { enum SymbolStatus { NotProcessed, @@ -569,21 +572,26 @@ class SymbolReaper { RegionSetTy RegionRoots; - const LocationContext *LCtx; + const StackFrameContext *LCtx; const Stmt *Loc; SymbolManager& SymMgr; StoreRef reapedStore; llvm::DenseMap<const MemRegion *, unsigned> includedRegionCache; public: + /// \brief Construct a reaper object, which removes everything which is not + /// live before we execute statement s in the given location context. + /// + /// If the statement is NULL, everything is this and parent contexts is + /// considered live. SymbolReaper(const LocationContext *ctx, const Stmt *s, SymbolManager& symmgr, StoreManager &storeMgr) - : LCtx(ctx), Loc(s), SymMgr(symmgr), reapedStore(0, storeMgr) {} + : LCtx(ctx->getCurrentStackFrame()), Loc(s), SymMgr(symmgr), + reapedStore(0, storeMgr) {} ~SymbolReaper() {} const LocationContext *getLocationContext() const { return LCtx; } - const Stmt *getCurrentStatement() const { return Loc; } bool isLive(SymbolRef sym); bool isLiveRegion(const MemRegion *region); diff --git a/include/clang/Tooling/ArgumentsAdjusters.h b/include/clang/Tooling/ArgumentsAdjusters.h new file mode 100644 index 0000000..492ddd2 --- /dev/null +++ b/include/clang/Tooling/ArgumentsAdjusters.h @@ -0,0 +1,59 @@ +//===--- ArgumentsAdjusters.h - Command line arguments adjuster -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares base abstract class ArgumentsAdjuster and its descendants. +// These classes are intended to modify command line arguments obtained from +// a compilation database before they are used to run a frontend action. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H +#define LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H + +#include <string> +#include <vector> + +namespace clang { + +namespace tooling { + +/// \brief A sequence of command line arguments. +typedef std::vector<std::string> CommandLineArguments; + +/// \brief Abstract interface for a command line adjusters. +/// +/// This abstract interface describes a command line argument adjuster, +/// which is responsible for command line arguments modification before +/// the arguments are used to run a frontend action. +class ArgumentsAdjuster { + virtual void anchor(); +public: + /// \brief Returns adjusted command line arguments. + /// + /// \param Args Input sequence of command line arguments. + /// + /// \returns Modified sequence of command line arguments. + virtual CommandLineArguments Adjust(const CommandLineArguments &Args) = 0; + virtual ~ArgumentsAdjuster() { + } +}; + +/// \brief Syntax check only command line adjuster. +/// +/// This class implements ArgumentsAdjuster interface and converts input +/// command line arguments to the "syntax check only" variant. +class ClangSyntaxOnlyAdjuster : public ArgumentsAdjuster { + virtual CommandLineArguments Adjust(const CommandLineArguments &Args); +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H + diff --git a/include/clang/Tooling/CommandLineClangTool.h b/include/clang/Tooling/CommandLineClangTool.h new file mode 100644 index 0000000..c29c302 --- /dev/null +++ b/include/clang/Tooling/CommandLineClangTool.h @@ -0,0 +1,80 @@ +//===- CommandLineClangTool.h - command-line clang tools driver -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the CommandLineClangTool class used to run clang +// tools as separate command-line applications with a consistent common +// interface for handling compilation database and input files. +// +// It provides a common subset of command-line options, common algorithm +// for locating a compilation database and source files, and help messages +// for the basic command-line interface. +// +// It creates a CompilationDatabase, initializes a ClangTool and runs a +// user-specified FrontendAction over all TUs in which the given files are +// compiled. +// +// This class uses the Clang Tooling infrastructure, see +// http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html +// for details on setting it up with LLVM source tree. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_CLANG_INCLUDE_CLANG_TOOLING_COMMANDLINECLANGTOOL_H +#define LLVM_TOOLS_CLANG_INCLUDE_CLANG_TOOLING_COMMANDLINECLANGTOOL_H + +#include "llvm/Support/CommandLine.h" +#include "clang/Tooling/CompilationDatabase.h" + +namespace clang { + +namespace tooling { + +class CompilationDatabase; +class FrontendActionFactory; + +/// \brief A common driver for command-line Clang tools. +/// +/// Parses a common subset of command-line arguments, locates and loads a +/// compilation commands database, runs a tool with user-specified action. It +/// also contains a help message for the common command-line options. +/// An example of usage: +/// @code +/// int main(int argc, const char **argv) { +/// CommandLineClangTool Tool; +/// cl::extrahelp MoreHelp("\nMore help text..."); +/// Tool.initialize(argc, argv); +/// return Tool.run(newFrontendActionFactory<clang::SyntaxOnlyAction>()); +/// } +/// @endcode +/// +class CommandLineClangTool { +public: + /// Sets up command-line options and help messages. + /// Add your own help messages after constructing this tool. + CommandLineClangTool(); + + /// Parses command-line, initializes a compilation database. + /// This method exits program in case of error. + void initialize(int argc, const char **argv); + + /// Runs a clang tool with an action created by \c ActionFactory. + int run(FrontendActionFactory *ActionFactory); + +private: + llvm::OwningPtr<CompilationDatabase> Compilations; + llvm::cl::opt<std::string> BuildPath; + llvm::cl::list<std::string> SourcePaths; + llvm::cl::extrahelp MoreHelp; +}; + +} // namespace tooling + +} // namespace clang + +#endif // LLVM_TOOLS_CLANG_INCLUDE_CLANG_TOOLING_COMMANDLINECLANGTOOL_H diff --git a/include/clang/Tooling/CompilationDatabase.h b/include/clang/Tooling/CompilationDatabase.h index 625c8ec..f78ffae 100644 --- a/include/clang/Tooling/CompilationDatabase.h +++ b/include/clang/Tooling/CompilationDatabase.h @@ -81,6 +81,20 @@ public: static CompilationDatabase *loadFromDirectory(StringRef BuildDirectory, std::string &ErrorMessage); + /// \brief Tries to detect a compilation database location and load it. + /// + /// Looks for a compilation database in all parent paths of file 'SourceFile' + /// by calling loadFromDirectory. + static CompilationDatabase *autoDetectFromSource(StringRef SourceFile, + std::string &ErrorMessage); + + /// \brief Tries to detect a compilation database location and load it. + /// + /// Looks for a compilation database in directory 'SourceDir' and all + /// its parent paths by calling loadFromDirectory. + static CompilationDatabase *autoDetectFromDirectory(StringRef SourceDir, + std::string &ErrorMessage); + /// \brief Returns all compile commands in which the specified file was /// compiled. /// @@ -92,6 +106,9 @@ public: /// lines for a.cc and b.cc and only the first command line for t.cc. virtual std::vector<CompileCommand> getCompileCommands( StringRef FilePath) const = 0; + + /// \brief Returns the list of all files available in the compilation database. + virtual std::vector<std::string> getAllFiles() const = 0; }; /// \brief A compilation database that returns a single compile command line. @@ -141,6 +158,11 @@ public: virtual std::vector<CompileCommand> getCompileCommands( StringRef FilePath) const; + /// \brief Returns the list of all files available in the compilation database. + /// + /// Note: This is always an empty list for the fixed compilation database. + virtual std::vector<std::string> getAllFiles() const; + private: /// This is built up to contain a single entry vector to be returned from /// getCompileCommands after adding the positional argument. @@ -187,6 +209,11 @@ public: virtual std::vector<CompileCommand> getCompileCommands( StringRef FilePath) const; + /// \brief Returns the list of all files available in the compilation database. + /// + /// These are the 'file' entries of the JSON objects. + virtual std::vector<std::string> getAllFiles() const; + private: /// \brief Constructs a JSON compilation database on a memory buffer. JSONCompilationDatabase(llvm::MemoryBuffer *Database) @@ -215,4 +242,3 @@ private: } // end namespace clang #endif // LLVM_CLANG_TOOLING_COMPILATION_DATABASE_H - diff --git a/include/clang/Tooling/Refactoring.h b/include/clang/Tooling/Refactoring.h new file mode 100644 index 0000000..0e42a0e --- /dev/null +++ b/include/clang/Tooling/Refactoring.h @@ -0,0 +1,151 @@ +//===--- Refactoring.h - Framework for clang refactoring tools --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Interfaces supporting refactorings that span multiple translation units. +// While single translation unit refactorings are supported via the Rewriter, +// when refactoring multiple translation units changes must be stored in a +// SourceManager independent form, duplicate changes need to be removed, and +// all changes must be applied at once at the end of the refactoring so that +// the code is always parseable. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_H +#define LLVM_CLANG_TOOLING_REFACTORING_H + +#include "llvm/ADT/StringRef.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Tooling/Tooling.h" +#include <set> +#include <string> + +namespace clang { + +class Rewriter; +class SourceLocation; + +namespace tooling { + +/// \brief A text replacement. +/// +/// Represents a SourceManager independent replacement of a range of text in a +/// specific file. +class Replacement { +public: + /// \brief Creates an invalid (not applicable) replacement. + Replacement(); + + /// \brief Creates a replacement of the range [Offset, Offset+Length) in + /// FilePath with ReplacementText. + /// + /// \param FilePath A source file accessible via a SourceManager. + /// \param Offset The byte offset of the start of the range in the file. + /// \param Length The length of the range in bytes. + Replacement(llvm::StringRef FilePath, unsigned Offset, + unsigned Length, llvm::StringRef ReplacementText); + + /// \brief Creates a Replacement of the range [Start, Start+Length) with + /// ReplacementText. + Replacement(SourceManager &Sources, SourceLocation Start, unsigned Length, + llvm::StringRef ReplacementText); + + /// \brief Creates a Replacement of the given range with ReplacementText. + Replacement(SourceManager &Sources, const CharSourceRange &Range, + llvm::StringRef ReplacementText); + + /// \brief Creates a Replacement of the node with ReplacementText. + template <typename Node> + Replacement(SourceManager &Sources, const Node &NodeToReplace, + llvm::StringRef ReplacementText); + + /// \brief Returns whether this replacement can be applied to a file. + /// + /// Only replacements that are in a valid file can be applied. + bool isApplicable() const; + + /// \brief Accessors. + /// @{ + StringRef getFilePath() const { return FilePath; } + unsigned getOffset() const { return Offset; } + unsigned getLength() const { return Length; } + /// @} + + /// \brief Applies the replacement on the Rewriter. + bool apply(Rewriter &Rewrite) const; + + /// \brief Returns a human readable string representation. + std::string toString() const; + + /// \brief Comparator to be able to use Replacement in std::set for uniquing. + class Less { + public: + bool operator()(const Replacement &R1, const Replacement &R2) const; + }; + + private: + void setFromSourceLocation(SourceManager &Sources, SourceLocation Start, + unsigned Length, llvm::StringRef ReplacementText); + void setFromSourceRange(SourceManager &Sources, const CharSourceRange &Range, + llvm::StringRef ReplacementText); + + std::string FilePath; + unsigned Offset; + unsigned Length; + std::string ReplacementText; +}; + +/// \brief A set of Replacements. +/// FIXME: Change to a vector and deduplicate in the RefactoringTool. +typedef std::set<Replacement, Replacement::Less> Replacements; + +/// \brief Apply all replacements on the Rewriter. +/// +/// If at least one Apply returns false, ApplyAll returns false. Every +/// Apply will be executed independently of the result of other +/// Apply operations. +bool applyAllReplacements(Replacements &Replaces, Rewriter &Rewrite); + +/// \brief A tool to run refactorings. +/// +/// This is a refactoring specific version of \see ClangTool. +/// All text replacements added to getReplacements() during the run of the +/// tool will be applied and saved after all translation units have been +/// processed. +class RefactoringTool { +public: + /// \see ClangTool::ClangTool. + RefactoringTool(const CompilationDatabase &Compilations, + ArrayRef<std::string> SourcePaths); + + /// \brief Returns a set of replacements. All replacements added during the + /// run of the tool will be applied after all translation units have been + /// processed. + Replacements &getReplacements(); + + /// \see ClangTool::run. + int run(FrontendActionFactory *ActionFactory); + +private: + ClangTool Tool; + Replacements Replace; +}; + +template <typename Node> +Replacement::Replacement(SourceManager &Sources, const Node &NodeToReplace, + llvm::StringRef ReplacementText) { + const CharSourceRange Range = + CharSourceRange::getTokenRange(NodeToReplace->getSourceRange()); + setFromSourceRange(Sources, Range, ReplacementText); +} + +} // end namespace tooling +} // end namespace clang + +#endif // end namespace LLVM_CLANG_TOOLING_REFACTORING_H + diff --git a/include/clang/Tooling/RefactoringCallbacks.h b/include/clang/Tooling/RefactoringCallbacks.h new file mode 100644 index 0000000..c500f35 --- /dev/null +++ b/include/clang/Tooling/RefactoringCallbacks.h @@ -0,0 +1,90 @@ +//===--- RefactoringCallbacks.h - Structural query framework ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Provides callbacks to make common kinds of refactorings easy. +// +// The general idea is to construct a matcher expression that describes a +// subtree match on the AST and then replace the corresponding source code +// either by some specific text or some other AST node. +// +// Example: +// int main(int argc, char **argv) { +// ClangTool Tool(argc, argv); +// MatchFinder Finder; +// ReplaceStmtWithText Callback("integer", "42"); +// Finder.AddMatcher(id("integer", expression(integerLiteral())), Callback); +// return Tool.run(newFrontendActionFactory(&Finder)); +// } +// +// This will replace all integer literals with "42". +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_REFACTORING_CALLBACKS_H +#define LLVM_CLANG_TOOLING_REFACTORING_CALLBACKS_H + +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Tooling/Refactoring.h" + +namespace clang { +namespace tooling { + +/// \brief Base class for RefactoringCallbacks. +/// +/// Collects \c tooling::Replacements while running. +class RefactoringCallback : public ast_matchers::MatchFinder::MatchCallback { +public: + RefactoringCallback(); + Replacements &getReplacements(); + +protected: + Replacements Replace; +}; + +/// \brief Replace the text of the statement bound to \c FromId with the text in +/// \c ToText. +class ReplaceStmtWithText : public RefactoringCallback { +public: + ReplaceStmtWithText(StringRef FromId, StringRef ToText); + virtual void run(const ast_matchers::MatchFinder::MatchResult &Result); + +private: + std::string FromId; + std::string ToText; +}; + +/// \brief Replace the text of the statement bound to \c FromId with the text of +/// the statement bound to \c ToId. +class ReplaceStmtWithStmt : public RefactoringCallback { +public: + ReplaceStmtWithStmt(StringRef FromId, StringRef ToId); + virtual void run(const ast_matchers::MatchFinder::MatchResult &Result); + +private: + std::string FromId; + std::string ToId; +}; + +/// \brief Replace an if-statement bound to \c Id with the outdented text of its +/// body, choosing the consequent or the alternative based on whether +/// \c PickTrueBranch is true. +class ReplaceIfStmtWithItsBody : public RefactoringCallback { +public: + ReplaceIfStmtWithItsBody(StringRef Id, bool PickTrueBranch); + virtual void run(const ast_matchers::MatchFinder::MatchResult &Result); + +private: + std::string Id; + const bool PickTrueBranch; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_REFACTORING_CALLBACKS_H diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h index 868eae3..e06705f 100644 --- a/include/clang/Tooling/Tooling.h +++ b/include/clang/Tooling/Tooling.h @@ -15,7 +15,7 @@ // all TUs in which the given files are compiled. // // It is also possible to run a FrontendAction over a snippet of code by -// calling runSyntaxOnlyToolOnCode, which is useful for unit testing. +// calling runToolOnCode, which is useful for unit testing. // // Applications that need more fine grained control over how to run // multiple FrontendActions over code can use ToolInvocation. @@ -35,6 +35,9 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/LLVM.h" #include "clang/Driver/Util.h" +#include "clang/Frontend/FrontendAction.h" +#include "clang/Tooling/ArgumentsAdjusters.h" +#include "clang/Tooling/CompilationDatabase.h" #include <string> #include <vector> @@ -50,8 +53,6 @@ class FrontendAction; namespace tooling { -class CompilationDatabase; - /// \brief Interface to generate clang::FrontendActions. class FrontendActionFactory { public: @@ -74,18 +75,19 @@ template <typename T> FrontendActionFactory *newFrontendActionFactory(); /// \brief Returns a new FrontendActionFactory for any type that provides an -/// implementation of newFrontendAction(). +/// implementation of newASTConsumer(). /// -/// FactoryT must implement: FrontendAction *newFrontendAction(). +/// FactoryT must implement: ASTConsumer *newASTConsumer(). /// /// Example: -/// struct ProvidesFrontendActions { -/// FrontendAction *newFrontendAction(); +/// struct ProvidesASTConsumers { +/// clang::ASTConsumer *newASTConsumer(); /// } Factory; /// FrontendActionFactory *FactoryAdapter = /// newFrontendActionFactory(&Factory); template <typename FactoryT> -FrontendActionFactory *newFrontendActionFactory(FactoryT *ActionFactory); +inline FrontendActionFactory *newFrontendActionFactory( + FactoryT *ConsumerFactory); /// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag. /// @@ -102,7 +104,10 @@ class ToolInvocation { public: /// \brief Create a tool invocation. /// - /// \param CommandLine The command line arguments to clang. + /// \param CommandLine The command line arguments to clang. Note that clang + /// uses its binary name (CommandLine[0]) to locate its builtin headers. + /// Callers have to ensure that they are installed in a compatible location + /// (see clang driver implementation) or mapped in via mapVirtualFile. /// \param ToolAction The action to be executed. Class takes ownership. /// \param Files The FileManager used for the execution. Class does not take /// ownership. @@ -126,8 +131,7 @@ class ToolInvocation { bool runInvocation(const char *BinaryName, clang::driver::Compilation *Compilation, clang::CompilerInvocation *Invocation, - const clang::driver::ArgStringList &CC1Args, - clang::FrontendAction *ToolAction); + const clang::driver::ArgStringList &CC1Args); std::vector<std::string> CommandLine; llvm::OwningPtr<FrontendAction> ToolAction; @@ -139,6 +143,10 @@ class ToolInvocation { /// \brief Utility to run a FrontendAction over a set of files. /// /// This class is written to be usable for command line utilities. +/// By default the class uses ClangSyntaxOnlyAdjuster to modify +/// command line arguments before the arguments are used to run +/// a frontend action. One could install another command line +/// arguments adjuster by call setArgumentsAdjuster() method. class ClangTool { public: /// \brief Constructs a clang tool to run over a list of files. @@ -156,6 +164,11 @@ class ClangTool { /// \param Content A null terminated buffer of the file's content. void mapVirtualFile(StringRef FilePath, StringRef Content); + /// \brief Install command line arguments adjuster. + /// + /// \param Adjuster Command line arguments adjuster. + void setArgumentsAdjuster(ArgumentsAdjuster *Adjuster); + /// Runs a frontend action over all files specified in the command line. /// /// \param ActionFactory Factory generating the frontend actions. The function @@ -169,13 +182,14 @@ class ClangTool { FileManager &getFiles() { return Files; } private: - // We store command lines as pair (file name, command line). - typedef std::pair< std::string, std::vector<std::string> > CommandLine; - std::vector<CommandLine> CommandLines; + // We store compile commands as pair (file name, compile command). + std::vector< std::pair<std::string, CompileCommand> > CompileCommands; FileManager Files; // Contains a list of pairs (<file name>, <file content>). std::vector< std::pair<StringRef, StringRef> > MappedFileContents; + + llvm::OwningPtr<ArgumentsAdjuster> ArgsAdjuster; }; template <typename T> @@ -189,25 +203,54 @@ FrontendActionFactory *newFrontendActionFactory() { } template <typename FactoryT> -FrontendActionFactory *newFrontendActionFactory(FactoryT *ActionFactory) { +inline FrontendActionFactory *newFrontendActionFactory( + FactoryT *ConsumerFactory) { class FrontendActionFactoryAdapter : public FrontendActionFactory { public: - explicit FrontendActionFactoryAdapter(FactoryT *ActionFactory) - : ActionFactory(ActionFactory) {} + explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory) + : ConsumerFactory(ConsumerFactory) {} virtual clang::FrontendAction *create() { - return ActionFactory->newFrontendAction(); + return new ConsumerFactoryAdaptor(ConsumerFactory); } private: - FactoryT *ActionFactory; + class ConsumerFactoryAdaptor : public clang::ASTFrontendAction { + public: + ConsumerFactoryAdaptor(FactoryT *ConsumerFactory) + : ConsumerFactory(ConsumerFactory) {} + + clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &, + llvm::StringRef) { + return ConsumerFactory->newASTConsumer(); + } + + private: + FactoryT *ConsumerFactory; + }; + FactoryT *ConsumerFactory; }; - return new FrontendActionFactoryAdapter(ActionFactory); + return new FrontendActionFactoryAdapter(ConsumerFactory); } +/// \brief Returns the absolute path of \c File, by prepending it with +/// the current directory if \c File is not absolute. +/// +/// Otherwise returns \c File. +/// If 'File' starts with "./", the returned path will not contain the "./". +/// Otherwise, the returned path will contain the literal path-concatenation of +/// the current directory and \c File. +/// +/// The difference to llvm::sys::fs::make_absolute is that we prefer +/// ::getenv("PWD") if available. +/// FIXME: Make this functionality available from llvm::sys::fs and delete +/// this function. +/// +/// \param File Either an absolute or relative path. +std::string getAbsolutePath(StringRef File); + } // end namespace tooling } // end namespace clang #endif // LLVM_CLANG_TOOLING_TOOLING_H - |