diff options
Diffstat (limited to 'include/clang')
72 files changed, 2425 insertions, 942 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index f9d2f71..4f29e5d 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -120,8 +120,7 @@ class ASTContext { QualType ObjCIdTypedefType; /// ObjCSelType - another pseudo built-in typedef type (set by Sema). - QualType ObjCSelType; - const RecordType *SelStructType; + QualType ObjCSelTypedefType; /// ObjCProtoType - another pseudo built-in typedef type (set by Sema). QualType ObjCProtoType; @@ -244,6 +243,7 @@ public: // pseudo-builtins QualType ObjCIdRedefinitionType; QualType ObjCClassRedefinitionType; + QualType ObjCSelRedefinitionType; /// \brief Source ranges for all of the comments in the source file, /// sorted in order of appearance in the translation unit. @@ -316,7 +316,7 @@ public: CanQualType OverloadTy; CanQualType DependentTy; CanQualType UndeducedAutoTy; - CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy; + CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy; ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t, IdentifierTable &idents, SelectorTable &sels, @@ -532,8 +532,7 @@ public: QualType Canon = QualType()); QualType getTemplateSpecializationType(TemplateName T, - const TemplateArgumentLoc *Args, - unsigned NumArgs, + const TemplateArgumentListInfo &Args, QualType Canon = QualType()); QualType getQualifiedNameType(NestedNameSpecifier *NNS, @@ -696,7 +695,7 @@ public: void setObjCIdType(QualType T); void setObjCSelType(QualType T); - QualType getObjCSelType() const { return ObjCSelType; } + QualType getObjCSelType() const { return ObjCSelTypedefType; } void setObjCProtoType(QualType QT); QualType getObjCProtoType() const { return ObjCProtoType; } @@ -734,6 +733,8 @@ public: return getExtQualType(T, Qs); } + DeclarationName getNameForTemplate(TemplateName Name); + TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, TemplateDecl *Template); @@ -796,6 +797,20 @@ public: return getTypeInfo(T).first; } + /// getByteWidth - Return the size of a byte, in bits + uint64_t getByteSize() { + return getTypeSize(CharTy); + } + + /// getTypeSizeInBytes - Return the size of the specified type, in bytes. + /// This method does not work on incomplete types. + uint64_t getTypeSizeInBytes(QualType T) { + return getTypeSize(T) / getByteSize(); + } + uint64_t getTypeSizeInBytes(const Type *T) { + return getTypeSize(T) / getByteSize(); + } + /// getTypeAlign - Return the ABI-specified alignment of a type, in bits. /// This method does not work on incomplete types. unsigned getTypeAlign(QualType T) { @@ -811,10 +826,7 @@ public: /// a data type. unsigned getPreferredTypeAlign(const Type *T); - /// getDeclAlignInBytes - Return the alignment of the specified decl - /// that should be returned by __alignof(). Note that bitfields do - /// not have a valid alignment, so this method will assert on them. - unsigned getDeclAlignInBytes(const Decl *D); + unsigned getDeclAlignInBytes(const Decl *D, bool RefAsPointee = false); /// getASTRecordLayout - Get or compute information about the layout of the /// specified record (struct/union/class), which indicates its size and field @@ -1023,8 +1035,7 @@ public: return T == ObjCClassTypedefType; } bool isObjCSelType(QualType T) const { - assert(SelStructType && "isObjCSelType used before 'SEL' type is built"); - return T->getAsStructureType() == SelStructType; + return T == ObjCSelTypedefType; } bool QualifiedIdConformsQualifiedId(QualType LHS, QualType RHS); bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS, diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index b36ff12..2c7ab9d 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -15,12 +15,12 @@ #define LLVM_CLANG_AST_ATTR_H #include "llvm/Support/Casting.h" -using llvm::dyn_cast; - +#include "llvm/ADT/StringRef.h" #include <cassert> #include <cstring> #include <string> #include <algorithm> +using llvm::dyn_cast; namespace clang { class ASTContext; @@ -49,6 +49,7 @@ public: AnalyzerNoReturn, // Clang-specific. Annotate, AsmLabel, // Represent GCC asm label extension. + BaseCheck, Blocks, CDecl, Cleanup, @@ -59,9 +60,11 @@ public: Deprecated, Destructor, FastCall, + Final, Format, FormatArg, GNUInline, + Hiding, IBOutletKind, // Clang-specific. Use "Kind" suffix to not conflict with Malloc, NoDebug, @@ -71,6 +74,7 @@ public: NoThrow, ObjCException, ObjCNSObject, + Override, CFReturnsRetained, // Clang/Checker-specific. NSReturnsRetained, // Clang/Checker-specific. Overloadable, // Clang-specific @@ -184,12 +188,24 @@ public: class AlignedAttr : public Attr { unsigned Alignment; public: - AlignedAttr(unsigned alignment) : Attr(Aligned), Alignment(alignment) {} + AlignedAttr(unsigned alignment) + : Attr(Aligned), Alignment(alignment) {} /// getAlignment - The specified alignment in bits. unsigned getAlignment() const { return Alignment; } + + /// getMaxAlignment - Get the maximum alignment of attributes on this list. + unsigned getMaxAlignment() const { + const AlignedAttr *Next = getNext<AlignedAttr>(); + if (Next) + return std::max(Next->getMaxAlignment(), Alignment); + else + return Alignment; + } - virtual Attr* clone(ASTContext &C) const { return ::new (C) AlignedAttr(Alignment); } + virtual Attr* clone(ASTContext &C) const { + return ::new (C) AlignedAttr(Alignment); + } // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { @@ -201,7 +217,7 @@ public: class AnnotateAttr : public Attr { std::string Annotation; public: - AnnotateAttr(const std::string &ann) : Attr(Annotate), Annotation(ann) {} + AnnotateAttr(llvm::StringRef ann) : Attr(Annotate), Annotation(ann) {} const std::string& getAnnotation() const { return Annotation; } @@ -217,7 +233,7 @@ public: class AsmLabelAttr : public Attr { std::string Label; public: - AsmLabelAttr(const std::string &L) : Attr(AsmLabel), Label(L) {} + AsmLabelAttr(llvm::StringRef L) : Attr(AsmLabel), Label(L) {} const std::string& getLabel() const { return Label; } @@ -235,7 +251,7 @@ DEF_SIMPLE_ATTR(AlwaysInline); class AliasAttr : public Attr { std::string Aliasee; public: - AliasAttr(const std::string &aliasee) : Attr(Alias), Aliasee(aliasee) {} + AliasAttr(llvm::StringRef aliasee) : Attr(Alias), Aliasee(aliasee) {} const std::string& getAliasee() const { return Aliasee; } @@ -304,11 +320,12 @@ DEF_SIMPLE_ATTR(Malloc); DEF_SIMPLE_ATTR(NoReturn); DEF_SIMPLE_ATTR(AnalyzerNoReturn); DEF_SIMPLE_ATTR(Deprecated); +DEF_SIMPLE_ATTR(Final); class SectionAttr : public Attr { std::string Name; public: - SectionAttr(const std::string &N) : Attr(Section), Name(N) {} + SectionAttr(llvm::StringRef N) : Attr(Section), Name(N) {} const std::string& getName() const { return Name; } @@ -367,11 +384,11 @@ class FormatAttr : public Attr { std::string Type; int formatIdx, firstArg; public: - FormatAttr(const std::string &type, int idx, int first) : Attr(Format), + FormatAttr(llvm::StringRef type, int idx, int first) : Attr(Format), Type(type), formatIdx(idx), firstArg(first) {} const std::string& getType() const { return Type; } - void setType(const std::string &type) { Type = type; } + void setType(llvm::StringRef type) { Type = type; } int getFormatIdx() const { return formatIdx; } int getFirstArg() const { return firstArg; } @@ -544,6 +561,11 @@ public: DEF_SIMPLE_ATTR(CFReturnsRetained); DEF_SIMPLE_ATTR(NSReturnsRetained); +// C++0x member checking attributes. +DEF_SIMPLE_ATTR(BaseCheck); +DEF_SIMPLE_ATTR(Hiding); +DEF_SIMPLE_ATTR(Override); + #undef DEF_SIMPLE_ATTR } // end namespace clang diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index ac79a91..f794477 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -54,6 +54,32 @@ public: TypeLoc getTypeLoc() const; }; +/// UnresolvedSet - A set of unresolved declarations. This is needed +/// in a lot of places, but isn't really worth breaking into its own +/// header right now. +class UnresolvedSet { + typedef llvm::SmallVector<NamedDecl*, 4> DeclsTy; + DeclsTy Decls; + +public: + void addDecl(NamedDecl *D) { + Decls.push_back(D); + } + + bool replace(const NamedDecl* Old, NamedDecl *New) { + for (DeclsTy::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) + if (*I == Old) + return (*I = New, true); + return false; + } + + unsigned size() const { return Decls.size(); } + + typedef DeclsTy::const_iterator iterator; + iterator begin() const { return Decls.begin(); } + iterator end() const { return Decls.end(); } +}; + /// TranslationUnitDecl - The top declaration context. class TranslationUnitDecl : public Decl, public DeclContext { ASTContext &Ctx; @@ -172,6 +198,26 @@ public: /// \brief Determine whether this declaration has linkage. bool hasLinkage() const; + /// \brief Describes the different kinds of linkage + /// (C++ [basic.link], C99 6.2.2) that an entity may have. + enum Linkage { + /// \brief No linkage, which means that the entity is unique and + /// can only be referred to from within its scope. + NoLinkage = 0, + + /// \brief Internal linkage, which indicates that the entity can + /// be referred to from within the translation unit (but not other + /// translation units). + InternalLinkage, + + /// \brief External linkage, which indicates that the entity can + /// be referred to from other translation units. + ExternalLinkage + }; + + /// \brief Determine what kind of linkage this entity has. + Linkage getLinkage() const; + /// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for /// the underlying named decl. NamedDecl *getUnderlyingDecl(); diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 79f7663..e1f948f 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -503,12 +503,12 @@ private: /// PrettyStackTraceDecl - If a crash occurs, indicate that it happened when /// doing something to a specific decl. class PrettyStackTraceDecl : public llvm::PrettyStackTraceEntry { - Decl *TheDecl; + const Decl *TheDecl; SourceLocation Loc; SourceManager &SM; const char *Message; public: - PrettyStackTraceDecl(Decl *theDecl, SourceLocation L, + PrettyStackTraceDecl(const Decl *theDecl, SourceLocation L, SourceManager &sm, const char *Msg) : TheDecl(theDecl), Loc(L), SM(sm), Message(Msg) {} diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index e5bf78c..990403e7 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -376,13 +376,13 @@ class CXXRecordDecl : public RecordDecl { /// of this C++ class (but not its inherited conversion /// functions). Each of the entries in this overload set is a /// CXXConversionDecl. - OverloadedFunctionDecl Conversions; + UnresolvedSet Conversions; /// VisibleConversions - Overload set containing the conversion functions /// of this C++ class and all those inherited conversion functions that /// are visible in this class. Each of the entries in this overload set is /// a CXXConversionDecl or a FunctionTemplateDecl. - OverloadedFunctionDecl VisibleConversions; + UnresolvedSet VisibleConversions; /// \brief The template or declaration that this declaration /// describes or was instantiated from, respectively. @@ -400,7 +400,7 @@ class CXXRecordDecl : public RecordDecl { const llvm::SmallPtrSet<CanQualType, 8> &TopConversionsTypeSet, const llvm::SmallPtrSet<CanQualType, 8> &HiddenConversionTypes); void collectConversionFunctions( - llvm::SmallPtrSet<CanQualType, 8>& ConversionsTypeSet); + llvm::SmallPtrSet<CanQualType, 8>& ConversionsTypeSet) const; protected: CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, @@ -581,22 +581,34 @@ public: /// getConversions - Retrieve the overload set containing all of the /// conversion functions in this class. - OverloadedFunctionDecl *getConversionFunctions() { + UnresolvedSet *getConversionFunctions() { assert((this->isDefinition() || cast<RecordType>(getTypeForDecl())->isBeingDefined()) && "getConversionFunctions() called on incomplete type"); return &Conversions; } - const OverloadedFunctionDecl *getConversionFunctions() const { + const UnresolvedSet *getConversionFunctions() const { assert((this->isDefinition() || cast<RecordType>(getTypeForDecl())->isBeingDefined()) && "getConversionFunctions() called on incomplete type"); return &Conversions; } + typedef UnresolvedSet::iterator conversion_iterator; + conversion_iterator conversion_begin() const { return Conversions.begin(); } + conversion_iterator conversion_end() const { return Conversions.end(); } + + /// Replaces a conversion function with a new declaration. + /// + /// Returns true if the old conversion was found. + bool replaceConversion(const NamedDecl* Old, NamedDecl *New) { + return Conversions.replace(Old, New); + } + /// getVisibleConversionFunctions - get all conversion functions visible /// in current class; including conversion function templates. - OverloadedFunctionDecl *getVisibleConversionFunctions(); + const UnresolvedSet *getVisibleConversionFunctions(); + /// addVisibleConversionFunction - Add a new conversion function to the /// list of visible conversion functions. void addVisibleConversionFunction(CXXConversionDecl *ConvDecl); @@ -1502,9 +1514,9 @@ class UsingDirectiveDecl : public NamedDecl { SourceLocation IdentLoc; /// NominatedNamespace - Namespace nominated by using-directive. - NamespaceDecl *NominatedNamespace; + NamedDecl *NominatedNamespace; - /// Enclosing context containing both using-directive and nomintated + /// Enclosing context containing both using-directive and nominated /// namespace. DeclContext *CommonAncestor; @@ -1520,12 +1532,12 @@ class UsingDirectiveDecl : public NamedDecl { SourceRange QualifierRange, NestedNameSpecifier *Qualifier, SourceLocation IdentLoc, - NamespaceDecl *Nominated, + NamedDecl *Nominated, DeclContext *CommonAncestor) : NamedDecl(Decl::UsingDirective, DC, L, getName()), NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange), Qualifier(Qualifier), IdentLoc(IdentLoc), - NominatedNamespace(Nominated? Nominated->getOriginalNamespace() : 0), + NominatedNamespace(Nominated), CommonAncestor(CommonAncestor) { } @@ -1538,8 +1550,13 @@ public: /// name of the namespace. NestedNameSpecifier *getQualifier() const { return Qualifier; } + NamedDecl *getNominatedNamespaceAsWritten() { return NominatedNamespace; } + const NamedDecl *getNominatedNamespaceAsWritten() const { + return NominatedNamespace; + } + /// getNominatedNamespace - Returns namespace nominated by using-directive. - NamespaceDecl *getNominatedNamespace() { return NominatedNamespace; } + NamespaceDecl *getNominatedNamespace(); const NamespaceDecl *getNominatedNamespace() const { return const_cast<UsingDirectiveDecl*>(this)->getNominatedNamespace(); @@ -1562,7 +1579,7 @@ public: SourceRange QualifierRange, NestedNameSpecifier *Qualifier, SourceLocation IdentLoc, - NamespaceDecl *Nominated, + NamedDecl *Nominated, DeclContext *CommonAncestor); static bool classof(const Decl *D) { diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 14f6660..3ecc4bb 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -955,8 +955,7 @@ public: TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, TemplateArgumentListBuilder &Builder, - TemplateArgumentLoc *ArgInfos, - unsigned NumArgInfos, + const TemplateArgumentListInfo &ArgInfos, ClassTemplatePartialSpecializationDecl *PrevDecl); /// Get the list of template parameters diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index a30f6e8..676bd2c 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -25,6 +25,7 @@ namespace llvm { namespace clang { class CXXSpecialName; class CXXOperatorIdName; + class CXXLiteralOperatorIdName; class DeclarationNameExtra; class IdentifierInfo; class MultiKeywordSelector; @@ -48,6 +49,7 @@ public: CXXDestructorName, CXXConversionFunctionName, CXXOperatorName, + CXXLiteralOperatorName, CXXUsingDirective }; @@ -115,6 +117,12 @@ private: return 0; } + CXXLiteralOperatorIdName *getAsCXXLiteralOperatorIdName() const { + if (getNameKind() == CXXLiteralOperatorName) + return reinterpret_cast<CXXLiteralOperatorIdName *>(Ptr & ~PtrMask); + return 0; + } + // Construct a declaration name from the name of a C++ constructor, // destructor, or conversion function. DeclarationName(CXXSpecialName *Name) @@ -131,6 +139,12 @@ private: Ptr |= StoredDeclarationNameExtra; } + DeclarationName(CXXLiteralOperatorIdName *Name) + : Ptr(reinterpret_cast<uintptr_t>(Name)) { + assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXLiteralOperatorId"); + Ptr |= StoredDeclarationNameExtra; + } + /// Construct a declaration name from a raw pointer. DeclarationName(uintptr_t Ptr) : Ptr(Ptr) { } @@ -201,7 +215,7 @@ public: N.Ptr = reinterpret_cast<uintptr_t> (P); return N; } - + static DeclarationName getFromOpaqueInteger(uintptr_t P) { DeclarationName N; N.Ptr = P; @@ -218,6 +232,10 @@ public: /// kind of overloaded operator. OverloadedOperatorKind getCXXOverloadedOperator() const; + /// getCXXLiteralIdentifier - If this name is the name of a literal + /// operator, retrieve the identifier associated with it. + IdentifierInfo *getCXXLiteralIdentifier() const; + /// getObjCSelector - Get the Objective-C selector stored in this /// declaration name. Selector getObjCSelector() const; @@ -293,7 +311,7 @@ public: /// getIdentifier - Create a declaration name that is a simple /// identifier. - DeclarationName getIdentifier(IdentifierInfo *ID) { + DeclarationName getIdentifier(const IdentifierInfo *ID) { return DeclarationName(ID); } @@ -324,6 +342,10 @@ public: /// getCXXOperatorName - Get the name of the overloadable C++ /// operator corresponding to Op. DeclarationName getCXXOperatorName(OverloadedOperatorKind Op); + + /// getCXXLiteralOperatorName - Get the name of the literal operator function + /// with II as the identifier. + DeclarationName getCXXLiteralOperatorName(IdentifierInfo *II); }; /// Insertion operator for diagnostics. This allows sending DeclarationName's diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index dfc5b13..7cf9aab 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -35,6 +35,7 @@ namespace clang { class CXXOperatorCallExpr; class CXXMemberCallExpr; class TemplateArgumentLoc; + class TemplateArgumentListInfo; /// Expr - This represents one expression. Note that Expr's are subclasses of /// Stmt. This allows an expression to be transparently used any place a Stmt @@ -366,6 +367,10 @@ struct ExplicitTemplateArgumentList { const TemplateArgumentLoc *getTemplateArgs() const { return reinterpret_cast<const TemplateArgumentLoc *> (this + 1); } + + void initializeFrom(const TemplateArgumentListInfo &List); + void copyInto(TemplateArgumentListInfo &List) const; + static std::size_t sizeFor(const TemplateArgumentListInfo &List); }; /// DeclRefExpr - [C99 6.5.1p2] - A reference to a declared variable, function, @@ -423,31 +428,24 @@ class DeclRefExpr : public Expr { DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, NamedDecl *D, SourceLocation NameLoc, - bool HasExplicitTemplateArgumentList, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, - SourceLocation RAngleLoc, - QualType T, bool TD, bool VD); + const TemplateArgumentListInfo *TemplateArgs, + QualType T); protected: - // FIXME: Eventually, this constructor will go away and all subclasses - // will have to provide the type- and value-dependent flags. - DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l) : - Expr(SC, t), DecoratedD(d, 0), Loc(l) {} + /// \brief Computes the type- and value-dependence flags for this + /// declaration reference expression. + void computeDependence(); - DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l, bool TD, - bool VD) : - Expr(SC, t, TD, VD), DecoratedD(d, 0), Loc(l) {} + DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l) : + Expr(SC, t, false, false), DecoratedD(d, 0), Loc(l) { + computeDependence(); + } public: - // FIXME: Eventually, this constructor will go away and all clients - // will have to provide the type- and value-dependent flags. DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l) : - Expr(DeclRefExprClass, t), DecoratedD(d, 0), Loc(l) {} - - DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, bool VD) : - Expr(DeclRefExprClass, t, TD, VD), DecoratedD(d, 0), Loc(l) {} + Expr(DeclRefExprClass, t, false, false), DecoratedD(d, 0), Loc(l) { + computeDependence(); + } /// \brief Construct an empty declaration reference expression. explicit DeclRefExpr(EmptyShell Empty) @@ -458,19 +456,8 @@ public: SourceRange QualifierRange, NamedDecl *D, SourceLocation NameLoc, - QualType T, bool TD, bool VD); - - static DeclRefExpr *Create(ASTContext &Context, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - NamedDecl *D, - SourceLocation NameLoc, - bool HasExplicitTemplateArgumentList, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, - SourceLocation RAngleLoc, - QualType T, bool TD, bool VD); + QualType T, + const TemplateArgumentListInfo *TemplateArgs = 0); NamedDecl *getDecl() { return DecoratedD.getPointer(); } const NamedDecl *getDecl() const { return DecoratedD.getPointer(); } @@ -508,6 +495,13 @@ public: bool hasExplicitTemplateArgumentList() const { return DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag; } + + /// \brief Copies the template arguments (if present) into the given + /// structure. + void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { + if (hasExplicitTemplateArgumentList()) + getExplicitTemplateArgumentList()->copyInto(List); + } /// \brief Retrieve the location of the left angle bracket following the /// member name ('<'), if any. @@ -546,8 +540,7 @@ public: } static bool classof(const Stmt *T) { - return T->getStmtClass() == DeclRefExprClass || - T->getStmtClass() == CXXConditionDeclExprClass; + return T->getStmtClass() == DeclRefExprClass; } static bool classof(const DeclRefExpr *) { return true; } @@ -1313,9 +1306,7 @@ class MemberExpr : public Expr { MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual, SourceRange qualrange, NamedDecl *memberdecl, SourceLocation l, - bool has_explicit, SourceLocation langle, - const TemplateArgumentLoc *targs, unsigned numtargs, - SourceLocation rangle, QualType ty); + const TemplateArgumentListInfo *targs, QualType ty); public: MemberExpr(Expr *base, bool isarrow, NamedDecl *memberdecl, SourceLocation l, @@ -1334,11 +1325,7 @@ public: NestedNameSpecifier *qual, SourceRange qualrange, NamedDecl *memberdecl, SourceLocation l, - bool has_explicit, - SourceLocation langle, - const TemplateArgumentLoc *targs, - unsigned numtargs, - SourceLocation rangle, + const TemplateArgumentListInfo *targs, QualType ty); void setBase(Expr *E) { Base = E; } @@ -1378,10 +1365,17 @@ public: /// \brief Determines whether this member expression actually had a C++ /// template argument list explicitly specified, e.g., x.f<int>. - bool hasExplicitTemplateArgumentList() { + bool hasExplicitTemplateArgumentList() const { return HasExplicitTemplateArgumentList; } + /// \brief Copies the template arguments (if present) into the given + /// structure. + void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { + if (hasExplicitTemplateArgumentList()) + getExplicitTemplateArgumentList()->copyInto(List); + } + /// \brief Retrieve the location of the left angle bracket following the /// member name ('<'), if any. SourceLocation getLAngleLoc() const { @@ -1579,7 +1573,11 @@ public: CK_FloatingToIntegral, /// CK_FloatingCast - Casting between floating types of different size. - CK_FloatingCast + CK_FloatingCast, + + /// CK_MemberPointerToBoolean - Member pointer to boolean + CK_MemberPointerToBoolean + }; private: diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 9e6fd4f..23844ce 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -17,6 +17,7 @@ #include "clang/Basic/TypeTraits.h" #include "clang/AST/Expr.h" #include "clang/AST/Decl.h" +#include "clang/AST/TemplateBase.h" namespace clang { @@ -24,6 +25,7 @@ namespace clang { class CXXDestructorDecl; class CXXMethodDecl; class CXXTemporary; + class TemplateArgumentListInfo; //===--------------------------------------------------------------------===// // C++ Expressions. @@ -669,40 +671,6 @@ public: virtual child_iterator child_end(); }; -/// CXXConditionDeclExpr - Condition declaration of a if/switch/while/for -/// statement, e.g: "if (int x = f()) {...}". -/// The main difference with DeclRefExpr is that CXXConditionDeclExpr owns the -/// decl that it references. -/// -class CXXConditionDeclExpr : public DeclRefExpr { -public: - CXXConditionDeclExpr(SourceLocation startLoc, - SourceLocation eqLoc, VarDecl *var) - : DeclRefExpr(CXXConditionDeclExprClass, var, - var->getType().getNonReferenceType(), startLoc, - var->getType()->isDependentType(), - /*FIXME:integral constant?*/ - var->getType()->isDependentType()) {} - - SourceLocation getStartLoc() const { return getLocation(); } - - VarDecl *getVarDecl() { return cast<VarDecl>(getDecl()); } - const VarDecl *getVarDecl() const { return cast<VarDecl>(getDecl()); } - - virtual SourceRange getSourceRange() const { - return SourceRange(getStartLoc(), getVarDecl()->getInit()->getLocEnd()); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXConditionDeclExprClass; - } - static bool classof(const CXXConditionDeclExpr *) { return true; } - - // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); -}; - /// CXXNewExpr - A new expression for memory allocation and constructor calls, /// e.g: "new CXXNewExpr(foo)". class CXXNewExpr : public Expr { @@ -975,52 +943,6 @@ public: virtual child_iterator child_end(); }; -/// \brief Represents the name of a function that has not been -/// resolved to any declaration. -/// -/// Unresolved function names occur when a function name is -/// encountered prior to an open parentheses ('(') in a C++ function -/// call, and the function name itself did not resolve to a -/// declaration. These function names can only be resolved when they -/// form the postfix-expression of a function call, so that -/// argument-dependent lookup finds declarations corresponding to -/// these functions. - -/// @code -/// template<typename T> void f(T x) { -/// g(x); // g is an unresolved function name (that is also a dependent name) -/// } -/// @endcode -class UnresolvedFunctionNameExpr : public Expr { - /// The name that was present in the source - DeclarationName Name; - - /// The location of this name in the source code - SourceLocation Loc; - -public: - UnresolvedFunctionNameExpr(DeclarationName N, QualType T, SourceLocation L) - : Expr(UnresolvedFunctionNameExprClass, T, false, false), Name(N), Loc(L) { } - - /// \brief Retrieves the name that occurred in the source code. - DeclarationName getName() const { return Name; } - - /// getLocation - Retrieves the location in the source code where - /// the name occurred. - SourceLocation getLocation() const { return Loc; } - - virtual SourceRange getSourceRange() const { return SourceRange(Loc); } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == UnresolvedFunctionNameExprClass; - } - static bool classof(const UnresolvedFunctionNameExpr *) { return true; } - - // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); -}; - /// UnaryTypeTraitExpr - A GCC or MS unary type trait, as used in the /// implementation of TR1/C++0x type trait templates. /// Example: @@ -1063,21 +985,177 @@ public: virtual child_iterator child_end(); }; +/// \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: +/// * 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. +class UnresolvedLookupExpr : public Expr { + /// The results. These are undesugared, which is to say, they may + /// include UsingShadowDecls. + UnresolvedSet Results; + + /// The name declared. + DeclarationName Name; + + /// The qualifier given, if any. + NestedNameSpecifier *Qualifier; + + /// The source range of the nested name specifier. + SourceRange QualifierRange; + + /// The location of the name. + SourceLocation NameLoc; + + /// True if these lookup results should be extended by + /// argument-dependent lookup if this is the operand of a function + /// call. + bool RequiresADL; + + /// True if these lookup results are overloaded. This is pretty + /// trivially rederivable if we urgently need to kill this field. + bool Overloaded; + + /// True if the name looked up had explicit template arguments. + /// This requires all the results to be function templates. + bool HasExplicitTemplateArgs; + + UnresolvedLookupExpr(QualType T, bool Dependent, + NestedNameSpecifier *Qualifier, SourceRange QRange, + DeclarationName Name, SourceLocation NameLoc, + bool RequiresADL, bool Overloaded, bool HasTemplateArgs) + : Expr(UnresolvedLookupExprClass, T, Dependent, Dependent), + Name(Name), Qualifier(Qualifier), QualifierRange(QRange), + NameLoc(NameLoc), RequiresADL(RequiresADL), Overloaded(Overloaded), + HasExplicitTemplateArgs(HasTemplateArgs) + {} + +public: + static UnresolvedLookupExpr *Create(ASTContext &C, + bool Dependent, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName Name, + SourceLocation NameLoc, + bool ADL, bool Overloaded) { + return new(C) UnresolvedLookupExpr(Dependent ? C.DependentTy : C.OverloadTy, + Dependent, Qualifier, QualifierRange, + Name, NameLoc, ADL, Overloaded, false); + } + + static UnresolvedLookupExpr *Create(ASTContext &C, + bool Dependent, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName Name, + SourceLocation NameLoc, + bool ADL, + const TemplateArgumentListInfo &Args); + + /// Computes whether an unresolved lookup on the given declarations + /// and optional template arguments is type- and value-dependent. + static bool ComputeDependence(NamedDecl * const *Begin, + NamedDecl * const *End, + const TemplateArgumentListInfo *Args); + + void addDecl(NamedDecl *Decl) { + Results.addDecl(Decl); + } + + typedef UnresolvedSet::iterator decls_iterator; + decls_iterator decls_begin() const { return Results.begin(); } + decls_iterator decls_end() const { return Results.end(); } + + /// True if this declaration should be extended by + /// argument-dependent lookup. + bool requiresADL() const { return RequiresADL; } + + /// True if this lookup is overloaded. + bool isOverloaded() const { return Overloaded; } + + /// Fetches the name looked up. + DeclarationName getName() const { return Name; } + + /// Gets the location of the name. + SourceLocation getNameLoc() const { return NameLoc; } + + /// Fetches the nested-name qualifier, if one was given. + NestedNameSpecifier *getQualifier() const { return Qualifier; } + + /// Fetches the range of the nested-name qualifier. + SourceRange getQualifierRange() const { return QualifierRange; } + + /// Determines whether this lookup had explicit template arguments. + bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; } + + // Note that, inconsistently with the explicit-template-argument AST + // nodes, users are *forbidden* from calling these methods on objects + // without explicit template arguments. + + /// Gets a reference to the explicit template argument list. + const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { + assert(hasExplicitTemplateArgs()); + return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1); + } + + /// \brief Copies the template arguments (if present) into the given + /// structure. + void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { + getExplicitTemplateArgs().copyInto(List); + } + + SourceLocation getLAngleLoc() const { + return getExplicitTemplateArgs().LAngleLoc; + } + + SourceLocation getRAngleLoc() const { + return getExplicitTemplateArgs().RAngleLoc; + } + + TemplateArgumentLoc const *getTemplateArgs() const { + return getExplicitTemplateArgs().getTemplateArgs(); + } + + unsigned getNumTemplateArgs() const { + return getExplicitTemplateArgs().NumTemplateArgs; + } + + virtual SourceRange getSourceRange() const { + SourceRange Range(NameLoc); + if (Qualifier) Range.setBegin(QualifierRange.getBegin()); + if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); + return Range; + } + + virtual StmtIterator child_begin(); + virtual StmtIterator child_end(); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == UnresolvedLookupExprClass; + } + static bool classof(const UnresolvedLookupExpr *) { return true; } +}; + /// \brief A qualified reference to a name whose declaration cannot /// yet be resolved. /// -/// UnresolvedDeclRefExpr is similar to eclRefExpr in that +/// DependentScopeDeclRefExpr is similar to DeclRefExpr in that /// it expresses a reference to a declaration such as /// X<T>::value. The difference, however, is that an -/// UnresolvedDeclRefExpr node is used only within C++ templates when +/// DependentScopeDeclRefExpr node is used only within C++ templates when /// the qualification (e.g., X<T>::) refers to a dependent type. In /// this case, X<T>::value cannot resolve to a declaration because the /// declaration will differ from on instantiation of X<T> to the -/// next. Therefore, UnresolvedDeclRefExpr keeps track of the +/// next. Therefore, DependentScopeDeclRefExpr keeps track of the /// qualifier (X<T>::) and the name of the entity being referenced /// ("value"). Such expressions will instantiate to a DeclRefExpr once the /// declaration can be found. -class UnresolvedDeclRefExpr : public Expr { +class DependentScopeDeclRefExpr : public Expr { /// The name of the entity we will be referencing. DeclarationName Name; @@ -1090,19 +1168,30 @@ class UnresolvedDeclRefExpr : public Expr { /// \brief The nested-name-specifier that qualifies this unresolved /// declaration name. - NestedNameSpecifier *NNS; + NestedNameSpecifier *Qualifier; - /// \brief Whether this expr is an address of (&) operand. - /// FIXME: Stash this bit into NNS! - bool IsAddressOfOperand; + /// \brief Whether the name includes explicit template arguments. + bool HasExplicitTemplateArgs; + + DependentScopeDeclRefExpr(QualType T, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName Name, + SourceLocation NameLoc, + bool HasExplicitTemplateArgs) + : Expr(DependentScopeDeclRefExprClass, T, true, true), + Name(Name), Loc(NameLoc), + QualifierRange(QualifierRange), Qualifier(Qualifier), + HasExplicitTemplateArgs(HasExplicitTemplateArgs) + {} public: - UnresolvedDeclRefExpr(DeclarationName N, QualType T, SourceLocation L, - SourceRange R, NestedNameSpecifier *NNS, - bool IsAddressOfOperand) - : Expr(UnresolvedDeclRefExprClass, T, true, true), - Name(N), Loc(L), QualifierRange(R), NNS(NNS), - IsAddressOfOperand(IsAddressOfOperand) { } + static DependentScopeDeclRefExpr *Create(ASTContext &C, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo *TemplateArgs = 0); /// \brief Retrieve the name that this expression refers to. DeclarationName getDeclName() const { return Name; } @@ -1115,116 +1204,57 @@ public: /// \brief Retrieve the nested-name-specifier that qualifies this /// declaration. - NestedNameSpecifier *getQualifier() const { return NNS; } - - /// \brief Retrieve whether this is an address of (&) operand. - - bool isAddressOfOperand() const { return IsAddressOfOperand; } - virtual SourceRange getSourceRange() const { - return SourceRange(QualifierRange.getBegin(), getLocation()); - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == UnresolvedDeclRefExprClass; - } - static bool classof(const UnresolvedDeclRefExpr *) { return true; } - - virtual StmtIterator child_begin(); - virtual StmtIterator child_end(); -}; - -/// \brief An expression that refers to a C++ template-id, such as -/// @c isa<FunctionDecl>. -class TemplateIdRefExpr : public Expr { - /// \brief If this template-id was qualified-id, e.g., @c std::sort<int>, - /// this nested name specifier contains the @c std::. - NestedNameSpecifier *Qualifier; - - /// \brief If this template-id was a qualified-id, e.g., @c std::sort<int>, - /// this covers the source code range of the @c std::. - SourceRange QualifierRange; - - /// \brief The actual template to which this template-id refers. - TemplateName Template; - - /// \brief The source location of the template name. - SourceLocation TemplateNameLoc; - - /// \brief The source location of the left angle bracket ('<'); - SourceLocation LAngleLoc; - - /// \brief The source location of the right angle bracket ('>'); - SourceLocation RAngleLoc; - - /// \brief The number of template arguments in TemplateArgs. - unsigned NumTemplateArgs; - - TemplateIdRefExpr(QualType T, - NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - TemplateName Template, SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation RAngleLoc); - - virtual void DoDestroy(ASTContext &Context); - -public: - static TemplateIdRefExpr * - Create(ASTContext &Context, QualType T, - NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - TemplateName Template, SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, const TemplateArgumentLoc *TemplateArgs, - unsigned NumTemplateArgs, SourceLocation RAngleLoc); - - /// \brief Retrieve the nested name specifier used to qualify the name of - /// this template-id, e.g., the "std::sort" in @c std::sort<int>, or NULL - /// if this template-id was an unqualified-id. NestedNameSpecifier *getQualifier() const { return Qualifier; } - /// \brief Retrieve the source range describing the nested name specifier - /// used to qualified the name of this template-id, if the name was qualified. - SourceRange getQualifierRange() const { return QualifierRange; } + /// Determines whether this lookup had explicit template arguments. + bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; } - /// \brief Retrieve the name of the template referenced, e.g., "sort" in - /// @c std::sort<int>; - TemplateName getTemplateName() const { return Template; } + // Note that, inconsistently with the explicit-template-argument AST + // nodes, users are *forbidden* from calling these methods on objects + // without explicit template arguments. - /// \brief Retrieve the location of the name of the template referenced, e.g., - /// the location of "sort" in @c std::sort<int>. - SourceLocation getTemplateNameLoc() const { return TemplateNameLoc; } + /// Gets a reference to the explicit template argument list. + const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { + assert(hasExplicitTemplateArgs()); + return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1); + } - /// \brief Retrieve the location of the left angle bracket following the - /// template name ('<'). - SourceLocation getLAngleLoc() const { return LAngleLoc; } + /// \brief Copies the template arguments (if present) into the given + /// structure. + void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { + getExplicitTemplateArgs().copyInto(List); + } + + SourceLocation getLAngleLoc() const { + return getExplicitTemplateArgs().LAngleLoc; + } - /// \brief Retrieve the template arguments provided as part of this - /// template-id. - const TemplateArgumentLoc *getTemplateArgs() const { - return reinterpret_cast<const TemplateArgumentLoc *>(this + 1); + SourceLocation getRAngleLoc() const { + return getExplicitTemplateArgs().RAngleLoc; } - /// \brief Retrieve the number of template arguments provided as part of this - /// template-id. - unsigned getNumTemplateArgs() const { return NumTemplateArgs; } + TemplateArgumentLoc const *getTemplateArgs() const { + return getExplicitTemplateArgs().getTemplateArgs(); + } - /// \brief Retrieve the location of the right angle bracket following the - /// template arguments ('>'). - SourceLocation getRAngleLoc() const { return RAngleLoc; } + unsigned getNumTemplateArgs() const { + return getExplicitTemplateArgs().NumTemplateArgs; + } virtual SourceRange getSourceRange() const { - return SourceRange(Qualifier? QualifierRange.getBegin() : TemplateNameLoc, - RAngleLoc); + SourceRange Range(QualifierRange.getBegin(), getLocation()); + if (hasExplicitTemplateArgs()) + Range.setEnd(getRAngleLoc()); + return Range; } - // Iterators - virtual child_iterator child_begin(); - virtual child_iterator child_end(); - static bool classof(const Stmt *T) { - return T->getStmtClass() == TemplateIdRefExprClass; + return T->getStmtClass() == DependentScopeDeclRefExprClass; } - static bool classof(const TemplateIdRefExpr *) { return true; } + static bool classof(const DependentScopeDeclRefExpr *) { return true; } + + virtual StmtIterator child_begin(); + virtual StmtIterator child_end(); }; class CXXExprWithTemporaries : public Expr { @@ -1377,10 +1407,10 @@ public: virtual child_iterator child_end(); }; -/// \brief Represents a C++ member access expression where the actual member -/// referenced could not be resolved, e.g., because the base expression or the -/// member name was dependent. -class CXXUnresolvedMemberExpr : public Expr { +/// \brief Represents a C++ member access expression where the actual +/// member referenced could not be resolved because the base +/// expression or the member name was dependent. +class CXXDependentScopeMemberExpr : public Expr { /// \brief The expression for the base pointer or class reference, /// e.g., the \c x in x.f. Stmt *Base; @@ -1408,7 +1438,7 @@ class CXXUnresolvedMemberExpr : public Expr { /// /// FIXME: This member, along with the Qualifier and QualifierRange, could /// be stuck into a structure that is optionally allocated at the end of - /// the CXXUnresolvedMemberExpr, to save space in the common case. + /// the CXXDependentScopeMemberExpr, to save space in the common case. NamedDecl *FirstQualifierFoundInScope; /// \brief The member to which this member expression refers, which @@ -1431,11 +1461,11 @@ class CXXUnresolvedMemberExpr : public Expr { /// \brief Retrieve the explicit template argument list that followed the /// member template name, if any. const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const { - return const_cast<CXXUnresolvedMemberExpr *>(this) + return const_cast<CXXDependentScopeMemberExpr *>(this) ->getExplicitTemplateArgumentList(); } - CXXUnresolvedMemberExpr(ASTContext &C, + CXXDependentScopeMemberExpr(ASTContext &C, Expr *Base, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, @@ -1443,14 +1473,10 @@ class CXXUnresolvedMemberExpr : public Expr { NamedDecl *FirstQualifierFoundInScope, DeclarationName Member, SourceLocation MemberLoc, - bool HasExplicitTemplateArgs, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation RAngleLoc); + const TemplateArgumentListInfo *TemplateArgs); public: - CXXUnresolvedMemberExpr(ASTContext &C, + CXXDependentScopeMemberExpr(ASTContext &C, Expr *Base, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, @@ -1458,14 +1484,14 @@ public: NamedDecl *FirstQualifierFoundInScope, DeclarationName Member, SourceLocation MemberLoc) - : Expr(CXXUnresolvedMemberExprClass, C.DependentTy, true, true), + : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true), Base(Base), IsArrow(IsArrow), HasExplicitTemplateArgumentList(false), OperatorLoc(OperatorLoc), Qualifier(Qualifier), QualifierRange(QualifierRange), FirstQualifierFoundInScope(FirstQualifierFoundInScope), Member(Member), MemberLoc(MemberLoc) { } - static CXXUnresolvedMemberExpr * + static CXXDependentScopeMemberExpr * Create(ASTContext &C, Expr *Base, bool IsArrow, SourceLocation OperatorLoc, @@ -1474,11 +1500,7 @@ public: NamedDecl *FirstQualifierFoundInScope, DeclarationName Member, SourceLocation MemberLoc, - bool HasExplicitTemplateArgs, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation RAngleLoc); + const TemplateArgumentListInfo *TemplateArgs); /// \brief Retrieve the base object of this member expressions, /// e.g., the \c x in \c x.m. @@ -1529,10 +1551,17 @@ public: /// \brief Determines whether this member expression actually had a C++ /// template argument list explicitly specified, e.g., x.f<int>. - bool hasExplicitTemplateArgumentList() { + bool hasExplicitTemplateArgumentList() const { return HasExplicitTemplateArgumentList; } + /// \brief Copies the template arguments (if present) into the given + /// structure. + void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { + if (hasExplicitTemplateArgumentList()) + getExplicitTemplateArgumentList()->copyInto(List); + } + /// \brief Retrieve the location of the left angle bracket following the /// member name ('<'), if any. SourceLocation getLAngleLoc() const { @@ -1579,9 +1608,182 @@ public: } static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXUnresolvedMemberExprClass; + return T->getStmtClass() == CXXDependentScopeMemberExprClass; + } + static bool classof(const CXXDependentScopeMemberExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + +/// \brief Represents a C++ member access expression for which lookup +/// produced a set of overloaded functions. These are replaced with +/// MemberExprs in the final AST. +class UnresolvedMemberExpr : public Expr { + /// The results. These are undesugared, which is to say, they may + /// include UsingShadowDecls. + UnresolvedSet Results; + + /// \brief The expression for the base pointer or class reference, + /// e.g., the \c x in x.f. + Stmt *Base; + + /// \brief Whether this member expression used the '->' operator or + /// the '.' operator. + bool IsArrow : 1; + + /// \brief Whether the lookup results contain an unresolved using + /// declaration. + bool HasUnresolvedUsing : 1; + + /// \brief Whether this member expression has explicitly-specified template + /// arguments. + bool HasExplicitTemplateArgs : 1; + + /// \brief The location of the '->' or '.' operator. + SourceLocation OperatorLoc; + + /// \brief The nested-name-specifier that precedes the member name, if any. + NestedNameSpecifier *Qualifier; + + /// \brief The source range covering the nested name specifier. + SourceRange QualifierRange; + + /// \brief The member to which this member expression refers, which + /// can be a name or an overloaded operator. + DeclarationName MemberName; + + /// \brief The location of the member name. + SourceLocation MemberLoc; + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name. + ExplicitTemplateArgumentList *getExplicitTemplateArgs() { + assert(HasExplicitTemplateArgs); + return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name, if any. + const ExplicitTemplateArgumentList *getExplicitTemplateArgs() const { + return const_cast<UnresolvedMemberExpr*>(this)->getExplicitTemplateArgs(); + } + + UnresolvedMemberExpr(QualType T, bool Dependent, + bool HasUnresolvedUsing, + Expr *Base, bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName Member, + SourceLocation MemberLoc, + const TemplateArgumentListInfo *TemplateArgs); + +public: + static UnresolvedMemberExpr * + Create(ASTContext &C, bool Dependent, bool HasUnresolvedUsing, + Expr *Base, bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName Member, + SourceLocation MemberLoc, + const TemplateArgumentListInfo *TemplateArgs); + + /// Adds a declaration to the unresolved set. By assumption, all of + /// these happen at initialization time and properties like + /// 'Dependent' and 'HasUnresolvedUsing' take them into account. + void addDecl(NamedDecl *Decl) { + Results.addDecl(Decl); + } + + typedef UnresolvedSet::iterator decls_iterator; + decls_iterator decls_begin() const { return Results.begin(); } + decls_iterator decls_end() const { return Results.end(); } + + unsigned getNumDecls() const { return Results.size(); } + + /// \brief Retrieve the base object of this member expressions, + /// e.g., the \c x in \c x.m. + Expr *getBase() { return cast<Expr>(Base); } + void setBase(Expr *E) { Base = E; } + + /// \brief Determine whether this member expression used the '->' + /// operator; otherwise, it used the '.' operator. + bool isArrow() const { return IsArrow; } + void setArrow(bool A) { IsArrow = A; } + + /// \brief Retrieve the location of the '->' or '.' operator. + SourceLocation getOperatorLoc() const { return OperatorLoc; } + void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } + + /// \brief Retrieve the nested-name-specifier that qualifies the member + /// name. + NestedNameSpecifier *getQualifier() const { return Qualifier; } + + /// \brief Retrieve the source range covering the nested-name-specifier + /// that qualifies the member name. + SourceRange getQualifierRange() const { return QualifierRange; } + + /// \brief Retrieve the name of the member that this expression + /// refers to. + DeclarationName getMemberName() const { return MemberName; } + void setMemberName(DeclarationName N) { MemberName = N; } + + // \brief Retrieve the location of the name of the member that this + // expression refers to. + SourceLocation getMemberLoc() const { return MemberLoc; } + void setMemberLoc(SourceLocation L) { MemberLoc = L; } + + /// \brief Determines whether this member expression actually had a C++ + /// template argument list explicitly specified, e.g., x.f<int>. + bool hasExplicitTemplateArgs() const { + return HasExplicitTemplateArgs; + } + + /// \brief Copies the template arguments into the given structure. + void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { + getExplicitTemplateArgs()->copyInto(List); + } + + /// \brief Retrieve the location of the left angle bracket following + /// the member name ('<'). + SourceLocation getLAngleLoc() const { + return getExplicitTemplateArgs()->LAngleLoc; + } + + /// \brief Retrieve the template arguments provided as part of this + /// template-id. + const TemplateArgumentLoc *getTemplateArgs() const { + return getExplicitTemplateArgs()->getTemplateArgs(); + } + + /// \brief Retrieve the number of template arguments provided as + /// part of this template-id. + unsigned getNumTemplateArgs() const { + return getExplicitTemplateArgs()->NumTemplateArgs; + } + + /// \brief Retrieve the location of the right angle bracket + /// following the template arguments ('>'). + SourceLocation getRAngleLoc() const { + return getExplicitTemplateArgs()->RAngleLoc; + } + + virtual SourceRange getSourceRange() const { + SourceRange Range = Base->getSourceRange(); + if (hasExplicitTemplateArgs()) + Range.setEnd(getRAngleLoc()); + else + Range.setEnd(MemberLoc); + return Range; + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == UnresolvedMemberExprClass; } - static bool classof(const CXXUnresolvedMemberExpr *) { return true; } + static bool classof(const UnresolvedMemberExpr *) { return true; } // Iterators virtual child_iterator child_begin(); diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index 9b1c640..5d2973e 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -47,6 +47,59 @@ class ASTRecordLayout { // FieldCount - Number of fields. unsigned FieldCount; +public: + /// PrimaryBaseInfo - Contains info about a primary base. + struct PrimaryBaseInfo { + PrimaryBaseInfo() {} + + PrimaryBaseInfo(const CXXRecordDecl *Base, bool IsVirtual) + : Value(Base, IsVirtual) {} + + /// Value - Points to the primary base. The single-bit value + /// will be non-zero when the primary base is virtual. + llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> Value; + + /// getBase - Returns the primary base. + const CXXRecordDecl *getBase() const { return Value.getPointer(); } + + /// isVirtual - Returns whether the primary base is virtual or not. + bool isVirtual() const { return Value.getInt(); } + + friend bool operator==(const PrimaryBaseInfo &X, const PrimaryBaseInfo &Y) { + return X.Value == Y.Value; + } + }; + + /// primary_base_info_iterator - An iterator for iterating the primary base + /// class chain. + class primary_base_info_iterator { + /// Current - The current base class info. + PrimaryBaseInfo Current; + + public: + primary_base_info_iterator() {} + primary_base_info_iterator(PrimaryBaseInfo Info) : Current(Info) {} + + const PrimaryBaseInfo &operator*() const { return Current; } + + primary_base_info_iterator& operator++() { + const CXXRecordDecl *RD = Current.getBase(); + Current = RD->getASTContext().getASTRecordLayout(RD).getPrimaryBaseInfo(); + return *this; + } + + friend bool operator==(const primary_base_info_iterator &X, + const primary_base_info_iterator &Y) { + return X.Current == Y.Current; + } + friend bool operator!=(const primary_base_info_iterator &X, + const primary_base_info_iterator &Y) { + return !(X == Y); + } + }; + +private: + /// CXXRecordLayoutInfo - Contains C++ specific layout information. struct CXXRecordLayoutInfo { /// NonVirtualSize - The non-virtual size (in bits) of an object, which is /// the size of the object without virtual bases. @@ -56,11 +109,9 @@ class ASTRecordLayout { /// which is the alignment of the object without virtual bases. uint64_t NonVirtualAlign; - /// PrimaryBase - The primary base for our vtable. - const CXXRecordDecl *PrimaryBase; - /// PrimaryBase - Wether or not the primary base was a virtual base. - bool PrimaryBaseWasVirtual; - + /// PrimaryBase - The primary base info for this record. + PrimaryBaseInfo PrimaryBase; + /// BaseOffsets - Contains a map from base classes to their offset. /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :) llvm::DenseMap<const CXXRecordDecl *, uint64_t> BaseOffsets; @@ -68,6 +119,13 @@ class ASTRecordLayout { /// VBaseOffsets - Contains a map from vbase classes to their offset. /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :) llvm::DenseMap<const CXXRecordDecl *, uint64_t> VBaseOffsets; + + /// KeyFunction - The key function, according to the Itanium C++ ABI, + /// section 5.2.3: + /// + /// ...the first non-pure virtual function that is not inline at the point + /// of class definition. + const CXXMethodDecl *KeyFunction; }; /// CXXInfo - If the record layout is for a C++ record, this will have @@ -92,11 +150,12 @@ class ASTRecordLayout { ASTRecordLayout(uint64_t size, unsigned alignment, uint64_t datasize, const uint64_t *fieldoffsets, unsigned fieldcount, uint64_t nonvirtualsize, unsigned nonvirtualalign, - const CXXRecordDecl *PB, bool PBVirtual, + const PrimaryBaseInfo &PrimaryBase, const std::pair<const CXXRecordDecl *, uint64_t> *bases, unsigned numbases, const std::pair<const CXXRecordDecl *, uint64_t> *vbases, - unsigned numvbases) + unsigned numvbases, + const CXXMethodDecl *KeyFunction) : Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment), FieldCount(fieldcount), CXXInfo(new CXXRecordLayoutInfo) { if (FieldCount > 0) { @@ -105,14 +164,14 @@ class ASTRecordLayout { FieldOffsets[i] = fieldoffsets[i]; } - CXXInfo->PrimaryBase = PB; - CXXInfo->PrimaryBaseWasVirtual = PBVirtual; + CXXInfo->PrimaryBase = PrimaryBase; CXXInfo->NonVirtualSize = nonvirtualsize; CXXInfo->NonVirtualAlign = nonvirtualalign; for (unsigned i = 0; i != numbases; ++i) CXXInfo->BaseOffsets[bases[i].first] = bases[i].second; for (unsigned i = 0; i != numvbases; ++i) CXXInfo->VBaseOffsets[vbases[i].first] = vbases[i].second; + CXXInfo->KeyFunction = KeyFunction; } ~ASTRecordLayout() { @@ -162,17 +221,21 @@ public: return CXXInfo->NonVirtualAlign; } - /// getPrimaryBase - Get the primary base. - const CXXRecordDecl *getPrimaryBase() const { + /// getPrimaryBaseInfo - Get the primary base info. + const PrimaryBaseInfo &getPrimaryBaseInfo() const { assert(CXXInfo && "Record layout does not have C++ specific info!"); return CXXInfo->PrimaryBase; } - /// getPrimaryBaseWasVirtual - Indicates if the primary base was virtual. - bool getPrimaryBaseWasVirtual() const { - assert(CXXInfo && "Record layout does not have C++ specific info!"); - return CXXInfo->PrimaryBaseWasVirtual; + // FIXME: Migrate off of this function and use getPrimaryBaseInfo directly. + const CXXRecordDecl *getPrimaryBase() const { + return getPrimaryBaseInfo().getBase(); + } + + // FIXME: Migrate off of this function and use getPrimaryBaseInfo directly. + bool getPrimaryBaseWasVirtual() const { + return getPrimaryBaseInfo().isVirtual(); } /// getBaseClassOffset - Get the offset, in bits, for the given base class. @@ -190,6 +253,25 @@ public: return CXXInfo->VBaseOffsets[VBase]; } + + /// getKeyFunction - Get the key function. + const CXXMethodDecl *getKeyFunction() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + + return CXXInfo->KeyFunction; + } + + primary_base_info_iterator primary_base_begin() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + + return primary_base_info_iterator(getPrimaryBaseInfo()); + } + + primary_base_info_iterator primary_base_end() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + + return primary_base_info_iterator(); + } }; } // end namespace clang diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h index 8679323..01f4b29 100644 --- a/include/clang/AST/Redeclarable.h +++ b/include/clang/AST/Redeclarable.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_REDECLARABLE_H #include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/Casting.h" #include <iterator> namespace clang { @@ -92,6 +93,11 @@ public: } /// \brief Returns the most recent (re)declaration of this declaration. + decl_type *getMostRecentDeclaration() { + return getFirstDeclaration()->RedeclLink.getNext(); + } + + /// \brief Returns the most recent (re)declaration of this declaration. const decl_type *getMostRecentDeclaration() const { return getFirstDeclaration()->RedeclLink.getNext(); } @@ -102,8 +108,11 @@ public: decl_type *First; if (PrevDecl) { - // Point to previous. - RedeclLink = PreviousDeclLink(PrevDecl); + // Point to previous. Make sure that this is actually the most recent + // redeclaration, or we can build invalid chains. If the most recent + // redeclaration is invalid, it won't be PrevDecl, but we want it anyway. + RedeclLink = PreviousDeclLink(llvm::cast<decl_type>( + PrevDecl->getMostRecentDeclaration())); First = PrevDecl->getFirstDeclaration(); assert(First->RedeclLink.NextIsLatest() && "Expected first"); } else { diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 411f215e..d6f6a83 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -171,6 +171,14 @@ public: } virtual ~Stmt() {} +#ifndef NDEBUG + /// \brief True if this statement's refcount is in a valid state. + /// Should be used only in assertions. + bool isRetained() const { + return (RefCount >= 1); + } +#endif + /// \brief Destroy the current statement and its children. void Destroy(ASTContext &Ctx) { assert(RefCount >= 1); @@ -203,7 +211,7 @@ public: // global temp stats (until we have a per-module visitor) static void addStmtClass(const StmtClass s); - static bool CollectingStats(bool enable=false); + static bool CollectingStats(bool Enable = false); static void PrintStats(); /// dump - This does a local dump of the specified AST fragment. It dumps the @@ -604,22 +612,36 @@ public: class IfStmt : public Stmt { enum { COND, THEN, ELSE, END_EXPR }; Stmt* SubExprs[END_EXPR]; + + /// \brief If non-NULL, the declaration in the "if" statement. + VarDecl *Var; + SourceLocation IfLoc; SourceLocation ElseLoc; + public: - IfStmt(SourceLocation IL, Expr *cond, Stmt *then, + IfStmt(SourceLocation IL, VarDecl *Var, Expr *cond, Stmt *then, SourceLocation EL = SourceLocation(), Stmt *elsev = 0) - : Stmt(IfStmtClass) { + : Stmt(IfStmtClass), Var(Var), IfLoc(IL), ElseLoc(EL) { SubExprs[COND] = reinterpret_cast<Stmt*>(cond); SubExprs[THEN] = then; SubExprs[ELSE] = elsev; - IfLoc = IL; - ElseLoc = EL; } /// \brief Build an empty if/then/else statement explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { } + /// \brief Retrieve the variable declared in this "if" statement, if any. + /// + /// In the following example, "x" is the condition variable. + /// \code + /// if (int x = foo()) { + /// printf("x is %d", x); + /// } + /// \endcode + VarDecl *getConditionVariable() const { return Var; } + void setConditionVariable(VarDecl *V) { Var = V; } + const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); } const Stmt *getThen() const { return SubExprs[THEN]; } @@ -658,6 +680,7 @@ public: class SwitchStmt : public Stmt { enum { COND, BODY, END_EXPR }; Stmt* SubExprs[END_EXPR]; + VarDecl *Var; // This points to a linked list of case and default statements. SwitchCase *FirstCase; SourceLocation SwitchLoc; @@ -666,14 +689,28 @@ protected: virtual void DoDestroy(ASTContext &Ctx); public: - SwitchStmt(Expr *cond) : Stmt(SwitchStmtClass), FirstCase(0) { - SubExprs[COND] = reinterpret_cast<Stmt*>(cond); - SubExprs[BODY] = NULL; - } + SwitchStmt(VarDecl *Var, Expr *cond) + : Stmt(SwitchStmtClass), Var(Var), FirstCase(0) + { + SubExprs[COND] = reinterpret_cast<Stmt*>(cond); + SubExprs[BODY] = NULL; + } /// \brief Build a empty switch statement. explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) { } + /// \brief Retrieve the variable declared in this "switch" statement, if any. + /// + /// In the following example, "x" is the condition variable. + /// \code + /// switch (int x = foo()) { + /// case 0: break; + /// // ... + /// } + /// \endcode + VarDecl *getConditionVariable() const { return Var; } + void setConditionVariable(VarDecl *V) { Var = V; } + const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} const Stmt *getBody() const { return SubExprs[BODY]; } const SwitchCase *getSwitchCaseList() const { return FirstCase; } @@ -721,10 +758,13 @@ public: /// class WhileStmt : public Stmt { enum { COND, BODY, END_EXPR }; + VarDecl *Var; Stmt* SubExprs[END_EXPR]; SourceLocation WhileLoc; public: - WhileStmt(Expr *cond, Stmt *body, SourceLocation WL) : Stmt(WhileStmtClass) { + WhileStmt(VarDecl *Var, Expr *cond, Stmt *body, SourceLocation WL) + : Stmt(WhileStmtClass), Var(Var) + { SubExprs[COND] = reinterpret_cast<Stmt*>(cond); SubExprs[BODY] = body; WhileLoc = WL; @@ -733,6 +773,17 @@ public: /// \brief Build an empty while statement. explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) { } + /// \brief Retrieve the variable declared in this "while" statement, if any. + /// + /// In the following example, "x" is the condition variable. + /// \code + /// while (int x = random()) { + /// // ... + /// } + /// \endcode + VarDecl *getConditionVariable() const { return Var; } + void setConditionVariable(VarDecl *V) { Var = V; } + Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); } @@ -812,26 +863,38 @@ public: class ForStmt : public Stmt { enum { INIT, COND, INC, BODY, END_EXPR }; Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt. + VarDecl *CondVar; SourceLocation ForLoc; SourceLocation LParenLoc, RParenLoc; public: - ForStmt(Stmt *Init, Expr *Cond, Expr *Inc, Stmt *Body, SourceLocation FL, - SourceLocation LP, SourceLocation RP) - : Stmt(ForStmtClass) { + ForStmt(Stmt *Init, Expr *Cond, VarDecl *CondVar, Expr *Inc, Stmt *Body, + SourceLocation FL, SourceLocation LP, SourceLocation RP) + : Stmt(ForStmtClass), CondVar(CondVar), ForLoc(FL), LParenLoc(LP), + RParenLoc(RP) + { SubExprs[INIT] = Init; SubExprs[COND] = reinterpret_cast<Stmt*>(Cond); SubExprs[INC] = reinterpret_cast<Stmt*>(Inc); SubExprs[BODY] = Body; - ForLoc = FL; - LParenLoc = LP; - RParenLoc = RP; } /// \brief Build an empty for statement. explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) { } Stmt *getInit() { return SubExprs[INIT]; } + + /// \brief Retrieve the variable declared in this "for" statement, if any. + /// + /// In the following example, "y" is the condition variable. + /// \code + /// for (int x = random(); int y = mangle(x); ++x) { + /// // ... + /// } + /// \endcode + VarDecl *getConditionVariable() const { return CondVar; } + void setConditionVariable(VarDecl *V) { CondVar = V; } + Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } Expr *getInc() { return reinterpret_cast<Expr*>(SubExprs[INC]); } Stmt *getBody() { return SubExprs[BODY]; } diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h index 28fe348..64eea24 100644 --- a/include/clang/AST/StmtCXX.h +++ b/include/clang/AST/StmtCXX.h @@ -42,9 +42,9 @@ public: } SourceLocation getCatchLoc() const { return CatchLoc; } - VarDecl *getExceptionDecl() { return ExceptionDecl; } - QualType getCaughtType(); - Stmt *getHandlerBlock() { return HandlerBlock; } + VarDecl *getExceptionDecl() const { return ExceptionDecl; } + QualType getCaughtType() const; + Stmt *getHandlerBlock() const { return HandlerBlock; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXCatchStmtClass; diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def index 034029a..7102336 100644 --- a/include/clang/AST/StmtNodes.def +++ b/include/clang/AST/StmtNodes.def @@ -121,20 +121,19 @@ EXPR(CXXThisExpr , Expr) EXPR(CXXThrowExpr , Expr) EXPR(CXXDefaultArgExpr , Expr) EXPR(CXXZeroInitValueExpr , Expr) -EXPR(CXXConditionDeclExpr , DeclRefExpr) EXPR(CXXNewExpr , Expr) EXPR(CXXDeleteExpr , Expr) EXPR(CXXPseudoDestructorExpr, Expr) -EXPR(UnresolvedFunctionNameExpr , Expr) +EXPR(UnresolvedLookupExpr , Expr) EXPR(UnaryTypeTraitExpr , Expr) -EXPR(UnresolvedDeclRefExpr , Expr) -EXPR(TemplateIdRefExpr , Expr) +EXPR(DependentScopeDeclRefExpr , Expr) EXPR(CXXConstructExpr , Expr) EXPR(CXXBindTemporaryExpr , Expr) EXPR(CXXExprWithTemporaries , Expr) EXPR(CXXTemporaryObjectExpr , CXXConstructExpr) EXPR(CXXUnresolvedConstructExpr, Expr) -EXPR(CXXUnresolvedMemberExpr, Expr) +EXPR(CXXDependentScopeMemberExpr, Expr) +EXPR(UnresolvedMemberExpr , Expr) // Obj-C Expressions. EXPR(ObjCStringLiteral , Expr) diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 6db0958..b46b3dc 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_AST_TEMPLATEBASE_H #include "llvm/ADT/APSInt.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/ErrorHandling.h" #include "clang/AST/Type.h" #include "clang/AST/TemplateName.h" @@ -437,6 +438,41 @@ public: } }; +/// A convenient class for passing around template argument +/// information. Designed to be passed by reference. +class TemplateArgumentListInfo { + llvm::SmallVector<TemplateArgumentLoc, 8> Arguments; + SourceLocation LAngleLoc; + SourceLocation RAngleLoc; + +public: + TemplateArgumentListInfo() {} + + TemplateArgumentListInfo(SourceLocation LAngleLoc, + SourceLocation RAngleLoc) + : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {} + + SourceLocation getLAngleLoc() const { return LAngleLoc; } + SourceLocation getRAngleLoc() const { return RAngleLoc; } + + void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; } + void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; } + + unsigned size() const { return Arguments.size(); } + + const TemplateArgumentLoc *getArgumentArray() const { + return Arguments.data(); + } + + const TemplateArgumentLoc &operator[](unsigned I) const { + return Arguments[I]; + } + + void addArgument(const TemplateArgumentLoc &Loc) { + Arguments.push_back(Loc); + } +}; + } #endif diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index c28bafe..349487f 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -82,6 +82,7 @@ namespace clang { class StmtIteratorBase; class TemplateArgument; class TemplateArgumentLoc; + class TemplateArgumentListInfo; class QualifiedNameType; struct PrintingPolicy; @@ -859,6 +860,7 @@ public: bool isObjCQualifiedClassType() const; // Class<foo> bool isObjCIdType() const; // id bool isObjCClassType() const; // Class + bool isObjCSelType() const; // Class bool isObjCBuiltinType() const; // 'id' or 'Class' bool isTemplateTypeParmType() const; // C++ template type parameter bool isNullPtrType() const; // C++0x nullptr_t @@ -1000,7 +1002,8 @@ public: UndeducedAuto, // In C++0x, this represents the type of an auto variable // that has not been deduced yet. ObjCId, // This represents the ObjC 'id' type. - ObjCClass // This represents the ObjC 'Class' type. + ObjCClass, // This represents the ObjC 'Class' type. + ObjCSel // This represents the ObjC 'SEL' type. }; private: Kind TypeKind; @@ -1457,21 +1460,27 @@ public: /// DependentSizedArrayType - This type represents an array type in /// C++ whose size is a value-dependent expression. For example: -/// @code +/// +/// \code /// template<typename T, int Size> /// class array { /// T data[Size]; /// }; -/// @endcode +/// \endcode +/// /// For these types, we won't actually know what the array bound is /// until template instantiation occurs, at which point this will /// become either a ConstantArrayType or a VariableArrayType. class DependentSizedArrayType : public ArrayType { ASTContext &Context; - /// SizeExpr - An assignment expression that will instantiate to the + /// \brief An assignment expression that will instantiate to the /// size of the array. + /// + /// The expression itself might be NULL, in which case the array + /// type will have its size deduced from an initializer. Stmt *SizeExpr; + /// Brackets - The left and right array brackets. SourceRange Brackets; @@ -2272,6 +2281,8 @@ public: static bool anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned NumArgs); + static bool anyDependentTemplateArguments(const TemplateArgumentListInfo &); + /// \brief Print a template argument list, including the '<' and '>' /// enclosing the template arguments. static std::string PrintTemplateArgumentList(const TemplateArgument *Args, @@ -2282,6 +2293,9 @@ public: unsigned NumArgs, const PrintingPolicy &Policy); + static std::string PrintTemplateArgumentList(const TemplateArgumentListInfo &, + const PrintingPolicy &Policy); + typedef const TemplateArgument * iterator; iterator begin() const { return getArgs(); } @@ -2534,6 +2548,7 @@ public: return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) && !Protocols.size(); } + /// isObjCQualifiedIdType - true for "id <p>". bool isObjCQualifiedIdType() const { return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) && @@ -2881,8 +2896,13 @@ inline bool Type::isObjCClassType() const { return OPT->isObjCClassType(); return false; } +inline bool Type::isObjCSelType() const { + if (const PointerType *OPT = getAs<PointerType>()) + return OPT->getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCSel); + return false; +} inline bool Type::isObjCBuiltinType() const { - return isObjCIdType() || isObjCClassType(); + return isObjCIdType() || isObjCClassType() || isObjCSelType(); } inline bool Type::isTemplateTypeParmType() const { return isa<TemplateTypeParmType>(CanonicalType); diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h index 8674943..0077a85 100644 --- a/include/clang/Analysis/Analyses/LiveVariables.h +++ b/include/clang/Analysis/Analyses/LiveVariables.h @@ -23,6 +23,7 @@ namespace clang { class Stmt; class DeclRefExpr; class SourceManager; +class AnalysisContext; struct LiveVariables_ValueTypes { @@ -39,8 +40,9 @@ struct LiveVariables_ValueTypes { struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy { ObserverTy* Observer; ValTy AlwaysLive; + AnalysisContext *AC; - AnalysisDataTy() : Observer(NULL) {} + AnalysisDataTy() : Observer(NULL), AC(NULL) {} }; //===-----------------------------------------------------===// @@ -66,7 +68,7 @@ class LiveVariables : public DataflowValues<LiveVariables_ValueTypes, public: typedef LiveVariables_ValueTypes::ObserverTy ObserverTy; - LiveVariables(ASTContext& Ctx, CFG& cfg); + LiveVariables(AnalysisContext &AC); /// IsLive - Return true if a variable is live at beginning of a /// specified block. diff --git a/include/clang/Analysis/PathDiagnostic.h b/include/clang/Analysis/PathDiagnostic.h index efc6677..cad702c 100644 --- a/include/clang/Analysis/PathDiagnostic.h +++ b/include/clang/Analysis/PathDiagnostic.h @@ -14,31 +14,24 @@ #ifndef LLVM_CLANG_PATH_DIAGNOSTIC_H #define LLVM_CLANG_PATH_DIAGNOSTIC_H -#include "clang/Basic/SourceManager.h" #include "clang/Basic/Diagnostic.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/FoldingSet.h" - -#include <vector> #include <deque> +#include <iterator> #include <string> -#include <algorithm> +#include <vector> namespace clang { - -class Stmt; + class Decl; -class Preprocessor; - +class SourceManager; +class Stmt; + //===----------------------------------------------------------------------===// // High-level interface for handlers of path-sensitive diagnostics. //===----------------------------------------------------------------------===// class PathDiagnostic; - -class Stmt; -class Decl; -class Preprocessor; class PathDiagnosticClient : public DiagnosticClient { public: diff --git a/include/clang/Analysis/PathSensitive/AnalysisContext.h b/include/clang/Analysis/PathSensitive/AnalysisContext.h index 9b58f74..8b1a329 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisContext.h +++ b/include/clang/Analysis/PathSensitive/AnalysisContext.h @@ -19,6 +19,7 @@ #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/Support/Allocator.h" namespace clang { @@ -38,17 +39,26 @@ class AnalysisContext { CFG *cfg; LiveVariables *liveness; ParentMap *PM; - + llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars; + llvm::BumpPtrAllocator A; public: - AnalysisContext(const Decl *d) : D(d), cfg(0), liveness(0), PM(0) {} + AnalysisContext(const Decl *d) : D(d), cfg(0), liveness(0), PM(0), + ReferencedBlockVars(0) {} + ~AnalysisContext(); + ASTContext &getASTContext() { return D->getASTContext(); } const Decl *getDecl() { return D; } Stmt *getBody(); CFG *getCFG(); ParentMap &getParentMap(); LiveVariables *getLiveVariables(); + typedef const VarDecl * const * referenced_decls_iterator; + + std::pair<referenced_decls_iterator, referenced_decls_iterator> + getReferencedBlockVars(const BlockDecl *BD); + /// Return the ImplicitParamDecl* associated with 'self' if this /// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise. const ImplicitParamDecl *getSelfDecl() const; diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Analysis/PathSensitive/BugReporter.h index f429735..58c8018 100644 --- a/include/clang/Analysis/PathSensitive/BugReporter.h +++ b/include/clang/Analysis/PathSensitive/BugReporter.h @@ -309,32 +309,33 @@ public: void EmitReport(BugReport *R); - void EmitBasicReport(const char* BugName, const char* BugStr, + void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugStr, SourceLocation Loc, SourceRange* RangeBeg, unsigned NumRanges); - void EmitBasicReport(const char* BugName, const char* BugCategory, - const char* BugStr, SourceLocation Loc, + void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugCategory, + llvm::StringRef BugStr, SourceLocation Loc, SourceRange* RangeBeg, unsigned NumRanges); - void EmitBasicReport(const char* BugName, const char* BugStr, + void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugStr, SourceLocation Loc) { EmitBasicReport(BugName, BugStr, Loc, 0, 0); } - void EmitBasicReport(const char* BugName, const char* BugCategory, - const char* BugStr, SourceLocation Loc) { + void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugCategory, + llvm::StringRef BugStr, SourceLocation Loc) { EmitBasicReport(BugName, BugCategory, BugStr, Loc, 0, 0); } - void EmitBasicReport(const char* BugName, const char* BugStr, + void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef BugStr, SourceLocation Loc, SourceRange R) { EmitBasicReport(BugName, BugStr, Loc, &R, 1); } - void EmitBasicReport(const char* BugName, const char* Category, - const char* BugStr, SourceLocation Loc, SourceRange R) { + void EmitBasicReport(llvm::StringRef BugName, llvm::StringRef Category, + llvm::StringRef BugStr, SourceLocation Loc, + SourceRange R) { EmitBasicReport(BugName, Category, BugStr, Loc, &R, 1); } @@ -432,7 +433,7 @@ class DiagBugReport : public RangedBugReport { std::list<std::string> Strs; FullSourceLoc L; public: - DiagBugReport(BugType& D, const char* desc, FullSourceLoc l) : + DiagBugReport(BugType& D, llvm::StringRef desc, FullSourceLoc l) : RangedBugReport(D, desc, 0), L(l) {} virtual ~DiagBugReport() {} diff --git a/include/clang/Analysis/PathSensitive/BugType.h b/include/clang/Analysis/PathSensitive/BugType.h index 8303dee..4f1523a 100644 --- a/include/clang/Analysis/PathSensitive/BugType.h +++ b/include/clang/Analysis/PathSensitive/BugType.h @@ -34,13 +34,13 @@ private: friend class BugReporter; bool SuppressonSink; public: - BugType(const char *name, const char* cat) + BugType(llvm::StringRef name, llvm::StringRef cat) : Name(name), Category(cat), SuppressonSink(false) {} virtual ~BugType(); // FIXME: Should these be made strings as well? - const std::string& getName() const { return Name; } - const std::string& getCategory() const { return Category; } + llvm::StringRef getName() const { return Name; } + llvm::StringRef getCategory() const { return Category; } /// isSuppressOnSink - Returns true if bug reports associated with this bug /// type should be suppressed if the end node of the report is post-dominated @@ -60,33 +60,15 @@ public: }; class BuiltinBug : public BugType { - GRExprEngine *Eng; -protected: const std::string desc; public: BuiltinBug(const char *name, const char *description) - : BugType(name, "Logic error"), Eng(0), desc(description) {} + : BugType(name, "Logic error"), desc(description) {} BuiltinBug(const char *name) - : BugType(name, "Logic error"), Eng(0), desc(name) {} + : BugType(name, "Logic error"), desc(name) {} - BuiltinBug(GRExprEngine *eng, const char* n, const char* d) - : BugType(n, "Logic error"), Eng(eng), desc(d) {} - - BuiltinBug(GRExprEngine *eng, const char* n) - : BugType(n, "Logic error"), Eng(eng), desc(n) {} - - const std::string &getDescription() const { return desc; } - - virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {} - - void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, *Eng); } - - virtual void registerInitialVisitors(BugReporterContext& BRC, - const ExplodedNode* N, - BuiltinBugReport *R) {} - - template <typename ITER> void Emit(BugReporter& BR, ITER I, ITER E); + llvm::StringRef getDescription() const { return desc; } }; } // end clang namespace diff --git a/include/clang/Analysis/PathSensitive/Checker.h b/include/clang/Analysis/PathSensitive/Checker.h index b7ed20f..91a4b6d 100644 --- a/include/clang/Analysis/PathSensitive/Checker.h +++ b/include/clang/Analysis/PathSensitive/Checker.h @@ -40,24 +40,35 @@ class CheckerContext { SaveAndRestore<ProgramPoint::Kind> OldPointKind; SaveOr OldHasGen; const GRState *state; - + const Stmt *statement; + const unsigned size; + bool DoneEvaluating; // FIXME: This is not a permanent API change. public: CheckerContext(ExplodedNodeSet &dst, GRStmtNodeBuilder &builder, GRExprEngine &eng, ExplodedNode *pred, const void *tag, ProgramPoint::Kind K, - const GRState *st = 0) + const Stmt *stmt = 0, const GRState *st = 0) : Dst(dst), B(builder), Eng(eng), Pred(pred), OldSink(B.BuildSinks), OldTag(B.Tag, tag), OldPointKind(B.PointKind, K), OldHasGen(B.HasGeneratedNode), - state(st) {} + state(st), statement(stmt), size(Dst.size()), + DoneEvaluating(false) {} - ~CheckerContext() { - if (!B.BuildSinks && !B.HasGeneratedNode) - Dst.Add(Pred); + ~CheckerContext(); + + // FIXME: This were added to support CallAndMessageChecker to indicating + // to GRExprEngine to "stop evaluating" a message expression under certain + // cases. This is *not* meant to be a permanent API change, and was added + // to aid in the transition of removing logic for checks from GRExprEngine. + void setDoneEvaluating() { + DoneEvaluating = true; } - + bool isDoneEvaluating() const { + return DoneEvaluating; + } + ConstraintManager &getConstraintManager() { return Eng.getConstraintManager(); } @@ -83,27 +94,70 @@ public: return getBugReporter().getSourceManager(); } - ExplodedNode *GenerateNode(const Stmt *S, bool markAsSink = false) { - return GenerateNode(S, getState(), markAsSink); + ValueManager &getValueManager() { + return Eng.getValueManager(); } - ExplodedNode *GenerateNode(const Stmt* S, const GRState *state, - bool markAsSink = false) { - ExplodedNode *node = B.generateNode(S, state, Pred); + ExplodedNode *GenerateNode(bool autoTransition = true) { + assert(statement && "Only transitions with statements currently supported"); + ExplodedNode *N = GenerateNodeImpl(statement, getState(), false); + if (N && autoTransition) + Dst.Add(N); + return N; + } + + ExplodedNode *GenerateNode(const Stmt *stmt, const GRState *state, + bool autoTransition = true) { + assert(state); + ExplodedNode *N = GenerateNodeImpl(stmt, state, false); + if (N && autoTransition) + addTransition(N); + return N; + } - if (markAsSink && node) - node->markAsSink(); + ExplodedNode *GenerateNode(const GRState *state, bool autoTransition = true) { + assert(statement && "Only transitions with statements currently supported"); + ExplodedNode *N = GenerateNodeImpl(statement, state, false); + if (N && autoTransition) + addTransition(N); + return N; + } - return node; + ExplodedNode *GenerateSink(const Stmt *stmt, const GRState *state = 0) { + return GenerateNodeImpl(stmt, state ? state : getState(), true); + } + + ExplodedNode *GenerateSink(const GRState *state = 0) { + assert(statement && "Only transitions with statements currently supported"); + return GenerateNodeImpl(statement, state ? state : getState(), true); } void addTransition(ExplodedNode *node) { Dst.Add(node); } + + void addTransition(const GRState *state) { + assert(state); + if (state != getState() || + (state && state != B.GetState(Pred))) + GenerateNode(state, true); + else + Dst.Add(Pred); + } void EmitReport(BugReport *R) { Eng.getBugReporter().EmitReport(R); } + +private: + ExplodedNode *GenerateNodeImpl(const Stmt* stmt, const GRState *state, + bool markAsSink) { + ExplodedNode *node = B.generateNode(stmt, state, Pred); + if (markAsSink && node) + node->markAsSink(); + return node; + } + }; class Checker { @@ -111,18 +165,19 @@ private: friend class GRExprEngine; // FIXME: Remove the 'tag' option. - void GR_Visit(ExplodedNodeSet &Dst, + bool GR_Visit(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder, GRExprEngine &Eng, const Stmt *S, ExplodedNode *Pred, void *tag, bool isPrevisit) { CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit ? ProgramPoint::PreStmtKind : - ProgramPoint::PostStmtKind); + ProgramPoint::PostStmtKind, S); if (isPrevisit) _PreVisit(C, S); else _PostVisit(C, S); + return C.isDoneEvaluating(); } // FIXME: Remove the 'tag' option. @@ -134,7 +189,7 @@ private: bool isPrevisit) { CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit ? ProgramPoint::PreStmtKind : - ProgramPoint::PostStmtKind); + ProgramPoint::PostStmtKind, StoreE); assert(isPrevisit && "Only previsit supported for now."); PreVisitBind(C, AssignE, StoreE, location, val); } @@ -149,7 +204,7 @@ private: void *tag, bool isLoad) { CheckerContext C(Dst, Builder, Eng, Pred, tag, isLoad ? ProgramPoint::PreLoadKind : - ProgramPoint::PreStoreKind, state); + ProgramPoint::PreStoreKind, S, state); VisitLocation(C, S, location); } @@ -157,12 +212,12 @@ private: GRExprEngine &Eng, const Stmt *S, ExplodedNode *Pred, SymbolReaper &SymReaper, void *tag) { CheckerContext C(Dst, Builder, Eng, Pred, tag, - ProgramPoint::PostPurgeDeadSymbolsKind, Pred->getState()); + ProgramPoint::PostPurgeDeadSymbolsKind, S); EvalDeadSymbols(C, S, SymReaper); } public: - virtual ~Checker() {} + virtual ~Checker(); virtual void _PreVisit(CheckerContext &C, const Stmt *S) {} virtual void _PostVisit(CheckerContext &C, const Stmt *S) {} virtual void VisitLocation(CheckerContext &C, const Stmt *S, SVal location) {} @@ -172,6 +227,10 @@ public: SymbolReaper &SymReaper) {} virtual void EvalEndPath(GREndPathNodeBuilder &B, void *tag, GRExprEngine &Eng) {} + + virtual void VisitBranchCondition(GRBranchNodeBuilder &Builder, + GRExprEngine &Eng, + Stmt *Condition, void *tag) {} }; } // end clang namespace diff --git a/include/clang/Analysis/PathSensitive/CheckerVisitor.def b/include/clang/Analysis/PathSensitive/CheckerVisitor.def index 090a5d3..4144d1a 100644 --- a/include/clang/Analysis/PathSensitive/CheckerVisitor.def +++ b/include/clang/Analysis/PathSensitive/CheckerVisitor.def @@ -11,7 +11,14 @@ // //===---------------------------------------------------------------------===// -#ifdef PREVISIT +#ifndef PREVISIT +#define PREVISIT(NODE) +#endif + +#ifndef POSTVISIT +#define POSTVISIT(NODE) +#endif + PREVISIT(ArraySubscriptExpr) PREVISIT(BinaryOperator) PREVISIT(CallExpr) @@ -19,11 +26,10 @@ PREVISIT(CastExpr) PREVISIT(DeclStmt) PREVISIT(ObjCMessageExpr) PREVISIT(ReturnStmt) -#undef PREVISIT -#endif -#ifdef POSTVISIT POSTVISIT(CallExpr) -#undef POSTVISIT -#endif +POSTVISIT(BlockExpr) +POSTVISIT(BinaryOperator) +#undef PREVISIT +#undef POSTVISIT diff --git a/include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h b/include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h deleted file mode 100644 index 13437eb..0000000 --- a/include/clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h +++ /dev/null @@ -1,33 +0,0 @@ -//===--- UndefinedAssignmentChecker.h ---------------------------*- C++ -*--==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This defines UndefinedAssginmentChecker, a builtin check in GRExprEngine that -// checks for assigning undefined values. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_UNDEFASSIGNMENTCHECKER -#define LLVM_CLANG_UNDEFASSIGNMENTCHECKER - -#include "clang/Analysis/PathSensitive/CheckerVisitor.h" - -namespace clang { -class UndefinedAssignmentChecker - : public CheckerVisitor<UndefinedAssignmentChecker> { - BugType *BT; -public: - UndefinedAssignmentChecker() : BT(0) {} - static void *getTag(); - virtual void PreVisitBind(CheckerContext &C, const Stmt *AssignE, - const Stmt *StoreE, SVal location, - SVal val); -}; -} -#endif - diff --git a/include/clang/Analysis/PathSensitive/ExplodedGraph.h b/include/clang/Analysis/PathSensitive/ExplodedGraph.h index a7bbdf9..76cab1d 100644 --- a/include/clang/Analysis/PathSensitive/ExplodedGraph.h +++ b/include/clang/Analysis/PathSensitive/ExplodedGraph.h @@ -352,10 +352,16 @@ public: typedef ImplTy::iterator iterator; typedef ImplTy::const_iterator const_iterator; - inline unsigned size() const { return Impl.size(); } - inline bool empty() const { return Impl.empty(); } - - inline void clear() { Impl.clear(); } + unsigned size() const { return Impl.size(); } + bool empty() const { return Impl.empty(); } + + void clear() { Impl.clear(); } + void insert(const ExplodedNodeSet &S) { + if (empty()) + Impl = S.Impl; + else + Impl.insert(S.begin(), S.end()); + } inline iterator begin() { return Impl.begin(); } inline iterator end() { return Impl.end(); } diff --git a/include/clang/Analysis/PathSensitive/GRCoreEngine.h b/include/clang/Analysis/PathSensitive/GRCoreEngine.h index 02e0b027..b78cc6a 100644 --- a/include/clang/Analysis/PathSensitive/GRCoreEngine.h +++ b/include/clang/Analysis/PathSensitive/GRCoreEngine.h @@ -215,7 +215,7 @@ public: void setAuditor(GRAuditor* A) { Auditor = A; } const GRState* GetState(ExplodedNode* Pred) const { - if ((ExplodedNode*) Pred == getBasePredecessor()) + if (Pred == getBasePredecessor()) return CleanedState; else return Pred->getState(); @@ -405,6 +405,8 @@ class GREndPathNodeBuilder { GRCoreEngine& Eng; CFGBlock& B; ExplodedNode* Pred; + +public: bool HasGeneratedNode; public: diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index 1b6d0bd..a7302c0 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -88,55 +88,6 @@ class GRExprEngine : public GRSubEngine { GRBugReporter BR; public: - typedef llvm::SmallPtrSet<ExplodedNode*,2> ErrorNodes; - typedef llvm::DenseMap<ExplodedNode*, Expr*> UndefArgsTy; - - /// NilReceiverStructRetExplicit - Nodes in the ExplodedGraph that resulted - /// from [x ...] with 'x' definitely being nil and the result was a 'struct' - // (an undefined value). - ErrorNodes NilReceiverStructRetExplicit; - - /// NilReceiverStructRetImplicit - Nodes in the ExplodedGraph that resulted - /// from [x ...] with 'x' possibly being nil and the result was a 'struct' - // (an undefined value). - ErrorNodes NilReceiverStructRetImplicit; - - /// NilReceiverLargerThanVoidPtrRetExplicit - Nodes in the ExplodedGraph that - /// resulted from [x ...] with 'x' definitely being nil and the result's size - // was larger than sizeof(void *) (an undefined value). - ErrorNodes NilReceiverLargerThanVoidPtrRetExplicit; - - /// NilReceiverLargerThanVoidPtrRetImplicit - Nodes in the ExplodedGraph that - /// resulted from [x ...] with 'x' possibly being nil and the result's size - // was larger than sizeof(void *) (an undefined value). - ErrorNodes NilReceiverLargerThanVoidPtrRetImplicit; - - /// UndefBranches - Nodes in the ExplodedGraph that result from - /// taking a branch based on an undefined value. - ErrorNodes UndefBranches; - - /// UndefStores - Sinks in the ExplodedGraph that result from - /// making a store to an undefined lvalue. - ErrorNodes UndefStores; - - /// NoReturnCalls - Sinks in the ExplodedGraph that result from - // calling a function with the attribute "noreturn". - ErrorNodes NoReturnCalls; - - /// UndefResults - Nodes in the ExplodedGraph where the operands are defined - /// by the result is not. Excludes divide-by-zero errors. - ErrorNodes UndefResults; - - /// UndefReceiver - Nodes in the ExplodedGraph resulting from message - /// ObjC message expressions where the receiver is undefined (uninitialized). - ErrorNodes UndefReceivers; - - /// MsgExprUndefArgs - Nodes in the ExplodedGraph resulting from - /// message expressions where a pass-by-value argument has an undefined - /// value. - UndefArgsTy MsgExprUndefArgs; - -public: GRExprEngine(AnalysisManager &mgr); ~GRExprEngine(); @@ -178,8 +129,6 @@ public: ExplodedGraph& getGraph() { return G; } const ExplodedGraph& getGraph() const { return G; } - void RegisterInternalChecks(); - template <typename CHECKER> void registerCheck(CHECKER *check) { unsigned entry = Checkers.size(); @@ -195,58 +144,6 @@ public: return static_cast<CHECKER*>(lookupChecker(CHECKER::getTag())); } - bool isNoReturnCall(const ExplodedNode* N) const { - return N->isSink() && NoReturnCalls.count(const_cast<ExplodedNode*>(N)) != 0; - } - - typedef ErrorNodes::iterator undef_branch_iterator; - undef_branch_iterator undef_branches_begin() { return UndefBranches.begin(); } - undef_branch_iterator undef_branches_end() { return UndefBranches.end(); } - - typedef ErrorNodes::iterator nil_receiver_struct_ret_iterator; - - nil_receiver_struct_ret_iterator nil_receiver_struct_ret_begin() { - return NilReceiverStructRetExplicit.begin(); - } - - nil_receiver_struct_ret_iterator nil_receiver_struct_ret_end() { - return NilReceiverStructRetExplicit.end(); - } - - typedef ErrorNodes::iterator nil_receiver_larger_than_voidptr_ret_iterator; - - nil_receiver_larger_than_voidptr_ret_iterator - nil_receiver_larger_than_voidptr_ret_begin() { - return NilReceiverLargerThanVoidPtrRetExplicit.begin(); - } - - nil_receiver_larger_than_voidptr_ret_iterator - nil_receiver_larger_than_voidptr_ret_end() { - return NilReceiverLargerThanVoidPtrRetExplicit.end(); - } - - typedef ErrorNodes::iterator undef_result_iterator; - undef_result_iterator undef_results_begin() { return UndefResults.begin(); } - undef_result_iterator undef_results_end() { return UndefResults.end(); } - - typedef UndefArgsTy::iterator undef_arg_iterator; - undef_arg_iterator msg_expr_undef_arg_begin() { - return MsgExprUndefArgs.begin(); - } - undef_arg_iterator msg_expr_undef_arg_end() { - return MsgExprUndefArgs.end(); - } - - typedef ErrorNodes::iterator undef_receivers_iterator; - - undef_receivers_iterator undef_receivers_begin() { - return UndefReceivers.begin(); - } - - undef_receivers_iterator undef_receivers_end() { - return UndefReceivers.end(); - } - void AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C); void AddCheck(GRSimpleAPICheck* A); @@ -312,7 +209,7 @@ public: protected: /// CheckerVisit - Dispatcher for performing checker-specific logic /// at specific statements. - void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, + bool CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, bool isPrevisit); void CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE, @@ -345,6 +242,9 @@ protected: AsmStmt::inputs_iterator I, AsmStmt::inputs_iterator E, ExplodedNode* Pred, ExplodedNodeSet& Dst); + + /// VisitBlockExpr - Transfer function logic for BlockExprs. + void VisitBlockExpr(BlockExpr *BE, ExplodedNode *Pred, ExplodedNodeSet &Dst); /// VisitBinaryOperator - Transfer function logic for binary operators. void VisitBinaryOperator(BinaryOperator* B, ExplodedNode* Pred, @@ -361,33 +261,38 @@ protected: unsigned ParamIdx = 0); /// VisitCast - Transfer function logic for all casts (implicit and explicit). - void VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst); + void VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred, + ExplodedNodeSet& Dst); /// VisitCompoundLiteralExpr - Transfer function logic for compound literals. void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, ExplodedNode* Pred, ExplodedNodeSet& Dst, bool asLValue); /// VisitDeclRefExpr - Transfer function logic for DeclRefExprs. - void VisitDeclRefExpr(DeclRefExpr* DR, ExplodedNode* Pred, ExplodedNodeSet& Dst, - bool asLValue); + void VisitDeclRefExpr(DeclRefExpr* DR, ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); /// VisitDeclStmt - Transfer function logic for DeclStmts. void VisitDeclStmt(DeclStmt* DS, ExplodedNode* Pred, ExplodedNodeSet& Dst); /// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose - void VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, ExplodedNode* Pred, ExplodedNodeSet& Dst); + void VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, ExplodedNode* Pred, + ExplodedNodeSet& Dst); - void VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred, ExplodedNodeSet& Dst); + void VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred, + ExplodedNodeSet& Dst); /// VisitLogicalExpr - Transfer function logic for '&&', '||' - void VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred, ExplodedNodeSet& Dst); + void VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred, + ExplodedNodeSet& Dst); /// VisitMemberExpr - Transfer function for member expressions. - void VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred, ExplodedNodeSet& Dst,bool asLValue); + void VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred, ExplodedNodeSet& Dst, + bool asLValue); /// VisitObjCIvarRefExpr - Transfer function logic for ObjCIvarRefExprs. - void VisitObjCIvarRefExpr(ObjCIvarRefExpr* DR, ExplodedNode* Pred, ExplodedNodeSet& Dst, - bool asLValue); + void VisitObjCIvarRefExpr(ObjCIvarRefExpr* DR, ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); /// VisitObjCForCollectionStmt - Transfer function logic for /// ObjCForCollectionStmt. diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h index ef0c36c..d8bc241 100644 --- a/include/clang/Analysis/PathSensitive/GRState.h +++ b/include/clang/Analysis/PathSensitive/GRState.h @@ -33,7 +33,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/DenseSet.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include <functional> @@ -264,8 +263,21 @@ public: const llvm::APSInt *getSymVal(SymbolRef sym); bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const; + + bool scanReachableSymbols(const SVal *I, const SVal *E, + SymbolVisitor &visitor) const; + + bool scanReachableSymbols(const MemRegion * const *I, + const MemRegion * const *E, + SymbolVisitor &visitor) const; template <typename CB> CB scanReachableSymbols(SVal val) const; + template <typename CB> CB scanReachableSymbols(const SVal *beg, + const SVal *end) const; + + template <typename CB> CB + scanReachableSymbols(const MemRegion * const *beg, + const MemRegion * const *end) const; //==---------------------------------------------------------------------==// // Accessing the Generic Data Map (GDM). @@ -726,7 +738,21 @@ CB GRState::scanReachableSymbols(SVal val) const { scanReachableSymbols(val, cb); return cb; } + +template <typename CB> +CB GRState::scanReachableSymbols(const SVal *beg, const SVal *end) const { + CB cb(this); + scanReachableSymbols(beg, end, cb); + return cb; +} +template <typename CB> +CB GRState::scanReachableSymbols(const MemRegion * const *beg, + const MemRegion * const *end) const { + CB cb(this); + scanReachableSymbols(beg, end, cb); + return cb; +} } // end clang namespace #endif diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h index 06d0d97..ed96497 100644 --- a/include/clang/Analysis/PathSensitive/MemRegion.h +++ b/include/clang/Analysis/PathSensitive/MemRegion.h @@ -35,6 +35,7 @@ namespace clang { class MemRegionManager; class MemSpaceRegion; class LocationContext; +class VarRegion; //===----------------------------------------------------------------------===// // Base region classes. @@ -42,13 +43,16 @@ class LocationContext; /// MemRegion - The root abstract class for all memory regions. class MemRegion : public llvm::FoldingSetNode { + friend class MemRegionManager; public: enum Kind { MemSpaceRegionKind, SymbolicRegionKind, AllocaRegionKind, // Typed regions. BEG_TYPED_REGIONS, - CodeTextRegionKind, + FunctionTextRegionKind, + BlockTextRegionKind, + BlockDataRegionKind, CompoundLiteralRegionKind, StringRegionKind, ElementRegionKind, // Decl Regions. @@ -237,45 +241,123 @@ public: } }; -/// CodeTextRegion - A region that represents code texts of a function. It wraps -/// two kinds of code texts: real function and symbolic function. Real function -/// is a function declared in the program. Symbolic function is a function -/// pointer that we don't know which function it points to. -class CodeTextRegion : public TypedRegion { - const FunctionDecl *FD; +class CodeTextRegion : public TypedRegion { +protected: + CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {} public: - - CodeTextRegion(const FunctionDecl* fd, const MemRegion* sreg) - : TypedRegion(sreg, CodeTextRegionKind), FD(fd) {} - QualType getValueType(ASTContext &C) const { // Do not get the object type of a CodeTextRegion. assert(0); return QualType(); } + + bool isBoundable() const { return false; } + + static bool classof(const MemRegion* R) { + Kind k = R->getKind(); + return k >= FunctionTextRegionKind && k <= BlockTextRegionKind; + } +}; +/// FunctionTextRegion - A region that represents code texts of function. +class FunctionTextRegion : public CodeTextRegion { + const FunctionDecl *FD; +public: + FunctionTextRegion(const FunctionDecl* fd, const MemRegion* sreg) + : CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) {} + QualType getLocationType(ASTContext &C) const { return C.getPointerType(FD->getType()); } - + const FunctionDecl *getDecl() const { return FD; } - - bool isBoundable() const { return false; } - + virtual void dumpToStream(llvm::raw_ostream& os) const; - + void Profile(llvm::FoldingSetNodeID& ID) const; - + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FunctionDecl *FD, const MemRegion*); - + + static bool classof(const MemRegion* R) { + return R->getKind() == FunctionTextRegionKind; + } +}; + + +/// BlockTextRegion - A region that represents code texts of blocks (closures). +/// Blocks are represented with two kinds of regions. BlockTextRegions +/// represent the "code", while BlockDataRegions represent instances of blocks, +/// which correspond to "code+data". The distinction is important, because +/// like a closure a block captures the values of externally referenced +/// variables. +class BlockTextRegion : public CodeTextRegion { + const BlockDecl *BD; + CanQualType locTy; +public: + BlockTextRegion(const BlockDecl *bd, CanQualType lTy, const MemRegion* sreg) + : CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), locTy(lTy) {} + + QualType getLocationType(ASTContext &C) const { + return locTy; + } + + const BlockDecl *getDecl() const { + return BD; + } + + virtual void dumpToStream(llvm::raw_ostream& os) const; + + void Profile(llvm::FoldingSetNodeID& ID) const; + + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD, + CanQualType, const MemRegion*); + static bool classof(const MemRegion* R) { - return R->getKind() == CodeTextRegionKind; + return R->getKind() == BlockTextRegionKind; } }; + +/// BlockDataRegion - A region that represents a block instance. +/// Blocks are represented with two kinds of regions. BlockTextRegions +/// represent the "code", while BlockDataRegions represent instances of blocks, +/// which correspond to "code+data". The distinction is important, because +/// like a closure a block captures the values of externally referenced +/// variables. +/// BlockDataRegion - A region that represents code texts of blocks (closures). +class BlockDataRegion : public SubRegion { + const BlockTextRegion *BC; + const LocationContext *LC; + void *ReferencedVars; +public: + BlockDataRegion(const BlockTextRegion *bc, + const LocationContext *lc, + const MemRegion *sreg) + : SubRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), ReferencedVars(0) {} + + const BlockTextRegion *getCodeRegion() const { return BC; } + + typedef const MemRegion * const * referenced_vars_iterator; + referenced_vars_iterator referenced_vars_begin() const; + referenced_vars_iterator referenced_vars_end() const; + + virtual void dumpToStream(llvm::raw_ostream& os) const; + + void Profile(llvm::FoldingSetNodeID& ID) const; + + static void ProfileRegion(llvm::FoldingSetNodeID& ID, + const BlockTextRegion *BC, + const LocationContext *LC, const MemRegion *); + + static bool classof(const MemRegion* R) { + return R->getKind() == BlockDataRegionKind; + } +private: + void LazyInitializeReferencedVars(); +}; /// SymbolicRegion - A special, "non-concrete" region. Unlike other region /// clases, SymbolicRegion represents a region that serves as an alias for @@ -577,9 +659,11 @@ public: : C(c), A(a), globals(0), stack(0), stackArguments(0), heap(0), unknown(0), code(0) {} - ~MemRegionManager() {} + ~MemRegionManager(); ASTContext &getContext() { return C; } + + llvm::BumpPtrAllocator &getAllocator() { return A; } /// getStackRegion - Retrieve the memory region associated with the /// current stack frame. @@ -656,7 +740,10 @@ public: ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl* ivd, const MemRegion* superRegion); - CodeTextRegion *getCodeTextRegion(const FunctionDecl *FD); + FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD); + BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, CanQualType locTy); + BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc, + const LocationContext *lc); template <typename RegionTy, typename A1> RegionTy* getRegion(const A1 a1); @@ -667,6 +754,10 @@ public: template <typename RegionTy, typename A1, typename A2> RegionTy* getRegion(const A1 a1, const A2 a2); + template <typename RegionTy, typename A1, typename A2> + RegionTy* getSubRegion(const A1 a1, const A2 a2, + const MemRegion* superRegion); + bool isGlobalsRegion(const MemRegion* R) { assert(R); return R == globals; @@ -745,6 +836,25 @@ RegionTy* MemRegionManager::getRegion(const A1 a1, const A2 a2) { return R; } + +template <typename RegionTy, typename A1, typename A2> +RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2, + const MemRegion *superRegion) { + + llvm::FoldingSetNodeID ID; + RegionTy::ProfileRegion(ID, a1, a2, superRegion); + void* InsertPos; + RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, + InsertPos)); + + if (!R) { + R = (RegionTy*) A.Allocate<RegionTy>(); + new (R) RegionTy(a1, a2, superRegion); + Regions.InsertNode(R, InsertPos); + } + + return R; +} //===----------------------------------------------------------------------===// // Traits for constructing regions. @@ -801,18 +911,21 @@ template <> struct MemRegionManagerTrait<SymbolicRegion> { } }; -template<> struct MemRegionManagerTrait<CodeTextRegion> { +template<> struct MemRegionManagerTrait<FunctionTextRegion> { typedef MemSpaceRegion SuperRegionTy; static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, const FunctionDecl*) { return MRMgr.getCodeRegion(); } +}; +template<> struct MemRegionManagerTrait<BlockTextRegion> { + typedef MemSpaceRegion SuperRegionTy; static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, - SymbolRef, QualType) { + const BlockDecl*, CanQualType) { return MRMgr.getCodeRegion(); } }; - + } // end clang namespace //===----------------------------------------------------------------------===// diff --git a/include/clang/Analysis/PathSensitive/ValueManager.h b/include/clang/Analysis/PathSensitive/ValueManager.h index 8d162a6..ef4e069 100644 --- a/include/clang/Analysis/PathSensitive/ValueManager.h +++ b/include/clang/Analysis/PathSensitive/ValueManager.h @@ -114,6 +114,9 @@ public: const TypedRegion *R); DefinedSVal getFunctionPointer(const FunctionDecl *FD); + + DefinedSVal getBlockPointer(const BlockDecl *BD, CanQualType locTy, + const LocationContext *LC); NonLoc makeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals) { return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals)); diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 2af9580..bbf42ee 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -250,8 +250,8 @@ BUILTIN(__builtin_ia32_pmaddwd128, "V8sV8sV8s", "") BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "") BUILTIN(__builtin_ia32_mwait, "vUiUi", "") BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "") -BUILTIN(__builtin_ia32_palignr128, "V2LLiV2LLiV2LLii", "") -BUILTIN(__builtin_ia32_palignr, "V1LLiV1LLiV1LLis", "") +BUILTIN(__builtin_ia32_palignr128, "V2LLiV2LLiV2LLic", "") +BUILTIN(__builtin_ia32_palignr, "V1LLiV1LLiV1LLic", "") BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "") BUILTIN(__builtin_ia32_storelv4si, "vV2i*V2LLi", "") diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index e2f1104..3f7d114 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -57,6 +57,9 @@ def err_drv_invalid_mfloat_abi : Error< "invalid float ABI '%0'">; def err_drv_I_dash_not_supported : Error< "'%0' not supported, please use -iquote instead">; +def err_drv_unknown_argument : Error<"unknown argument: '%0'">; +def err_drv_invalid_value : Error<"invalid value '%1' in '%0'">; +def err_drv_invalid_int_value : Error<"invalid integral value '%1' in '%0'">; def warn_drv_input_file_unused : Warning< "%0: '%1' input unused when '%2' is present">; diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index e9b351f..cbc287c 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -17,6 +17,8 @@ def err_fe_invalid_ast_file : Error<"invalid AST file: '%0'">, DefaultFatal; def err_fe_invalid_ast_action : Error<"invalid action for AST input">, DefaultFatal; def err_fe_invalid_code_complete_file : Error<"cannot locate code-completion file %0">, DefaultFatal; +def err_fe_stdout_binary : Error<"unable to change standard output to binary">, + DefaultFatal; def err_fe_dependency_file_requires_MT : Error< "-dependency-file requires at least one -MT option">; def err_fe_incompatible_options : Error< diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 93c655b..c1c833c 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -78,16 +78,19 @@ def : DiagGroup<"synth">; // Preprocessor warnings. def : DiagGroup<"builtin-macro-redefined">; -// Just silence warnings about common forms of -Wstrict-aliasing for now. +// Just silence warnings about -Wstrict-aliasing for now. def : DiagGroup<"strict-aliasing=0">; def : DiagGroup<"strict-aliasing=1">; def : DiagGroup<"strict-aliasing=2">; def : DiagGroup<"strict-aliasing">; -// Just silence warnings about common forms of -Wstrict-aliasing for now. +// Just silence warnings about -Wstrict-overflow for now. def : DiagGroup<"strict-overflow=0">; def : DiagGroup<"strict-overflow=1">; def : DiagGroup<"strict-overflow=2">; +def : DiagGroup<"strict-overflow=3">; +def : DiagGroup<"strict-overflow=4">; +def : DiagGroup<"strict-overflow=5">; def : DiagGroup<"strict-overflow">; def InvalidOffsetof : DiagGroup<"invalid-offsetof">; diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 7f3f4ea..39123d9 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -170,6 +170,8 @@ def ext_pp_counter : Extension< def err_pp_invalid_directive : Error<"invalid preprocessing directive">; def err_pp_hash_error : Error<"#error%0">; def err_pp_file_not_found : Error<"'%0' file not found">, DefaultFatal; +def err_pp_error_opening_file : Error< + "error opening file '%0'">, DefaultFatal; def err_pp_empty_filename : Error<"empty filename">; def err_pp_include_too_deep : Error<"#include nested too deeply">; def err_pp_expects_filename : Error<"expected \"FILENAME\" or <FILENAME>">; diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 3a8c5bf..4310704 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -44,7 +44,8 @@ def ext_c99_variable_decl_in_for_loop : Extension< def ext_c99_compound_literal : Extension< "compound literals are a C99-specific feature">; def ext_enumerator_list_comma : Extension< - "commas at the end of enumerator lists are a %select{C99|C++0x}0-specific feature">; + "commas at the end of enumerator lists are a %select{C99|C++0x}0-specific " + "feature">; def ext_gnu_indirect_goto : Extension< "use of GNU indirect-goto extension">; @@ -75,6 +76,7 @@ def err_expected_ident_lbrace : Error<"expected identifier or '{'">; def err_expected_lbrace : Error<"expected '{'">; def err_expected_lparen : Error<"expected '('">; def err_expected_rparen : Error<"expected ')'">; +def err_expected_lsquare : Error<"expected '['">; def err_expected_rsquare : Error<"expected ']'">; def err_expected_rbrace : Error<"expected '}'">; def err_expected_greater : Error<"expected '>'">; @@ -240,11 +242,18 @@ def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">; // C++ operator overloading def err_operator_missing_type_specifier : Error< "missing type specifier after 'operator'">; +def err_operator_string_not_empty : Error< + "string literal after 'operator' must be '\"\"'">; // Classes. def err_anon_type_definition : Error< "declaration of anonymous %0 must be a definition">; +def err_cxx0x_attribute_forbids_arguments : Error< + "C++0x attribute '%0' cannot have an argument list">; +def err_cxx0x_attribute_requires_arguments : Error< + "C++0x attribute '%0' must have an argument list">; +def err_attributes_not_allowed : Error<"an attribute list cannot appear here">; /// C++ Templates def err_expected_template : Error<"expected template">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index a864d8a..a0e03fe 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -443,8 +443,9 @@ def err_implicit_object_parameter_init : Error< def note_field_decl : Note<"member is declared here">; def note_previous_class_decl : Note< "%0 declared here">; -def note_ctor_synthesized_at : Note< - "implicit default constructor for %0 first required here">; +def note_member_synthesized_at : Note< + "implicit default %select{constructor|copy constructor|" + "copy assignment operator|destructor}0 for %1 first required here">; def err_missing_default_ctor : Error< "%select{|implicit default }0constructor for %1 must explicitly initialize " "the %select{base class|member}2 %3 which does not have a default " @@ -552,6 +553,15 @@ def err_auto_not_allowed : Error< def err_auto_var_requires_init : Error< "declaration of variable %0 with type %1 requires an initializer">; +// C++0x attributes +def err_repeat_attribute : Error<"'%0' attribute cannot be repeated">; + +// C++0x [[final]] +def err_final_function_overridden : Error< + "declaration of %0 overrides a 'final' function">; +def err_final_base : Error< + "derivation from 'final' %0">; + // Objective-C++ def err_objc_decls_may_only_appear_in_global_scope : Error< "Objective-C declarations may only appear in global scope">; @@ -638,8 +648,16 @@ def warn_attribute_weak_import_invalid_on_definition : Warning< "'weak_import' attribute cannot be specified on a definition">; def warn_attribute_wrong_decl_type : Warning< "%0 attribute only applies to %select{function|union|" - "variable and function|function or method|parameter|parameter or Objective-C method |" - "function, method or block}1 types">; + "variable and function|function or method|parameter|" + "parameter or Objective-C method |function, method or block|" + "virtual method or class|function, method, or parameter|class|virtual method" + "|member}1 types">; +def err_attribute_wrong_decl_type : Error< + "%0 attribute only applies to %select{function|union|" + "variable and function|function or method|parameter|" + "parameter or Objective-C method |function, method or block|" + "virtual method or class|function, method, or parameter|class|virtual method" + "|member}1 types">; def warn_gnu_inline_attribute_requires_inline : Warning< "'gnu_inline' attribute requires function to be marked 'inline'," " attribute ignored">; @@ -865,7 +883,7 @@ def err_addr_ovl_ambiguous : Error< def err_template_param_shadow : Error< "declaration of %0 shadows template parameter">; def note_template_param_here : Note<"template parameter is declared here">; -def note_template_export_unsupported : Note< +def warn_template_export_unsupported : Warning< "exported templates are unsupported">; def err_template_outside_namespace_or_class_scope : Error< "templates can only be declared in namespace or class scope">; @@ -902,7 +920,15 @@ def note_template_param_prev_default_arg : Note< "previous default template argument defined here">; def err_template_param_default_arg_missing : Error< "template parameter missing a default argument">; - +def err_template_parameter_default_in_function_template : Error< + "a template parameter of a function template cannot have a default argument " + "in C++98">; +def err_template_parameter_default_template_member : Error< + "cannot add a default template argument to the definition of a member of a " + "class template">; +def err_template_parameter_default_friend_template : Error< + "default template argument not permitted on a friend template">; + def err_template_variable : Error<"variable %0 declared as a template">; def err_template_variable_noparams : Error< "extraneous 'template<>' in declaration of variable %0">; @@ -1037,6 +1063,11 @@ def err_template_param_list_matches_nontemplate : Error< def err_template_spec_extra_headers : Error< "extraneous template parameter list in template specialization or " "out-of-line template definition">; +def warn_template_spec_extra_headers : Warning< + "extraneous template parameter list in template specialization">; +def note_explicit_template_spec_does_not_need_header : Note< + "'template<>' header not required for explicitly-specialized class %0 " + "declared here">; def err_template_qualified_declarator_no_match : Error< "nested name specifier '%0' for declaration does not refer into a class, " "class template or class template partial specialization">; @@ -1197,6 +1228,10 @@ def err_template_kw_refers_to_non_template : Error< "%0 following the 'template' keyword does not refer to a template">; def err_template_kw_refers_to_function_template : Error< "%0 following the 'template' keyword refers to a function template">; +def err_template_kw_refers_to_class_template : Error< + "'%0%1' instantiated to a class template, not a function template">; +def note_referenced_class_template : Error< + "class template declared here">; // C++0x Variadic Templates def err_template_param_pack_default_arg : Error< @@ -2050,6 +2085,8 @@ def err_base_init_direct_and_virtual : Error< "inherited virtual base class">; def err_not_direct_base_or_virtual : Error< "type %0 is not a direct or virtual base of '%1'">; +def err_not_direct_base_or_virtual_multi : Error< + "type %0 is not a direct or virtual base of '%1'">; def err_in_class_initializer_non_integral_type : Error< "in-class initializer has non-integral, non-enumeration type %0">; @@ -2275,6 +2312,15 @@ def err_typecheck_statement_requires_integer : Error< "statement requires expression of integer type (%0 invalid)">; def err_multiple_default_labels_defined : Error< "multiple default labels in one switch">; +def err_switch_multiple_conversions : Error< + "multiple conversions from switch condition type %0 to an integral or " + "enumeration type">; +def note_switch_conversion : Note< + "conversion to %select{integral|enumeration}0 type %1">; +def err_switch_explicit_conversion : Error< + "switch condition type %0 requires explicit conversion to %1">; +def err_switch_incomplete_class_type : Error< + "switch condition has incomplete class type %0">; def warn_empty_if_body : Warning< "if statement has empty body">, InGroup<EmptyBody>; def err_va_start_used_in_non_variadic_function : Error< diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index e06dfbb..5393950 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -496,6 +496,7 @@ public: #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ CXXOperator##Name, #include "clang/Basic/OperatorKinds.def" + CXXLiteralOperator, CXXUsingDirective, NUM_EXTRA_KINDS }; @@ -503,10 +504,10 @@ public: /// ExtraKindOrNumArgs - Either the kind of C++ special name or /// operator-id (if the value is one of the CXX* enumerators of /// ExtraKind), in which case the DeclarationNameExtra is also a - /// CXXSpecialName (for CXXConstructor, CXXDestructor, or - /// CXXConversionFunction) or CXXOperatorIdName, it may be also - /// name common to C++ using-directives (CXXUsingDirective), otherwise - /// it is NUM_EXTRA_KINDS+NumArgs, where NumArgs is the number of + /// CXXSpecialName, (for CXXConstructor, CXXDestructor, or + /// CXXConversionFunction) CXXOperatorIdName, or CXXLiteralOperatorName, + /// it may be also name common to C++ using-directives (CXXUsingDirective), + /// otherwise it is NUM_EXTRA_KINDS+NumArgs, where NumArgs is the number of /// arguments in the Objective-C selector, in which case the /// DeclarationNameExtra is also a MultiKeywordSelector. unsigned ExtraKindOrNumArgs; diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 99c100d..a16a271 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -14,6 +14,8 @@ #ifndef LLVM_CLANG_LANGOPTIONS_H #define LLVM_CLANG_LANGOPTIONS_H +#include <string> + namespace clang { /// LangOptions - This class keeps track of the various options that can be @@ -101,15 +103,10 @@ private: // on making enums signed. Set/Query this // value using accessors. - /// The user provided name for the "main file", if non-null. This is - /// useful in situations where the input file name does not match - /// the original input file, for example with -save-temps. - const char *MainFileName; - public: unsigned InstantiationDepth; // Maximum template instantiation depth. - const char *ObjCConstantStringClass; + std::string ObjCConstantStringClass; enum GCMode { NonGC, GCOnly, HybridGC }; enum StackProtectorMode { SSPOff, SSPOn, SSPReq }; @@ -124,7 +121,6 @@ public: GNUMode = ImplicitInt = Digraphs = 0; HexFloats = 0; GC = ObjC1 = ObjC2 = ObjCNonFragileABI = 0; - ObjCConstantStringClass = 0; C99 = Microsoft = CPlusPlus = CPlusPlus0x = 0; CXXOperatorNames = PascalStrings = WritableStrings = 0; Exceptions = Freestanding = NoBuiltin = 0; @@ -164,8 +160,6 @@ public: CharIsSigned = 1; ShortWChar = 0; - - MainFileName = 0; } GCMode getGCMode() const { return (GCMode) GC; } @@ -178,9 +172,6 @@ public: StackProtector = static_cast<unsigned>(m); } - const char *getMainFileName() const { return MainFileName; } - void setMainFileName(const char *Name) { MainFileName = Name; } - VisibilityMode getVisibilityMode() const { return (VisibilityMode) SymbolVisibility; } diff --git a/include/clang/Basic/OnDiskHashTable.h b/include/clang/Basic/OnDiskHashTable.h index 6b60f2e..9b50e8d 100644 --- a/include/clang/Basic/OnDiskHashTable.h +++ b/include/clang/Basic/OnDiskHashTable.h @@ -15,7 +15,6 @@ #define LLVM_CLANG_BASIC_ON_DISK_HASH_TABLE_H #include "llvm/Support/Allocator.h" -#include "llvm/Support/Compiler.h" #include "llvm/System/DataTypes.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 695f51d..49eaafe 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -80,7 +80,7 @@ public: }; protected: IntType SizeType, IntMaxType, UIntMaxType, PtrDiffType, IntPtrType, WCharType, - WIntType, Char16Type, Char32Type, Int64Type; + WIntType, Char16Type, Char32Type, Int64Type, SigAtomicType; public: IntType getSizeType() const { return SizeType; } IntType getIntMaxType() const { return IntMaxType; } @@ -94,6 +94,7 @@ public: IntType getChar16Type() const { return Char16Type; } IntType getChar32Type() const { return Char32Type; } IntType getInt64Type() const { return Int64Type; } + IntType getSigAtomicType() const { return SigAtomicType; } /// getTypeWidth - Return the width (in bits) of the specified integer type diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 239712c..9942233 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -17,6 +17,9 @@ #ifndef TOK #define TOK(X) #endif +#ifndef PUNCTUATOR +#define PUNCTUATOR(X,Y) TOK(X) +#endif #ifndef KEYWORD #define KEYWORD(X,Y) TOK(kw_ ## X) #endif @@ -113,64 +116,63 @@ TOK(wide_string_literal) // L"foo" TOK(angle_string_literal)// <foo> // C99 6.4.6: Punctuators. -TOK(l_square) // [ -TOK(r_square) // ] -TOK(l_paren) // ( -TOK(r_paren) // ) -TOK(l_brace) // { -TOK(r_brace) // } -TOK(period) // . -TOK(ellipsis) // ... -TOK(amp) // & -TOK(ampamp) // && -TOK(ampequal) // &= -TOK(star) // * -TOK(starequal) // *= -TOK(plus) // + -TOK(plusplus) // ++ -TOK(plusequal) // += -TOK(minus) // - -TOK(arrow) // -> -TOK(minusminus) // -- -TOK(minusequal) // -= -TOK(tilde) // ~ -TOK(exclaim) // ! -TOK(exclaimequal) // != -TOK(slash) // / -TOK(slashequal) // /= -TOK(percent) // % -TOK(percentequal) // %= -TOK(less) // < -TOK(lessless) // << -TOK(lessequal) // <= -TOK(lesslessequal) // <<= -TOK(greater) // > -TOK(greatergreater) // >> -TOK(greaterequal) // >= -TOK(greatergreaterequal) // >>= -TOK(caret) // ^ -TOK(caretequal) // ^= -TOK(pipe) // | -TOK(pipepipe) // || -TOK(pipeequal) // |= -TOK(question) // ? -TOK(colon) // : -TOK(semi) // ; -TOK(equal) // = -TOK(equalequal) // == -TOK(comma) // , -TOK(hash) // # -TOK(hashhash) // ## -TOK(hashat) // #@ +PUNCTUATOR(l_square, "[") +PUNCTUATOR(r_square, "]") +PUNCTUATOR(l_paren, "(") +PUNCTUATOR(r_paren, ")") +PUNCTUATOR(l_brace, "{") +PUNCTUATOR(r_brace, "}") +PUNCTUATOR(period, ".") +PUNCTUATOR(ellipsis, "...") +PUNCTUATOR(amp, "&") +PUNCTUATOR(ampamp, "&&") +PUNCTUATOR(ampequal, "&=") +PUNCTUATOR(star, "*") +PUNCTUATOR(starequal, "*=") +PUNCTUATOR(plus, "+") +PUNCTUATOR(plusplus, "++") +PUNCTUATOR(plusequal, "+=") +PUNCTUATOR(minus, "-") +PUNCTUATOR(arrow, "->") +PUNCTUATOR(minusminus, "--") +PUNCTUATOR(minusequal, "-=") +PUNCTUATOR(tilde, "~") +PUNCTUATOR(exclaim, "!") +PUNCTUATOR(exclaimequal, "!=") +PUNCTUATOR(slash, "/") +PUNCTUATOR(slashequal, "/=") +PUNCTUATOR(percent, "%") +PUNCTUATOR(percentequal, "%=") +PUNCTUATOR(less, "<") +PUNCTUATOR(lessless, "<<") +PUNCTUATOR(lessequal, "<=") +PUNCTUATOR(lesslessequal, "<<=") +PUNCTUATOR(greater, ">") +PUNCTUATOR(greatergreater, ">>") +PUNCTUATOR(greaterequal, ">=") +PUNCTUATOR(greatergreaterequal, ">>=") +PUNCTUATOR(caret, "^") +PUNCTUATOR(caretequal, "^=") +PUNCTUATOR(pipe, "|") +PUNCTUATOR(pipepipe, "||") +PUNCTUATOR(pipeequal, "|=") +PUNCTUATOR(question, "?") +PUNCTUATOR(colon, ":") +PUNCTUATOR(semi, ";") +PUNCTUATOR(equal, "=") +PUNCTUATOR(equalequal, "==") +PUNCTUATOR(comma, ",") +PUNCTUATOR(hash, "#") +PUNCTUATOR(hashhash, "##") +PUNCTUATOR(hashat, "#@") // C++ Support -TOK(periodstar) // .* -TOK(arrowstar) // ->* -TOK(coloncolon) // :: +PUNCTUATOR(periodstar, ".*") +PUNCTUATOR(arrowstar, "->*") +PUNCTUATOR(coloncolon, "::") // Objective C support. -TOK(at) // @ - +PUNCTUATOR(at, "@") // C99 6.4.1: Keywords. These turn into kw_* tokens. // Flags allowed: @@ -415,4 +417,5 @@ ANNOTATION(template_id) // annotation for a C++ template-id that names a #undef PPKEYWORD #undef ALIAS #undef KEYWORD +#undef PUNCTUATOR #undef TOK diff --git a/include/clang/CodeGen/CodeGenOptions.h b/include/clang/CodeGen/CodeGenOptions.h index 02679cd..c8fb37b 100644 --- a/include/clang/CodeGen/CodeGenOptions.h +++ b/include/clang/CodeGen/CodeGenOptions.h @@ -29,7 +29,9 @@ public: OnlyAlwaysInlining // Only run the always inlining pass. }; + unsigned AsmVerbose : 1; /// -dA, -fverbose-asm. unsigned DebugInfo : 1; /// Should generate deubg info (-g). + 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 @@ -38,35 +40,63 @@ public: unsigned MergeAllConstants : 1; /// Merge identical constants. unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled. unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled. + unsigned NoZeroInitializedInBSS : 1; /// -fno-zero-initialized-in-bss unsigned OptimizationLevel : 3; /// The -O[0-4] option specified. unsigned OptimizeSize : 1; /// If -Os is specified. - unsigned SimplifyLibCalls : 1; /// Should standard library calls be treated - /// specially. + unsigned SoftFloat : 1; /// -soft-float. 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 UnwindTables : 1; /// Emit unwind tables. unsigned VerifyModule : 1; /// Control whether the module should be run /// through the LLVM Verifier. - /// Inlining - The kind of inlining to perform. + /// The code model to use (-mcmodel). + std::string CodeModel; + + /// Enable additional debugging information. + std::string DebugPass; + + /// The ABI to use for passing floating point arguments. + std::string FloatABI; + + /// The float precision limit to use, if non-empty. + std::string LimitFloatPrecision; + + /// The kind of inlining to perform. InliningMethod Inlining; + /// The user provided name for the "main file", if non-empty. This is useful + /// in situations where the input file name does not match the original input + /// file, for example with -save-temps. + std::string MainFileName; + + /// The name of the relocation model to use. + std::string RelocationModel; + public: CodeGenOptions() { + AsmVerbose = 0; + DebugInfo = 0; + DisableFPElim = 0; + DisableLLVMOpts = 0; + DisableRedZone = 0; + MergeAllConstants = 1; + NoCommon = 0; + NoImplicitFloat = 0; + NoZeroInitializedInBSS = 0; OptimizationLevel = 0; OptimizeSize = 0; - DebugInfo = 0; + UnrollLoops = 0; + SoftFloat = 0; + TimePasses = 0; UnitAtATime = 1; - SimplifyLibCalls = UnrollLoops = 0; + UnwindTables = 0; VerifyModule = 1; - TimePasses = 0; - NoCommon = 0; + Inlining = NoInlining; - DisableRedZone = 0; - NoImplicitFloat = 0; - MergeAllConstants = 1; - DisableLLVMOpts = 0; + RelocationModel = "pic"; } }; diff --git a/include/clang/Driver/ArgList.h b/include/clang/Driver/ArgList.h index 5263108..ab1abff 100644 --- a/include/clang/Driver/ArgList.h +++ b/include/clang/Driver/ArgList.h @@ -25,8 +25,67 @@ namespace llvm { namespace clang { namespace driver { class Arg; + class ArgList; class Option; + /// arg_iterator - Iterates through arguments stored inside an ArgList. + class arg_iterator { + /// The current argument. + llvm::SmallVectorImpl<Arg*>::const_iterator Current; + + /// The argument list we are iterating over. + const ArgList &Args; + + /// Optional filters on the arguments which will be match. Most clients + /// should never want to iterate over arguments without filters, so we won't + /// bother to factor this into two separate iterator implementations. + // + // FIXME: Make efficient; the idea is to provide efficient iteration over + // all arguments which match a particular id and then just provide an + // iterator combinator which takes multiple iterators which can be + // efficiently compared and returns them in order. + OptSpecifier Id0, Id1, Id2; + + void SkipToNextArg(); + + public: + typedef const Arg* value_type; + typedef const Arg* reference; + typedef const Arg* pointer; + typedef std::forward_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + + arg_iterator(llvm::SmallVectorImpl<Arg*>::const_iterator it, + const ArgList &_Args, OptSpecifier _Id0 = 0U, + OptSpecifier _Id1 = 0U, OptSpecifier _Id2 = 0U) + : Current(it), Args(_Args), Id0(_Id0), Id1(_Id1), Id2(_Id2) { + SkipToNextArg(); + } + + operator const Arg*() { return *Current; } + reference operator*() const { return *Current; } + pointer operator->() const { return *Current; } + + arg_iterator &operator++() { + ++Current; + SkipToNextArg(); + return *this; + } + + arg_iterator operator++(int) { + arg_iterator tmp(*this); + ++(*this); + return tmp; + } + + friend bool operator==(arg_iterator LHS, arg_iterator RHS) { + return LHS.Current == RHS.Current; + } + friend bool operator!=(arg_iterator LHS, arg_iterator RHS) { + return !(LHS == RHS); + } + }; + /// ArgList - Ordered collection of driver arguments. /// /// The ArgList class manages a list of Arg instances as well as @@ -62,6 +121,10 @@ namespace driver { unsigned size() const { return Args.size(); } + /// @} + /// @name Arg Iteration + /// @{ + iterator begin() { return Args.begin(); } iterator end() { return Args.end(); } @@ -74,6 +137,18 @@ namespace driver { const_reverse_iterator rbegin() const { return Args.rbegin(); } const_reverse_iterator rend() const { return Args.rend(); } + arg_iterator filtered_begin(OptSpecifier Id0 = 0U, OptSpecifier Id1 = 0U, + OptSpecifier Id2 = 0U) const { + return arg_iterator(Args.begin(), *this, Id0, Id1, Id2); + } + arg_iterator filtered_end() const { + return arg_iterator(Args.end(), *this); + } + + /// @} + /// @name Arg Access + /// @{ + /// hasArg - Does the arg list contain any option matching \arg Id. /// /// \arg Claim Whether the argument should be claimed, if it exists. @@ -115,17 +190,13 @@ namespace driver { void AddLastArg(ArgStringList &Output, OptSpecifier Id0) const; /// AddAllArgs - Render all arguments matching the given ids. - void AddAllArgs(ArgStringList &Output, OptSpecifier Id0) const; void AddAllArgs(ArgStringList &Output, OptSpecifier Id0, - OptSpecifier Id1) const; - void AddAllArgs(ArgStringList &Output, OptSpecifier Id0, OptSpecifier Id1, - OptSpecifier Id2) const; + OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const; /// AddAllArgValues - Render the argument values of all arguments /// matching the given ids. - void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0) const; void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0, - OptSpecifier Id1) const; + OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const; /// AddAllArgsTranslated - Render all the arguments matching the /// given ids, but forced to separate args and using the provided diff --git a/include/clang/Driver/CC1Options.h b/include/clang/Driver/CC1Options.h index 057022c..4a8bbe5 100644 --- a/include/clang/Driver/CC1Options.h +++ b/include/clang/Driver/CC1Options.h @@ -17,8 +17,6 @@ namespace driver { namespace cc1options { enum ID { OPT_INVALID = 0, // This is not an option ID. - OPT_INPUT, // Reserved ID for input option. - OPT_UNKNOWN, // Reserved ID for unknown option. #define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ HELPTEXT, METAVAR) OPT_##ID, #include "clang/Driver/CC1Options.inc" diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index ef8d847..b34fe03 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -14,13 +14,400 @@ // Include the common option parsing interfaces. include "OptParser.td" +//===----------------------------------------------------------------------===// // Target Options +//===----------------------------------------------------------------------===// def target_abi : Separate<"-target-abi">, HelpText<"Target a particular ABI type">; -def target_cpu : Separate<"-mcpu">, - HelpText<"Target a specific cpu type (-mcpu=help for details)">; -def target_features : Separate<"-target-feature">, +def mcpu : Separate<"-mcpu">, + HelpText<"Target a specific cpu type ('-mcpu help' for details)">; +def target_feature : Separate<"-target-feature">, HelpText<"Target specific attributes">; -def target_triple : Separate<"-triple">, +def triple : Separate<"-triple">, HelpText<"Specify target triple (e.g. i686-apple-darwin9)">; +def triple_EQ : Joined<"-triple=">, Alias<triple>; + +//===----------------------------------------------------------------------===// +// Analyzer Options +//===----------------------------------------------------------------------===// + +def analysis_CFGDump : Flag<"-cfg-dump">, + HelpText<"Display Control-Flow Graphs">; +def analysis_CFGView : Flag<"-cfg-view">, + HelpText<"View Control-Flow Graphs using GraphViz">; +def analysis_DisplayLiveVariables : Flag<"-dump-live-variables">, + HelpText<"Print results of live variable analysis">; +def analysis_SecuritySyntacticChecks : Flag<"-warn-security-syntactic">, + HelpText<"Perform quick security checks that require no data flow">; +def analysis_WarnDeadStores : Flag<"-warn-dead-stores">, + HelpText<"Warn about stores to dead variables">; +def analysis_WarnUninitVals : Flag<"-warn-uninit-values">, + HelpText<"Warn about uses of uninitialized variables">; +def analysis_WarnObjCMethSigs : Flag<"-warn-objc-methodsigs">, + HelpText<"Warn about Objective-C method signatures with type incompatibilities">; +def analysis_WarnObjCDealloc : Flag<"-warn-objc-missing-dealloc">, + HelpText<"Warn about Objective-C classes that lack a correct implementation of -dealloc">; +def analysis_WarnObjCUnusedIvars : Flag<"-warn-objc-unused-ivars">, + HelpText<"Warn about private ivars that are never used">; +def analysis_CheckerCFRef : Flag<"-checker-cfref">, + HelpText<"Run the [Core] Foundation reference count checker">; +def analysis_WarnSizeofPointer : Flag<"-warn-sizeof-pointer">, + HelpText<"Warn about unintended use of sizeof() on pointer expressions">; +def analysis_InlineCall : Flag<"-inline-call">, + HelpText<"Experimental transfer function inling callees when its definition is available.">; + +def analyzer_store : Separate<"-analyzer-store">, + HelpText<"Source Code Analysis - Abstract Memory Store Models">; +def analyzer_store_EQ : Joined<"-analyzer-store=">, Alias<analyzer_store>; + +def analyzer_constraints : Separate<"-analyzer-constraints">, + HelpText<"Source Code Analysis - Symbolic Constraint Engines">; +def analyzer_constraints_EQ : Joined<"-analyzer-constraints=">, + Alias<analyzer_constraints>; + +def analyzer_output : Separate<"-analyzer-output">, + HelpText<"Source Code Analysis - Output Options">; +def analyzer_output_EQ : Joined<"-analyzer-output=">, + Alias<analyzer_output>; + +def analyzer_opt_analyze_headers : Flag<"-analyzer-opt-analyze-headers">, + HelpText<"Force the static analyzer to analyze functions defined in header files">; +def analyzer_display_progress : Flag<"-analyzer-display-progress">, + HelpText<"Emit verbose output about the analyzer's progress">; +def analyzer_experimental_checks : Flag<"-analyzer-experimental-checks">, + HelpText<"Use experimental path-sensitive checks">; +def analyzer_experimental_internal_checks : + Flag<"-analyzer-experimental-internal-checks">, + HelpText<"Use new default path-sensitive checks currently in testing">; +def analyze_function : Separate<"-analyze-function">, + HelpText<"Run analysis on specific function">; +def analyze_function_EQ : Joined<"-analyze-function=">, Alias<analyze_function>; +def analyzer_eagerly_assume : Flag<"-analyzer-eagerly-assume">, + HelpText<"Eagerly assume the truth/falseness of some symbolic constraints">; +def analyzer_no_purge_dead : Flag<"-analyzer-no-purge-dead">, + HelpText<"Don't remove dead symbols, bindings, and constraints before processing a statement">; +def trim_egraph : Flag<"-trim-egraph">, + HelpText<"Only show error-related paths in the analysis graph">; +def analyzer_viz_egraph_graphviz : Flag<"-analyzer-viz-egraph-graphviz">, + HelpText<"Display exploded graph using GraphViz">; +def analyzer_viz_egraph_ubigraph : Flag<"-analyzer-viz-egraph-ubigraph">, + HelpText<"Display exploded graph using Ubigraph">; + +//===----------------------------------------------------------------------===// +// CodeGen Options +//===----------------------------------------------------------------------===// + +def disable_llvm_optzns : Flag<"-disable-llvm-optzns">, + HelpText<"Don't run LLVM optimization passes">; +def disable_red_zone : Flag<"-disable-red-zone">, + HelpText<"Do not emit code that uses the red zone.">; +def g : Flag<"-g">, HelpText<"Generate source level debug information">; +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 fno_merge_all_constants : Flag<"-fno-merge-all-constants">, + HelpText<"Disallow merging of constants.">; +def masm_verbose : Flag<"-masm-verbose">, + HelpText<"Generate verbose assembly output">; +def mcode_model : Separate<"-mcode-model">, + HelpText<"The code model to use">; +def mdebug_pass : Separate<"-mdebug-pass">, + HelpText<"Enable additional debug output">; +def mdisable_fp_elim : Flag<"-mdisable-fp-elim">, + HelpText<"Disable frame pointer elimination optimization">; +def mfloat_abi : Flag<"-mfloat-abi">, + HelpText<"The float ABI to use">; +def mlimit_float_precision : Separate<"-mlimit-float-precision">, + HelpText<"Limit float precision to the given value">; +def mno_zero_initialized_in_bss : Flag<"-mno-zero-initialized-in-bss">, + HelpText<"Do not put zero initialized data in the BSS">; +def msoft_float : Separate<"-msoft-float">, + HelpText<"Use software floating point">; +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 O : Joined<"-O">, HelpText<"Optimization level">; +def Os : Flag<"-Os">, HelpText<"Optimize for size">; + +//===----------------------------------------------------------------------===// +// Dependency Output Options +//===----------------------------------------------------------------------===// + +def dependency_file : Separate<"-dependency-file">, + HelpText<"Filename (or -) to write dependency output to">; +def sys_header_deps : Flag<"-sys-header-deps">, + HelpText<"Include system headers in dependency output">; +def MT : Separate<"-MT">, HelpText<"Specify target for dependency">; +def MP : Flag<"-MP">, + HelpText<"Create phony target for each dependency (other than main file)">; + +//===----------------------------------------------------------------------===// +// Diagnostic Options +//===----------------------------------------------------------------------===// + +def dump_build_information : Separate<"-dump-build-information">, + MetaVarName<"filename">, + HelpText<"output a dump of some build information to a file">; +def fno_show_column : Flag<"-fno-show-column">, + HelpText<"Do not 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 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 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_show_option : Flag<"-fdiagnostics-show-option">, + HelpText<"Print diagnostic name with mappable diagnostics">; +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 +//===----------------------------------------------------------------------===// + +def code_completion_at : Separate<"-code-completion-at">, + MetaVarName<"file:line:column">, + HelpText<"Dump code-completion information at a location">; +def code_completion_at_EQ : Joined<"-code-completion-at=">, + Alias<code_completion_at>; +def no_code_completion_debug_printer : Flag<"-no-code-completion-debug-printer">, + HelpText<"Don't the \"debug\" code-completion print">; +def code_completion_macros : Flag<"-code-completion-macros">, + HelpText<"Include macros in code-completion results">; +def disable_free : Flag<"-disable-free">, + HelpText<"Disable freeing of memory on exit">; +def empty_input_only : Flag<"-empty-input-only">, + HelpText<"Force running on an empty input file">; +def x : Separate<"-x">, HelpText<"Input language type">; +def cxx_inheritance_view : Separate<"-cxx-inheritance-view">, + MetaVarName<"class name">, + HelpText<"View C++ inheritance for a specified class">; +def fixit_at : Separate<"-fixit-at">, MetaVarName<"source-location">, + HelpText<"Perform Fix-It modifications at the given source location">; +def o : Separate<"-o">, MetaVarName<"path">, HelpText<"Specify output file">; +def plugin : Separate<"-plugin">, + HelpText<"Use the named plugin action (use \"help\" to list available options)">; + +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">, + HelpText<"Run static analysis engine">; +def dump_tokens : Flag<"-dump-tokens">, + HelpText<"Run preprocessor, dump internal rep of tokens">; +def parse_noop : Flag<"-parse-noop">, + HelpText<"Run parser with noop callbacks (for timings)">; +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 parse_print_callbacks : Flag<"-parse-print-callbacks">, + HelpText<"Run parser and print each callback invoked">; +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_print_xml : Flag<"-ast-print-xml">, + HelpText<"Build ASTs and then print them in XML format">; +def ast_dump : Flag<"-ast-dump">, + HelpText<"Build ASTs and then debug dump them">; +def ast_view : Flag<"-ast-view">, + HelpText<"Build ASTs and view them with GraphViz">; +def print_decl_contexts : Flag<"-print-decl-contexts">, + HelpText<"Print DeclContexts and their Decls">; +def dump_record_layouts : Flag<"-dump-record-layouts">, + HelpText<"Dump record layout information">; +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">, + HelpText<"Build ASTs and convert to LLVM, discarding output">; +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 rewrite_blocks : Flag<"-rewrite-blocks">, + HelpText<"Rewrite Blocks to C">; + +} + +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">; + +//===----------------------------------------------------------------------===// +// 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 faccess_control : Flag<"-faccess-control">, + HelpText<"Enable C++ access control">; +def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, + HelpText<"Allow '$' 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 fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">; +def fexceptions : Flag<"-fexceptions">, + HelpText<"Enable support for exception handling">; +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 std_EQ : Joined<"-std=">, + HelpText<"Language standard to compile for">; +def fms_extensions : Flag<"-fms-extensions">, + HelpText<"Accept some non-standard constructs used in Microsoft header files ">; +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_math_errno : Flag<"-fno-math-errno">, + HelpText<"Don't require math functions to respect errno">; +def fno_signed_char : Flag<"-fno-signed-char">, + HelpText<"Char is unsigned">; +def fno_operator_names : Flag<"-fno-operator-names">, + HelpText<"Do not treat C++ operator name keywords as synonyms for operators">; +def fconstant_string_class : Separate<"-fconstant-string-class">, + MetaVarName<"class name">, + HelpText<"Specify the class to use for constant Objective-C string objects.">; +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 print_ivar_layout : Flag<"-print-ivar-layout">, + HelpText<"Enable Objective-C Ivar layout bitmap print trace">; +def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">, + HelpText<"enable objective-c's nonfragile abi">; +def ftrapv : Flag<"-ftrapv">, + HelpText<"Trap on integer overflow">; +def pic_level : Separate<"-pic-level">, + HelpText<"-Value for __PIC__">; +def pthread : Flag<"-pthread">, + HelpText<"Support POSIX threads in generated code">; +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 fshort_wchar : Flag<"-fshort-wchar">, + HelpText<"Force wchar_t to be a short unsigned int">; +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 ftemplate_depth : Separate<"-ftemplate-depth">, + HelpText<"Maximum depth of recursive template instantiation">; +def trigraphs : Flag<"-trigraphs">, + HelpText<"Process trigraph sequences">; +def fwritable_strings : Flag<"-fwritable-strings">, + HelpText<"Store string literals as writable data">; + +//===----------------------------------------------------------------------===// +// Header Search Options +//===----------------------------------------------------------------------===// + +def nostdinc : Flag<"-nostdinc">, + HelpText<"Disable standard #include directories">; +def nobuiltininc : Flag<"-nobuiltininc">, + HelpText<"Disable builtin #include directories">; +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 : Separate<"-idirafter">, MetaVarName<"directory">, + HelpText<"Add directory to AFTER include search path">; +def iquote : Separate<"-iquote">, MetaVarName<"directory">, + HelpText<"Add directory to QUOTE include search path">; +def isystem : Separate<"-isystem">, MetaVarName<"directory">, + HelpText<"Add directory to SYSTEM include search path">; +def iprefix : Separate<"-iprefix">, MetaVarName<"prefix">, + HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">; +def iwithprefix : Separate<"-iwithprefix">, MetaVarName<"dir">, + HelpText<"Set directory to SYSTEM include search path with prefix">; +def iwithprefixbefore : Separate<"-iwithprefixbefore">, MetaVarName<"dir">, + HelpText<"Set directory to include search path with prefix">; +def isysroot : Separate<"-isysroot">, MetaVarName<"dir">, + HelpText<"Set the system root directory (usually /)">; +def v : Flag<"-v">, HelpText<"Enable verbose output">; + +//===----------------------------------------------------------------------===// +// Preprocessor Options +//===----------------------------------------------------------------------===// + +def D : JoinedOrSeparate<"-D">, MetaVarName<"macro">, + HelpText<"Predefine the specified macro">; +def include_ : Separate<"-include">, MetaVarName<"file">, EnumName<"include">, + HelpText<"Include file before parsing">; +def imacros : Separate<"-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 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">; + +//===----------------------------------------------------------------------===// +// 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">; diff --git a/include/clang/Driver/Makefile b/include/clang/Driver/Makefile index c0f2cc7..18f3e58 100644 --- a/include/clang/Driver/Makefile +++ b/include/clang/Driver/Makefile @@ -5,11 +5,11 @@ TABLEGEN_INC_FILES_COMMON = 1 include $(LEVEL)/Makefile.common -$(ObjDir)/Options.inc.tmp : Options.td OptParser.td $(ObjDir)/.dir +$(ObjDir)/Options.inc.tmp : Options.td OptParser.td $(TBLGEN) $(ObjDir)/.dir $(Echo) "Building Clang Driver Option tables with tblgen" $(Verb) $(TableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $< -$(ObjDir)/CC1Options.inc.tmp : CC1Options.td OptParser.td $(ObjDir)/.dir +$(ObjDir)/CC1Options.inc.tmp : CC1Options.td OptParser.td $(TBLGEN) $(ObjDir)/.dir $(Echo) "Building Clang CC1 Option tables with tblgen" $(Verb) $(TableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $< diff --git a/include/clang/Driver/OptParser.td b/include/clang/Driver/OptParser.td index 70b59c6..f5b6980 100644 --- a/include/clang/Driver/OptParser.td +++ b/include/clang/Driver/OptParser.td @@ -14,14 +14,20 @@ // Define the kinds of options. -class OptionKind<string name, int predecence = 0> { +class OptionKind<string name, int predecence = 0, bit sentinel = 0> { string Name = name; // The kind precedence, kinds with lower precedence are matched first. int Precedence = predecence; + // Indicate a sentinel option. + bit Sentinel = sentinel; } // An option group. def KIND_GROUP : OptionKind<"Group">; +// The input option kind. +def KIND_INPUT : OptionKind<"Input", 1, 1>; +// The unknown option kind. +def KIND_UNKNOWN : OptionKind<"Unknown", 2, 1>; // A flag with no values. def KIND_FLAG : OptionKind<"Flag">; // An option which prefixes its (single) value. @@ -114,3 +120,10 @@ class Flags<list<OptionFlag> flags> { list<OptionFlag> Flags = flags; } class Group<OptionGroup group> { OptionGroup Group = group; } class HelpText<string text> { string HelpText = text; } class MetaVarName<string name> { string MetaVarName = name; } + +// Predefined options. + +// FIXME: Have generator validate that these appear in correct position (and +// aren't duplicated). +def INPUT : Option<"<input>", KIND_INPUT>, Flags<[DriverOption]>; +def UNKNOWN : Option<"<unknown>", KIND_UNKNOWN>; diff --git a/include/clang/Driver/OptSpecifier.h b/include/clang/Driver/OptSpecifier.h index c38b36c..bb1cd17 100644 --- a/include/clang/Driver/OptSpecifier.h +++ b/include/clang/Driver/OptSpecifier.h @@ -22,9 +22,12 @@ namespace driver { explicit OptSpecifier(bool); // DO NOT IMPLEMENT public: + OptSpecifier() : ID(0) {} /*implicit*/ OptSpecifier(unsigned _ID) : ID(_ID) {} /*implicit*/ OptSpecifier(const Option *Opt); + bool isValid() const { return ID != 0; } + unsigned getID() const { return ID; } bool operator==(OptSpecifier Opt) const { return ID == Opt.getID(); } diff --git a/include/clang/Driver/Options.h b/include/clang/Driver/Options.h index b05d5af..ac312cd 100644 --- a/include/clang/Driver/Options.h +++ b/include/clang/Driver/Options.h @@ -17,8 +17,6 @@ namespace driver { namespace options { enum ID { OPT_INVALID = 0, // This is not an option ID. - OPT_INPUT, // Reserved ID for input option. - OPT_UNKNOWN, // Reserved ID for unknown option. #define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ HELPTEXT, METAVAR) OPT_##ID, #include "clang/Driver/Options.inc" diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h index 0e7d55e..26efa97 100644 --- a/include/clang/Frontend/ASTConsumers.h +++ b/include/clang/Frontend/ASTConsumers.h @@ -83,6 +83,7 @@ ASTConsumer *CreateBackendConsumer(BackendAction Action, const LangOptions &Features, const CodeGenOptions &CodeGenOpts, const TargetOptions &TargetOpts, + bool TimePasses, const std::string &ModuleID, llvm::raw_ostream *OS, llvm::LLVMContext& C); diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 7dfabba..04dc5ed 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -22,16 +22,17 @@ #include <string> namespace clang { - class FileManager; - class FileEntry; - class SourceManager; - class Diagnostic; - class TextDiagnosticBuffer; - class HeaderSearch; - class TargetInfo; - class Preprocessor; - class ASTContext; - class Decl; +class ASTContext; +class CompilerInvocation; +class Decl; +class Diagnostic; +class FileEntry; +class FileManager; +class HeaderSearch; +class Preprocessor; +class SourceManager; +class TargetInfo; +class TextDiagnosticBuffer; using namespace idx; @@ -92,21 +93,35 @@ public: /// /// \param Filename - The PCH file to load. /// - /// \param diagClient - The diagnostics client to use. Specify NULL + /// \param DiagClient - The diagnostics client to use. Specify NULL /// to use a default client that emits warnings/errors to standard error. /// The ASTUnit objects takes ownership of this object. /// - /// \param FileMgr - The FileManager to use. - /// /// \param ErrMsg - Error message to report if the PCH file could not be /// loaded. /// /// \returns - The initialized ASTUnit or null if the PCH failed to load. static ASTUnit *LoadFromPCHFile(const std::string &Filename, std::string *ErrMsg = 0, - DiagnosticClient *diagClient = NULL, + DiagnosticClient *DiagClient = NULL, bool OnlyLocalDecls = false, bool UseBumpAllocator = false); + + /// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a + /// CompilerInvocation object. + /// + /// \param CI - The compiler invocation to use; it must have exactly one input + /// source file. + /// + /// \param Diags - The diagnostics engine to use for reporting errors. + // + // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we + // shouldn't need to specify them at construction time. + static ASTUnit *LoadFromCompilerInvocation(const CompilerInvocation &CI, + Diagnostic &Diags, + bool OnlyLocalDecls = false, + bool UseBumpAllocator = false); + }; } // namespace clang diff --git a/include/clang/Frontend/AnalysisConsumer.h b/include/clang/Frontend/AnalysisConsumer.h index 7a32433..24fed6e 100644 --- a/include/clang/Frontend/AnalysisConsumer.h +++ b/include/clang/Frontend/AnalysisConsumer.h @@ -77,7 +77,7 @@ public: AnalyzeAll = 0; AnalyzerDisplayProgress = 0; EagerlyAssume = 0; - PurgeDead = 0; + PurgeDead = 1; TrimGraph = 0; VisualizeEGDot = 0; VisualizeEGUbi = 0; diff --git a/include/clang/Frontend/CommandLineSourceLoc.h b/include/clang/Frontend/CommandLineSourceLoc.h index d5a0598..bea468b 100644 --- a/include/clang/Frontend/CommandLineSourceLoc.h +++ b/include/clang/Frontend/CommandLineSourceLoc.h @@ -16,7 +16,7 @@ #define LLVM_CLANG_FRONTEND_COMMANDLINESOURCELOC_H #include "llvm/Support/CommandLine.h" -#include <cstdio> +#include "llvm/Support/raw_ostream.h" namespace clang { @@ -25,6 +25,23 @@ struct ParsedSourceLocation { std::string FileName; unsigned Line; unsigned Column; + +public: + /// Construct a parsed source location from a string; the Filename is empty on + /// error. + static ParsedSourceLocation FromString(llvm::StringRef Str) { + ParsedSourceLocation PSL; + std::pair<llvm::StringRef, llvm::StringRef> ColSplit = Str.rsplit(':'); + std::pair<llvm::StringRef, llvm::StringRef> LineSplit = + ColSplit.first.rsplit(':'); + + // If both tail splits were valid integers, return success. + if (!ColSplit.second.getAsInteger(10, PSL.Column) && + !LineSplit.second.getAsInteger(10, PSL.Line)) + PSL.FileName = LineSplit.first; + + return PSL; + } }; } @@ -48,35 +65,13 @@ namespace llvm { clang::ParsedSourceLocation &Val) { using namespace clang; - const char *ExpectedFormat - = "source location must be of the form filename:line:column"; - StringRef::size_type SecondColon = ArgValue.rfind(':'); - if (SecondColon == std::string::npos) { - std::fprintf(stderr, "%s\n", ExpectedFormat); - return true; - } - - unsigned Column; - if (ArgValue.substr(SecondColon + 1).getAsInteger(10, Column)) { - std::fprintf(stderr, "%s\n", ExpectedFormat); - return true; - } - ArgValue = ArgValue.substr(0, SecondColon); - - StringRef::size_type FirstColon = ArgValue.rfind(':'); - if (FirstColon == std::string::npos) { - std::fprintf(stderr, "%s\n", ExpectedFormat); - return true; - } - unsigned Line; - if (ArgValue.substr(FirstColon + 1).getAsInteger(10, Line)) { - std::fprintf(stderr, "%s\n", ExpectedFormat); + Val = ParsedSourceLocation::FromString(ArgValue); + if (Val.FileName.empty()) { + errs() << "error: " + << "source location must be of the form filename:line:column\n"; return true; } - Val.FileName = ArgValue.substr(0, FirstColon); - Val.Line = Line; - Val.Column = Column; return false; } } diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index ed28050..d7e7d99 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -21,6 +21,7 @@ namespace llvm { class LLVMContext; class raw_ostream; class raw_fd_ostream; +class Timer; } namespace clang { @@ -89,6 +90,9 @@ class CompilerInstance { /// The code completion consumer. llvm::OwningPtr<CodeCompleteConsumer> CompletionConsumer; + /// The frontend timer + llvm::OwningPtr<llvm::Timer> FrontendTimer; + /// The list of active output files. std::list< std::pair<std::string, llvm::raw_ostream*> > OutputFiles; @@ -367,6 +371,17 @@ public: void setCodeCompletionConsumer(CodeCompleteConsumer *Value); /// } + /// @name Frontend timer + /// { + + bool hasFrontendTimer() const { return FrontendTimer != 0; } + + llvm::Timer &getFrontendTimer() const { + assert(FrontendTimer && "Compiler instance has no frontend timer!"); + return *FrontendTimer; + } + + /// } /// @name Output Files /// { @@ -462,6 +477,9 @@ public: bool UseDebugPrinter, bool ShowMacros, llvm::raw_ostream &OS); + /// Create the frontend timer and replace any existing one with it. + void createFrontendTimer(); + /// Create the default output file (from the invocation's options) and add it /// to the list of tracked output files. llvm::raw_fd_ostream * diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h index 9d068c5..e7c51aa 100644 --- a/include/clang/Frontend/CompilerInvocation.h +++ b/include/clang/Frontend/CompilerInvocation.h @@ -31,6 +31,8 @@ namespace llvm { namespace clang { +class Diagnostic; + /// CompilerInvocation - Helper class for holding the data necessary to invoke /// the compiler. /// @@ -77,12 +79,18 @@ public: /// CreateFromArgs - Create a compiler invocation from a list of input /// options. /// - /// FIXME: Documenting error behavior. - /// /// \param Res [out] - The resulting invocation. - /// \param Args - The input argument strings. - static void CreateFromArgs(CompilerInvocation &Res, - const llvm::SmallVectorImpl<llvm::StringRef> &Args); + /// \param ArgBegin - The first element in the argument vector. + /// \param ArgEnd - The last element in the argument vector. + /// \param Argv0 - The program path (from argv[0]), for finding the builtin + /// compiler path. + /// \param MainAddr - The address of main (or some other function in the main + /// executable), for finding the builtin compiler path. + /// \param Diags - The diagnostic engine to use for errors. + static void CreateFromArgs(CompilerInvocation &Res, const char **ArgBegin, + const char **ArgEnd, const char *Argv0, + void *MainAddr, + Diagnostic &Diags); /// toArgs - Convert the CompilerInvocation to a list of strings suitable for /// passing to CreateFromArgs. diff --git a/include/clang/Frontend/DeclXML.def b/include/clang/Frontend/DeclXML.def index 8b80d1d..c750492 100644 --- a/include/clang/Frontend/DeclXML.def +++ b/include/clang/Frontend/DeclXML.def @@ -7,46 +7,46 @@ // //===----------------------------------------------------------------------===// // -// This file defines the XML statement database structure as written in -// <TranslationUnit> sub-nodes of the XML document. +// This file defines the XML statement database structure as written in +// <TranslationUnit> sub-nodes of the XML document. // The semantics of the attributes and enums are mostly self-documenting // by looking at the appropriate internally used functions and values. // The following macros are used: // -// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete -// statement of class CLASS where CLASS is a class name used internally by clang. -// After a NODE_XML the definition of all (optional) attributes of that statement +// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete +// statement of class CLASS where CLASS is a class name used internally by clang. +// After a NODE_XML the definition of all (optional) attributes of that statement // node and possible sub-nodes follows. // // END_NODE_XML - Closes the attribute definition of the current node. // -// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a -// string, which value uniquely identify that statement. Other nodes may refer +// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a +// string, which value uniquely identify that statement. Other nodes may refer // by reference attributes to this value (currently used only for Label). // // TYPE_ATTRIBUTE_XML( FN ) - Type nodes refer to the result type id of an // expression by a "type" attribute. FN is internally used by clang. -// -// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally +// +// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally // used by clang. A boolean attribute have the values "0" or "1". // -// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves -// a special handling. See the appropriate documentations. +// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves +// a special handling. See the appropriate documentations. // // ATTRIBUTE_FILE_LOCATION_XML - A bunch of attributes denoting the location of // a statement in the source file(s). // -// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME. -// Optional attributes are omitted for boolean types, if the value is false, -// for integral types, if the value is null and for strings, +// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME. +// Optional attributes are omitted for boolean types, if the value is false, +// for integral types, if the value is null and for strings, // if the value is the empty string. FN is internally used by clang. // // ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value -// is an enumeration defined with ENUM_XML macros immediately following after -// that macro. An optional attribute is ommited, if the particular enum is the +// is an enumeration defined with ENUM_XML macros immediately following after +// that macro. An optional attribute is ommited, if the particular enum is the // empty string. FN is internally used by clang. -// -// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is +// +// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is // internally used by clang. // // END_ENUM_XML - Closes the enumeration definition of the current attribute. @@ -55,7 +55,7 @@ // // SUB_NODE_OPT_XML( CLASS ) - An optional sub-node of class CLASS or its sub-classes. // -// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or +// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or // its sub-classes. // //===----------------------------------------------------------------------===// @@ -114,8 +114,8 @@ NODE_XML(CXXMethodDecl, "CXXMethodDecl") TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType()) ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type") ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") - ATTRIBUTE_OPT_XML(isStatic(), "static") - ATTRIBUTE_OPT_XML(isVirtual(), "virtual") + ATTRIBUTE_OPT_XML(isStatic(), "static") + ATTRIBUTE_OPT_XML(isVirtual(), "virtual") ATTRIBUTE_XML(getNumParams(), "num_args") SUB_NODE_SEQUENCE_XML(ParmVarDecl) //SUB_NODE_OPT_XML("Body") @@ -124,7 +124,7 @@ END_NODE_XML //NODE_XML("Body") // SUB_NODE_XML(Stmt) //END_NODE_XML - + NODE_XML(NamespaceDecl, "Namespace") ID_ATTRIBUTE_XML ATTRIBUTE_FILE_LOCATION_XML @@ -152,7 +152,7 @@ NODE_XML(RecordDecl, "Record") ATTRIBUTE_XML(getDeclContext(), "context") ATTRIBUTE_XML(getNameAsString(), "name") ATTRIBUTE_OPT_XML(isDefinition() == false, "forward") - ATTRIBUTE_XML(getTypeForDecl(), "type") // refers to the type this decl creates + ATTRIBUTE_XML(getTypeForDecl(), "type") // refers to the type this decl creates SUB_NODE_SEQUENCE_XML(FieldDecl) END_NODE_XML @@ -162,7 +162,7 @@ NODE_XML(EnumDecl, "Enum") ATTRIBUTE_XML(getDeclContext(), "context") ATTRIBUTE_XML(getNameAsString(), "name") ATTRIBUTE_OPT_XML(isDefinition() == false, "forward") - ATTRIBUTE_SPECIAL_XML(getIntegerType(), "type") // is NULL in pure declarations thus deserves special handling + ATTRIBUTE_SPECIAL_XML(getIntegerType(), "type") // is NULL in pure declarations thus deserves special handling SUB_NODE_SEQUENCE_XML(EnumConstantDecl) // only present in definition END_NODE_XML @@ -209,7 +209,7 @@ NODE_XML(VarDecl, "Var") ENUM_XML(VarDecl::Static, "static") ENUM_XML(VarDecl::PrivateExtern, "__private_extern__") END_ENUM_XML - SUB_NODE_OPT_XML(Expr) // init expr + SUB_NODE_OPT_XML(Expr) // init expr END_NODE_XML NODE_XML(ParmVarDecl, "ParmVar") @@ -218,7 +218,7 @@ NODE_XML(ParmVarDecl, "ParmVar") ATTRIBUTE_XML(getDeclContext(), "context") ATTRIBUTE_XML(getNameAsString(), "name") TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_OPT_XML(Expr) // default argument expression + SUB_NODE_OPT_XML(Expr) // default argument expression END_NODE_XML NODE_XML(LinkageSpecDecl, "LinkageSpec") @@ -234,7 +234,7 @@ END_NODE_XML //===----------------------------------------------------------------------===// #undef NODE_XML -#undef ID_ATTRIBUTE_XML +#undef ID_ATTRIBUTE_XML #undef TYPE_ATTRIBUTE_XML #undef ATTRIBUTE_XML #undef ATTRIBUTE_SPECIAL_XML @@ -243,8 +243,8 @@ END_NODE_XML #undef ATTRIBUTE_ENUM_OPT_XML #undef ATTRIBUTE_FILE_LOCATION_XML #undef ENUM_XML -#undef END_ENUM_XML -#undef END_NODE_XML +#undef END_ENUM_XML +#undef END_NODE_XML #undef SUB_NODE_XML #undef SUB_NODE_SEQUENCE_XML #undef SUB_NODE_OPT_XML diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h index 469ea53..3042767 100644 --- a/include/clang/Frontend/FrontendAction.h +++ b/include/clang/Frontend/FrontendAction.h @@ -14,10 +14,6 @@ #include "llvm/ADT/OwningPtr.h" #include <string> -namespace llvm { -class Timer; -} - namespace clang { class ASTUnit; class ASTConsumer; @@ -29,7 +25,6 @@ class FrontendAction { std::string CurrentFile; llvm::OwningPtr<ASTUnit> CurrentASTUnit; CompilerInstance *Instance; - llvm::Timer *CurrentTimer; protected: /// @name Implementation Action Interface @@ -112,18 +107,6 @@ public: void setCurrentFile(llvm::StringRef Value, ASTUnit *AST = 0); /// @} - /// @name Timing Utilities - /// @{ - - llvm::Timer *getCurrentTimer() const { - return CurrentTimer; - } - - void setCurrentTimer(llvm::Timer *Value) { - CurrentTimer = Value; - } - - /// @} /// @name Supported Modes /// @{ diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index 197a2a0..c1ec8e7 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -107,7 +107,7 @@ public: public: FrontendOptions() { - DebugCodeCompletionPrinter = 0; + DebugCodeCompletionPrinter = 1; DisableFree = 0; EmptyInputOnly = 0; ProgramAction = frontend::ParseSyntaxOnly; diff --git a/include/clang/Frontend/LangStandard.h b/include/clang/Frontend/LangStandard.h new file mode 100644 index 0000000..441d34f --- /dev/null +++ b/include/clang/Frontend/LangStandard.h @@ -0,0 +1,83 @@ +//===--- LangStandard.h -----------------------------------------*- 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_FRONTEND_LANGSTANDARD_H +#define LLVM_CLANG_FRONTEND_LANGSTANDARD_H + +#include "llvm/ADT/StringRef.h" + +namespace clang { + +namespace frontend { + +enum LangFeatures { + BCPLComment = (1 << 0), + C99 = (1 << 1), + CPlusPlus = (1 << 2), + CPlusPlus0x = (1 << 3), + Digraphs = (1 << 4), + GNUMode = (1 << 5), + HexFloat = (1 << 6), + ImplicitInt = (1 << 7) +}; + +} + +/// LangStandard - Information about the properties of a particular language +/// standard. +struct LangStandard { + enum Kind { +#define LANGSTANDARD(id, name, desc, features) \ + lang_##id, +#include "clang/Frontend/LangStandards.def" + lang_unspecified + }; + + const char *ShortName; + const char *Description; + unsigned Flags; + +public: + /// getName - Get the name of this standard. + const char *getName() const { return ShortName; } + + /// getDescription - Get the description of this standard. + const char *getDescription() const { return Description; } + + /// hasBCPLComments - Language supports '//' comments. + bool hasBCPLComments() const { return Flags & frontend::BCPLComment; } + + /// isC99 - Language is a superset of C99. + bool isC99() const { return Flags & frontend::C99; } + + /// isCPlusPlus - Language is a C++ variant. + bool isCPlusPlus() const { return Flags & frontend::CPlusPlus; } + + /// isCPlusPlus0x - Language is a C++0x variant. + bool isCPlusPlus0x() const { return Flags & frontend::CPlusPlus0x; } + + /// hasDigraphs - Language supports digraphs. + bool hasDigraphs() const { return Flags & frontend::Digraphs; } + + /// isGNUMode - Language includes GNU extensions. + bool isGNUMode() const { return Flags & frontend::GNUMode; } + + /// hasHexFloats - Language supports hexadecimal float constants. + bool hasHexFloats() const { return Flags & frontend::HexFloat; } + + /// hasImplicitInt - Language allows variables to be typed as int implicitly. + bool hasImplicitInt() const { return Flags & frontend::ImplicitInt; } + + static const LangStandard &getLangStandardForKind(Kind K); + static const LangStandard *getLangStandardForName(llvm::StringRef Name); +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Frontend/LangStandards.def b/include/clang/Frontend/LangStandards.def new file mode 100644 index 0000000..52aa463 --- /dev/null +++ b/include/clang/Frontend/LangStandards.def @@ -0,0 +1,83 @@ +//===-- LangStandards.def - Language Standard Data --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LANGSTANDARD +#error "LANGSTANDARD must be defined before including this file" +#endif + +/// LANGSTANDARD(IDENT, NAME, DESC, FEATURES) +/// +/// \param IDENT - The name of the standard as a C++ identifier. +/// \param NAME - The name of the standard. +/// \param DESC - A short description of the standard. +/// \param FEATURES - The standard features as flags, these are enums from the +/// clang::frontend namespace, which is assumed to be be available. + +// C89-ish modes. +LANGSTANDARD(c89, "c89", + "ISO C 1990", + ImplicitInt) +LANGSTANDARD(c90, "c90", + "ISO C 1990", + ImplicitInt) +LANGSTANDARD(iso9899_1990, "iso9899:1990", + "ISO C 1990", + ImplicitInt) + +LANGSTANDARD(c94, "iso9899:199409", + "ISO C 1990 with amendment 1", + Digraphs | ImplicitInt) + +LANGSTANDARD(gnu89, "gnu89", + "ISO C 1990 with GNU extensions", + BCPLComment | Digraphs | GNUMode | ImplicitInt) + +// C99-ish modes +LANGSTANDARD(c99, "c99", + "ISO C 1999", + BCPLComment | C99 | Digraphs | HexFloat) +LANGSTANDARD(c9x, "c9x", + "ISO C 1999", + BCPLComment | C99 | Digraphs | HexFloat) +LANGSTANDARD(iso9899_1999, + "iso9899:1999", "ISO C 1999", + BCPLComment | C99 | Digraphs | HexFloat) +LANGSTANDARD(iso9899_199x, + "iso9899:199x", "ISO C 1999", + BCPLComment | C99 | Digraphs | HexFloat) + +LANGSTANDARD(gnu99, "gnu99", + "ISO C 1999 with GNU extensions", + BCPLComment | C99 | Digraphs | GNUMode | HexFloat | Digraphs) +LANGSTANDARD(gnu9x, "gnu9x", + "ISO C 1999 with GNU extensions", + BCPLComment | C99 | Digraphs | GNUMode | HexFloat) + +// C++ modes +LANGSTANDARD(cxx98, "c++98", + "ISO C++ 1998 with amendments", + BCPLComment | CPlusPlus | Digraphs) +LANGSTANDARD(gnucxx98, "gnu++98", + "ISO C++ 1998 with " "amendments and GNU extensions", + BCPLComment | CPlusPlus | Digraphs | GNUMode) + +LANGSTANDARD(cxx0x, "c++0x", + "Upcoming ISO C++ 200x with amendments", + BCPLComment | CPlusPlus | CPlusPlus0x | Digraphs) +LANGSTANDARD(gnucxx0x, "gnu++0x", + "Upcoming ISO C++ 200x with amendments and GNU extensions", + BCPLComment | CPlusPlus | CPlusPlus0x | Digraphs | GNUMode) + +// OpenCL + +LANGSTANDARD(opencl, "cl", + "OpenCL 1.0", + BCPLComment | C99 | Digraphs | HexFloat) + +#undef LANGSTANDARD diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index b2bb9a1..98463c3 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -336,7 +336,9 @@ namespace clang { /// \brief The ObjC 'id' type. PREDEF_TYPE_OBJC_ID = 26, /// \brief The ObjC 'Class' type. - PREDEF_TYPE_OBJC_CLASS = 27 + PREDEF_TYPE_OBJC_CLASS = 27, + /// \brief The ObjC 'SEL' type. + PREDEF_TYPE_OBJC_SEL = 28 }; /// \brief The number of predefined type IDs that are reserved for @@ -438,7 +440,9 @@ namespace clang { /// \brief Block descriptor type for Blocks CodeGen SPECIAL_TYPE_BLOCK_DESCRIPTOR = 12, /// \brief Block extedned descriptor type for Blocks CodeGen - SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR = 13 + SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR = 13, + /// \brief Objective-C "SEL" redefinition type + SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 14 }; /// \brief Record codes for each kind of declaration. diff --git a/include/clang/Frontend/PathDiagnosticClients.h b/include/clang/Frontend/PathDiagnosticClients.h index 98831ba..f8d2eeb 100644 --- a/include/clang/Frontend/PathDiagnosticClients.h +++ b/include/clang/Frontend/PathDiagnosticClients.h @@ -14,9 +14,7 @@ #ifndef LLVM_CLANG_FRONTEND_PATH_DIAGNOSTIC_CLIENTS_H #define LLVM_CLANG_FRONTEND_PATH_DIAGNOSTIC_CLiENTS_H -#include <memory> #include <string> -#include "llvm/ADT/SmallVector.h" namespace clang { diff --git a/include/clang/Frontend/StmtXML.def b/include/clang/Frontend/StmtXML.def index fd79cf0..2f0da9e 100644 --- a/include/clang/Frontend/StmtXML.def +++ b/include/clang/Frontend/StmtXML.def @@ -7,46 +7,46 @@ // //===----------------------------------------------------------------------===// // -// This file defines the XML statement database structure as written in -// <TranslationUnit> sub-nodes of the XML document. +// This file defines the XML statement database structure as written in +// <TranslationUnit> sub-nodes of the XML document. // The semantics of the attributes and enums are mostly self-documenting // by looking at the appropriate internally used functions and values. // The following macros are used: // -// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete -// statement of class CLASS where CLASS is a class name used internally by clang. -// After a NODE_XML the definition of all (optional) attributes of that statement +// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete +// statement of class CLASS where CLASS is a class name used internally by clang. +// After a NODE_XML the definition of all (optional) attributes of that statement // node and possible sub-nodes follows. // // END_NODE_XML - Closes the attribute definition of the current node. // -// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a -// string, which value uniquely identify that statement. Other nodes may refer +// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a +// string, which value uniquely identify that statement. Other nodes may refer // by reference attributes to this value (currently used only for Label). // // TYPE_ATTRIBUTE_XML( FN ) - Type nodes refer to the result type id of an // expression by a "type" attribute. FN is internally used by clang. -// -// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally +// +// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally // used by clang. A boolean attribute have the values "0" or "1". // -// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves -// a special handling. See the appropriate documentations. +// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves +// a special handling. See the appropriate documentations. // // ATTRIBUTE_FILE_LOCATION_XML - A bunch of attributes denoting the location of // a statement in the source file(s). // -// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME. -// Optional attributes are omitted for boolean types, if the value is false, -// for integral types, if the value is null and for strings, +// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME. +// Optional attributes are omitted for boolean types, if the value is false, +// for integral types, if the value is null and for strings, // if the value is the empty string. FN is internally used by clang. // // ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value -// is an enumeration defined with ENUM_XML macros immediately following after -// that macro. An optional attribute is ommited, if the particular enum is the +// is an enumeration defined with ENUM_XML macros immediately following after +// that macro. An optional attribute is ommited, if the particular enum is the // empty string. FN is internally used by clang. -// -// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is +// +// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is // internally used by clang. // // END_ENUM_XML - Closes the enumeration definition of the current attribute. @@ -55,7 +55,7 @@ // // SUB_NODE_OPT_XML( CLASS ) - An optional sub-node of class CLASS or its sub-classes. // -// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or +// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or // its sub-classes. // //===----------------------------------------------------------------------===// @@ -94,21 +94,21 @@ END_NODE_XML NODE_XML(CaseStmt, "CaseStmt") // case expr: body; ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(Stmt) // body + SUB_NODE_XML(Stmt) // body SUB_NODE_XML(Expr) // expr SUB_NODE_XML(Expr) // rhs expr in gc extension: case expr .. expr: body; END_NODE_XML NODE_XML(DefaultStmt, "DefaultStmt") // default: body; ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(Stmt) // body + SUB_NODE_XML(Stmt) // body END_NODE_XML NODE_XML(LabelStmt, "LabelStmt") // Label: body; ID_ATTRIBUTE_XML ATTRIBUTE_FILE_LOCATION_XML ATTRIBUTE_XML(getName(), "name") // string - SUB_NODE_XML(Stmt) // body + SUB_NODE_XML(Stmt) // body END_NODE_XML NODE_XML(IfStmt, "IfStmt") // if (cond) stmt1; else stmt2; @@ -173,23 +173,23 @@ NODE_XML(AsmStmt, "AsmStmt") // GNU inline-assembly sta // FIXME END_NODE_XML -NODE_XML(DeclStmt, "DeclStmt") // a declaration statement +NODE_XML(DeclStmt, "DeclStmt") // a declaration statement ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_SEQUENCE_XML(Decl) + SUB_NODE_SEQUENCE_XML(Decl) END_NODE_XML // C++ statements NODE_XML(CXXTryStmt, "CXXTryStmt") // try CompoundStmt CXXCatchStmt1 CXXCatchStmt2 .. ATTRIBUTE_FILE_LOCATION_XML ATTRIBUTE_XML(getNumHandlers(), "num_handlers") - SUB_NODE_XML(CompoundStmt) - SUB_NODE_SEQUENCE_XML(CXXCatchStmt) + SUB_NODE_XML(CompoundStmt) + SUB_NODE_SEQUENCE_XML(CXXCatchStmt) END_NODE_XML NODE_XML(CXXCatchStmt, "CXXCatchStmt") // catch (decl) Stmt ATTRIBUTE_FILE_LOCATION_XML SUB_NODE_XML(VarDecl) - SUB_NODE_XML(Stmt) + SUB_NODE_XML(Stmt) END_NODE_XML // Expressions @@ -234,7 +234,7 @@ NODE_XML(StringLiteral, "StringLiteral") ATTRIBUTE_FILE_LOCATION_XML TYPE_ATTRIBUTE_XML(getType()) ATTRIBUTE_SPECIAL_XML(getStrData(), "value") // string, special handling for escaping needed - ATTRIBUTE_OPT_XML(isWide(), "is_wide") // boolean + ATTRIBUTE_OPT_XML(isWide(), "is_wide") // boolean END_NODE_XML NODE_XML(UnaryOperator, "UnaryOperator") // op(expr) or (expr)op @@ -251,7 +251,7 @@ NODE_XML(UnaryOperator, "UnaryOperator") // op(expr) or (expr)op ENUM_XML(UnaryOperator::Minus, "minus") ENUM_XML(UnaryOperator::Not, "not") // bitwise not ENUM_XML(UnaryOperator::LNot, "lnot") // boolean not - ENUM_XML(UnaryOperator::Real, "__real") + ENUM_XML(UnaryOperator::Real, "__real") ENUM_XML(UnaryOperator::Imag, "__imag") ENUM_XML(UnaryOperator::Extension, "__extension__") ENUM_XML(UnaryOperator::OffsetOf, "__builtin_offsetof") @@ -314,7 +314,7 @@ END_NODE_XML NODE_XML(SizeOfAlignOfExpr, "SizeOfAlignOfExpr") // sizeof(expr) or alignof(expr) ATTRIBUTE_FILE_LOCATION_XML TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(isSizeOf(), "is_sizeof") + ATTRIBUTE_XML(isSizeOf(), "is_sizeof") ATTRIBUTE_XML(isArgumentType(), "is_type") // "1" if expr denotes a type ATTRIBUTE_SPECIAL_XML(getArgumentType(), "type_ref") // optional, denotes the type of expr, if is_type=="1", special handling needed since getArgumentType() could assert SUB_NODE_OPT_XML(Expr) // expr, if is_type=="0" @@ -346,29 +346,29 @@ END_NODE_XML NODE_XML(CStyleCastExpr, "CStyleCastExpr") // (type)expr ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) + TYPE_ATTRIBUTE_XML(getType()) ATTRIBUTE_XML(getTypeAsWritten(), "type_ref") // denotes the type as written in the source code SUB_NODE_XML(Expr) // expr END_NODE_XML NODE_XML(ImplicitCastExpr, "ImplicitCastExpr") ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_XML(Expr) + TYPE_ATTRIBUTE_XML(getType()) + SUB_NODE_XML(Expr) END_NODE_XML -NODE_XML(CompoundLiteralExpr, "CompoundLiteralExpr") // [C99 6.5.2.5] +NODE_XML(CompoundLiteralExpr, "CompoundLiteralExpr") // [C99 6.5.2.5] SUB_NODE_XML(Expr) // init END_NODE_XML NODE_XML(ExtVectorElementExpr, "ExtVectorElementExpr") - SUB_NODE_XML(Expr) // base + SUB_NODE_XML(Expr) // base END_NODE_XML NODE_XML(InitListExpr, "InitListExpr") // struct foo x = { expr1, { expr2, expr3 } }; ATTRIBUTE_FILE_LOCATION_XML TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_OPT_XML(getInitializedFieldInUnion(), "field_ref") // if a union is initialized, this refers to the initialized union field id + ATTRIBUTE_OPT_XML(getInitializedFieldInUnion(), "field_ref") // if a union is initialized, this refers to the initialized union field id ATTRIBUTE_XML(getNumInits(), "num_inits") // unsigned SUB_NODE_SEQUENCE_XML(Expr) // expr1..exprN END_NODE_XML @@ -412,8 +412,8 @@ END_NODE_XML NODE_XML(TypesCompatibleExpr, "TypesCompatibleExpr") // GNU builtin-in function __builtin_types_compatible_p ATTRIBUTE_FILE_LOCATION_XML TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getArgType1(), "type1_ref") // id of type1 - ATTRIBUTE_XML(getArgType2(), "type2_ref") // id of type2 + ATTRIBUTE_XML(getArgType1(), "type1_ref") // id of type1 + ATTRIBUTE_XML(getArgType2(), "type2_ref") // id of type2 END_NODE_XML NODE_XML(ChooseExpr, "ChooseExpr") // GNU builtin-in function __builtin_choose_expr(expr1, expr2, expr3) @@ -495,16 +495,9 @@ NODE_XML(CXXDefaultArgExpr, "CXXDefaultArgExpr") ATTRIBUTE_XML(getParam(), "ref") // id of the parameter declaration (the expression is a subnode of the declaration) END_NODE_XML -NODE_XML(CXXConditionDeclExpr, "CXXConditionDeclExpr") - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_XML(VarDecl) // a CXXConditionDeclExpr owns the declaration -END_NODE_XML - - //===----------------------------------------------------------------------===// #undef NODE_XML -#undef ID_ATTRIBUTE_XML +#undef ID_ATTRIBUTE_XML #undef TYPE_ATTRIBUTE_XML #undef ATTRIBUTE_XML #undef ATTRIBUTE_SPECIAL_XML @@ -513,8 +506,8 @@ END_NODE_XML #undef ATTRIBUTE_ENUM_OPT_XML #undef ATTRIBUTE_FILE_LOCATION_XML #undef ENUM_XML -#undef END_ENUM_XML -#undef END_NODE_XML +#undef END_ENUM_XML +#undef END_NODE_XML #undef SUB_NODE_XML #undef SUB_NODE_SEQUENCE_XML #undef SUB_NODE_OPT_XML diff --git a/include/clang/Frontend/TextDiagnosticBuffer.h b/include/clang/Frontend/TextDiagnosticBuffer.h index 4e907e1..380a1dd 100644 --- a/include/clang/Frontend/TextDiagnosticBuffer.h +++ b/include/clang/Frontend/TextDiagnosticBuffer.h @@ -41,6 +41,10 @@ public: virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, const DiagnosticInfo &Info); + + /// FlushDiagnostics - Flush the buffered diagnostics to an given + /// diagnostic engine. + void FlushDiagnostics(Diagnostic &Diags) const; }; } // end namspace clang diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index c2db4d3..52bf194 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -78,7 +78,7 @@ public: /// with the specified preprocessor managing the lexing process. This lexer /// assumes that the associated file buffer and Preprocessor objects will /// outlive it, so it doesn't take ownership of either of them. - Lexer(FileID FID, Preprocessor &PP); + 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 @@ -89,7 +89,8 @@ public: /// 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. - Lexer(FileID FID, const SourceManager &SM, const LangOptions &Features); + Lexer(FileID FID, const llvm::MemoryBuffer *InputBuffer, + const SourceManager &SM, const LangOptions &Features); /// Create_PragmaLexer: Lexer constructor - Create a new lexer object for /// _Pragma expansion. This has a variety of magic semantics that this method diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 1c0036e..edd34b7 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -329,9 +329,9 @@ public: void EnterMainSourceFile(); /// EnterSourceFile - Add a source file to the top of the include stack and - /// start lexing tokens from it instead of the current buffer. If isMainFile - /// is true, this is the main file for the translation unit. - void EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir); + /// start lexing tokens from it instead of the current buffer. Return true + /// on failure. + bool EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir); /// EnterMacro - Add a Macro to the top of the include stack and start lexing /// tokens from it instead of the current buffer. Args specifies the diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 3d3232b..fc56cc6 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -203,11 +203,15 @@ public: /// this occurs when deriving from "std::vector<T>::allocator_type", where T /// is a template parameter. /// + /// \param ObjectType if we're checking whether an identifier is a type + /// within a C++ member access expression, this will be the type of the + /// /// \returns the type referred to by this identifier, or NULL if the type /// does not name an identifier. virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc, Scope *S, const CXXScopeSpec *SS = 0, - bool isClassName = false) = 0; + bool isClassName = false, + TypeTy *ObjectType = 0) = 0; /// isTagName() - This method is called *for error recovery purposes only* /// to determine if the specified name is a valid tag name ("struct foo"). If @@ -668,6 +672,9 @@ public: return StmtEmpty(); } + virtual void ActOnForEachDeclStmt(DeclGroupPtrTy Decl) { + } + virtual OwningStmtResult ActOnExprStmt(FullExprArg Expr) { return OwningStmtResult(*this, Expr->release()); } @@ -698,14 +705,39 @@ public: return StmtEmpty(); } + /// \brief Parsed an "if" statement. + /// + /// \param IfLoc the location of the "if" keyword. + /// + /// \param CondVal if the "if" condition was parsed as an expression, + /// the expression itself. + /// + /// \param CondVar if the "if" condition was parsed as a condition variable, + /// the condition variable itself. + /// + /// \param ThenVal the "then" statement. + /// + /// \param ElseLoc the location of the "else" keyword. + /// + /// \param ElseVal the "else" statement. virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc, - FullExprArg CondVal, StmtArg ThenVal, + FullExprArg CondVal, + DeclPtrTy CondVar, + StmtArg ThenVal, SourceLocation ElseLoc, StmtArg ElseVal) { return StmtEmpty(); } - virtual OwningStmtResult ActOnStartOfSwitchStmt(ExprArg Cond) { + /// \brief Parsed the start of a "switch" statement. + /// + /// \param Cond if the "switch" condition was parsed as an expression, + /// the expression itself. + /// + /// \param CondVar if the "switch" condition was parsed as a condition + /// variable, the condition variable itself. + virtual OwningStmtResult ActOnStartOfSwitchStmt(FullExprArg Cond, + DeclPtrTy CondVar) { return StmtEmpty(); } @@ -714,8 +746,18 @@ public: return StmtEmpty(); } + /// \brief Parsed a "while" statement. + /// + /// \param Cond if the "while" condition was parsed as an expression, + /// the expression itself. + /// + /// \param CondVar if the "while" condition was parsed as a condition + /// variable, the condition variable itself. + /// + /// \param Body the body of the "while" loop. virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc, - FullExprArg Cond, StmtArg Body) { + FullExprArg Cond, DeclPtrTy CondVar, + StmtArg Body) { return StmtEmpty(); } virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body, @@ -725,13 +767,36 @@ public: SourceLocation CondRParen) { return StmtEmpty(); } + + /// \brief Parsed a "for" statement. + /// + /// \param ForLoc the location of the "for" keyword. + /// + /// \param LParenLoc the location of the left parentheses. + /// + /// \param First the statement used to initialize the for loop. + /// + /// \param Second the condition to be checked during each iteration, if + /// that condition was parsed as an expression. + /// + /// \param SecondArg the condition variable to be checked during each + /// iterator, if that condition was parsed as a variable declaration. + /// + /// \param Third the expression that will be evaluated to "increment" any + /// values prior to the next iteration. + /// + /// \param RParenLoc the location of the right parentheses. + /// + /// \param Body the body of the "body" loop. virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, - StmtArg First, ExprArg Second, - ExprArg Third, SourceLocation RParenLoc, + StmtArg First, FullExprArg Second, + DeclPtrTy SecondVar, FullExprArg Third, + SourceLocation RParenLoc, StmtArg Body) { return StmtEmpty(); } + virtual OwningStmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc, SourceLocation LParenLoc, StmtArg First, ExprArg Second, @@ -852,23 +917,12 @@ public: /// \brief The parser is entering a new expression evaluation context. /// /// \param NewContext is the new expression evaluation context. - /// - /// \returns the previous expression evaluation context. - virtual ExpressionEvaluationContext - PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) { - return PotentiallyEvaluated; - } + virtual void + PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) { } - /// \brief The parser is existing an expression evaluation context. - /// - /// \param OldContext the expression evaluation context that the parser is - /// leaving. - /// - /// \param NewContext the expression evaluation context that the parser is - /// returning to. + /// \brief The parser is exiting an expression evaluation context. virtual void - PopExpressionEvaluationContext(ExpressionEvaluationContext OldContext, - ExpressionEvaluationContext NewContext) { } + PopExpressionEvaluationContext() { } // Primary Expressions. @@ -927,9 +981,10 @@ public: return move(Val); // Default impl returns operand. } - virtual OwningExprResult ActOnParenListExpr(SourceLocation L, + virtual OwningExprResult ActOnParenOrParenListExpr(SourceLocation L, SourceLocation R, - MultiExprArg Val) { + MultiExprArg Val, + TypeTy *TypeOfCast=0) { return ExprEmpty(); } @@ -1041,6 +1096,10 @@ public: return ExprEmpty(); } + virtual bool TypeIsVectorType(TypeTy *Ty) { + return false; + } + virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, tok::TokenKind Kind, ExprArg LHS, ExprArg RHS) { @@ -1371,15 +1430,22 @@ public: return ExprEmpty(); } - /// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a - /// C++ if/switch/while/for statement. - /// e.g: "if (int x = f()) {...}" - virtual OwningExprResult ActOnCXXConditionDeclarationExpr(Scope *S, - SourceLocation StartLoc, - Declarator &D, - SourceLocation EqualLoc, - ExprArg AssignExprVal) { - return ExprEmpty(); + /// \brief Parsed a condition declaration in a C++ if, switch, or while + /// statement. + /// + /// This callback will be invoked after parsing the declaration of "x" in + /// + /// \code + /// if (int x = f()) { + /// // ... + /// } + /// \endcode + /// + /// \param S the scope of the if, switch, or while statement. + /// + /// \param D the declarator that that describes the variable being declared. + virtual DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D) { + return DeclResult(); } /// ActOnCXXNew - Parsed a C++ 'new' expression. UseGlobal is true if the @@ -1470,6 +1536,7 @@ public: MultiTemplateParamsArg TemplateParameterLists, ExprTy *BitfieldWidth, ExprTy *Init, + bool IsDefinition, bool Deleted = false) { return DeclPtrTy(); } @@ -1678,10 +1745,14 @@ public: /// \param ObjectType if this dependent template name occurs in the /// context of a member access expression, the type of the object being /// accessed. + /// + /// \param EnteringContext whether we are entering the context of this + /// template. virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc, const CXXScopeSpec &SS, UnqualifiedId &Name, - TypeTy *ObjectType) { + TypeTy *ObjectType, + bool EnteringContext) { return TemplateTy(); } @@ -2515,7 +2586,8 @@ public: /// does not name an identifier. virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc, Scope *S, const CXXScopeSpec *SS, - bool isClassName = false); + bool isClassName = false, + TypeTy *ObjectType = 0); /// isCurrentClassName - Always returns false, because MinimalAction /// does not support C++ classes with constructors. @@ -2578,21 +2650,15 @@ class EnterExpressionEvaluationContext { /// \brief The action object. Action &Actions; - /// \brief The previous expression evaluation context. - Action::ExpressionEvaluationContext PrevContext; - - /// \brief The current expression evaluation context. - Action::ExpressionEvaluationContext CurContext; - public: EnterExpressionEvaluationContext(Action &Actions, Action::ExpressionEvaluationContext NewContext) - : Actions(Actions), CurContext(NewContext) { - PrevContext = Actions.PushExpressionEvaluationContext(NewContext); + : Actions(Actions) { + Actions.PushExpressionEvaluationContext(NewContext); } ~EnterExpressionEvaluationContext() { - Actions.PopExpressionEvaluationContext(CurContext, PrevContext); + Actions.PopExpressionEvaluationContext(); } }; diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h index 81bb300..ecaa6ae 100644 --- a/include/clang/Parse/AttributeList.h +++ b/include/clang/Parse/AttributeList.h @@ -33,19 +33,22 @@ namespace clang { class AttributeList { IdentifierInfo *AttrName; SourceLocation AttrLoc; + IdentifierInfo *ScopeName; + SourceLocation ScopeLoc; IdentifierInfo *ParmName; SourceLocation ParmLoc; ActionBase::ExprTy **Args; unsigned NumArgs; AttributeList *Next; - bool DeclspecAttribute; + bool DeclspecAttribute, CXX0XAttribute; AttributeList(const AttributeList &); // DO NOT IMPLEMENT void operator=(const AttributeList &); // DO NOT IMPLEMENT public: AttributeList(IdentifierInfo *AttrName, SourceLocation AttrLoc, + IdentifierInfo *ScopeName, SourceLocation ScopeLoc, IdentifierInfo *ParmName, SourceLocation ParmLoc, ActionBase::ExprTy **args, unsigned numargs, - AttributeList *Next, bool declspec = false); + AttributeList *Next, bool declspec = false, bool cxx0x = false); ~AttributeList(); enum Kind { // Please keep this list alphabetized. @@ -56,7 +59,9 @@ public: AT_always_inline, AT_analyzer_noreturn, AT_annotate, + AT_base_check, AT_blocks, + AT_carries_dependency, AT_cdecl, AT_cleanup, AT_const, @@ -67,9 +72,11 @@ public: AT_dllimport, AT_ext_vector_type, AT_fastcall, + AT_final, AT_format, AT_format_arg, AT_gnu_inline, + AT_hiding, AT_malloc, AT_mode, AT_nodebug, @@ -80,6 +87,7 @@ public: AT_nothrow, AT_nsobject, AT_objc_exception, + AT_override, AT_cf_returns_retained, // Clang-specific. AT_ns_returns_retained, // Clang-specific. AT_objc_gc, @@ -106,8 +114,15 @@ public: IdentifierInfo *getName() const { return AttrName; } SourceLocation getLoc() const { return AttrLoc; } + + bool hasScope() const { return ScopeName; } + IdentifierInfo *getScopeName() const { return ScopeName; } + SourceLocation getScopeLoc() const { return ScopeLoc; } + IdentifierInfo *getParameterName() const { return ParmName; } + bool isDeclspecAttribute() const { return DeclspecAttribute; } + bool isCXX0XAttribute() const { return CXX0XAttribute; } Kind getKind() const { return getKind(getName()); } static Kind getKind(const IdentifierInfo *Name); @@ -181,6 +196,22 @@ inline AttributeList* addAttributeLists (AttributeList *Left, return Left; } +/// CXX0XAttributeList - A wrapper around a C++0x attribute list. +/// Stores, in addition to the list proper, whether or not an actual list was +/// (as opposed to an empty list, which may be ill-formed in some places) and +/// the source range of the list. +struct CXX0XAttributeList { + AttributeList *AttrList; + SourceRange Range; + bool HasAttr; + CXX0XAttributeList (AttributeList *attrList, SourceRange range, bool hasAttr) + : AttrList(attrList), Range(range), HasAttr (hasAttr) { + } + CXX0XAttributeList () + : AttrList(0), Range(), HasAttr(false) { + } +}; + } // end namespace clang #endif diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index 7e7d0b3..fe899b3 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -484,6 +484,8 @@ public: IK_OperatorFunctionId, /// \brief A conversion function name, e.g., operator int. IK_ConversionFunctionId, + /// \brief A user-defined literal name, e.g., operator "" _i. + IK_LiteralOperatorId, /// \brief A constructor name. IK_ConstructorName, /// \brief A destructor name. @@ -495,7 +497,8 @@ public: /// \brief Anonymous union that holds extra data associated with the /// parsed unqualified-id. union { - /// \brief When Kind == IK_Identifier, the parsed identifier. + /// \brief When Kind == IK_Identifier, the parsed identifier, or when Kind + /// == IK_UserLiteralId, the identifier suffix. IdentifierInfo *Identifier; /// \brief When Kind == IK_OperatorFunctionId, the overloaded operator @@ -607,6 +610,22 @@ public: EndLocation = EndLoc; ConversionFunctionId = Ty; } + + /// \brief Specific that this unqualified-id was parsed as a + /// literal-operator-id. + /// + /// \param Id the parsed identifier. + /// + /// \param OpLoc the location of the 'operator' keyword. + /// + /// \param IdLoc the location of the identifier. + void setLiteralOperatorId(const IdentifierInfo *Id, SourceLocation OpLoc, + SourceLocation IdLoc) { + Kind = IK_LiteralOperatorId; + Identifier = const_cast<IdentifierInfo *>(Id); + StartLocation = OpLoc; + EndLocation = IdLoc; + } /// \brief Specify that this unqualified-id was parsed as a constructor name. /// diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index f7cccca..81a80eb 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -24,6 +24,7 @@ namespace clang { class AttributeList; + struct CXX0XAttributeList; class PragmaHandler; class Scope; class DiagnosticBuilder; @@ -753,10 +754,10 @@ private: //===--------------------------------------------------------------------===// // C99 6.9: External Definitions. - DeclGroupPtrTy ParseExternalDeclaration(); + DeclGroupPtrTy ParseExternalDeclaration(CXX0XAttributeList Attr); bool isDeclarationAfterDeclarator(); bool isStartOfFunctionDefinition(); - DeclGroupPtrTy ParseDeclarationOrFunctionDefinition( + DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(AttributeList *Attr, AccessSpecifier AS = AS_none); DeclPtrTy ParseFunctionDefinition(ParsingDeclarator &D, @@ -832,10 +833,10 @@ private: OwningExprResult ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand, bool &NotCastExpr, - bool parseParenAsExprList); + TypeTy *TypeOfCast); OwningExprResult ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand = false, - bool parseParenAsExprList = false); + TypeTy *TypeOfCast = 0); OwningExprResult ParsePostfixExpressionSuffix(OwningExprResult LHS); OwningExprResult ParseSizeofAlignofExpression(); OwningExprResult ParseBuiltinPrimaryExpression(); @@ -865,7 +866,7 @@ private: }; OwningExprResult ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, - bool parseAsExprList, + TypeTy *TypeOfCast, TypeTy *&CastTy, SourceLocation &RParenLoc); @@ -933,8 +934,8 @@ private: SourceLocation Start); //===--------------------------------------------------------------------===// - // C++ if/switch/while/for condition expression. - OwningExprResult ParseCXXCondition(); + // C++ if/switch/while condition expression. + bool ParseCXXCondition(OwningExprResult &ExprResult, DeclPtrTy &DeclResult); //===--------------------------------------------------------------------===// // C++ types @@ -994,24 +995,23 @@ private: return ParseStatementOrDeclaration(true); } OwningStmtResult ParseStatementOrDeclaration(bool OnlyStatement = false); - OwningStmtResult ParseLabeledStatement(); - OwningStmtResult ParseCaseStatement(); - OwningStmtResult ParseDefaultStatement(); - OwningStmtResult ParseCompoundStatement(bool isStmtExpr = false); + OwningStmtResult ParseLabeledStatement(AttributeList *Attr); + OwningStmtResult ParseCaseStatement(AttributeList *Attr); + OwningStmtResult ParseDefaultStatement(AttributeList *Attr); + OwningStmtResult ParseCompoundStatement(AttributeList *Attr, + bool isStmtExpr = false); OwningStmtResult ParseCompoundStatementBody(bool isStmtExpr = false); - bool ParseParenExprOrCondition(OwningExprResult &CondExp, - bool OnlyAllowCondition = false, - SourceLocation *LParenLoc = 0, - SourceLocation *RParenLoc = 0); - OwningStmtResult ParseIfStatement(); - OwningStmtResult ParseSwitchStatement(); - OwningStmtResult ParseWhileStatement(); - OwningStmtResult ParseDoStatement(); - OwningStmtResult ParseForStatement(); - OwningStmtResult ParseGotoStatement(); - OwningStmtResult ParseContinueStatement(); - OwningStmtResult ParseBreakStatement(); - OwningStmtResult ParseReturnStatement(); + bool ParseParenExprOrCondition(OwningExprResult &ExprResult, + DeclPtrTy &DeclResult); + OwningStmtResult ParseIfStatement(AttributeList *Attr); + OwningStmtResult ParseSwitchStatement(AttributeList *Attr); + OwningStmtResult ParseWhileStatement(AttributeList *Attr); + OwningStmtResult ParseDoStatement(AttributeList *Attr); + OwningStmtResult ParseForStatement(AttributeList *Attr); + OwningStmtResult ParseGotoStatement(AttributeList *Attr); + OwningStmtResult ParseContinueStatement(AttributeList *Attr); + OwningStmtResult ParseBreakStatement(AttributeList *Attr); + OwningStmtResult ParseReturnStatement(AttributeList *Attr); OwningStmtResult ParseAsmStatement(bool &msAsm); OwningStmtResult FuzzyParseMicrosoftAsmStatement(); bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names, @@ -1021,7 +1021,7 @@ private: //===--------------------------------------------------------------------===// // C++ 6: Statements and Blocks - OwningStmtResult ParseCXXTryBlock(); + OwningStmtResult ParseCXXTryBlock(AttributeList *Attr); OwningStmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc); OwningStmtResult ParseCXXCatchBlock(); @@ -1045,9 +1045,11 @@ private: DSC_class // class context, enables 'friend' }; - DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd); + DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd, + CXX0XAttributeList Attr); DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context, - SourceLocation &DeclEnd); + SourceLocation &DeclEnd, + AttributeList *Attr); DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context, bool AllowFunctionDefinitions, SourceLocation *DeclEnd = 0); @@ -1217,11 +1219,14 @@ private: void ParseBlockId(); // EndLoc, if non-NULL, is filled with the location of the last token of // the attribute list. - AttributeList *ParseAttributes(SourceLocation *EndLoc = 0); + CXX0XAttributeList ParseCXX0XAttributes(SourceLocation *EndLoc = 0); + AttributeList *ParseGNUAttributes(SourceLocation *EndLoc = 0); AttributeList *ParseMicrosoftDeclSpec(AttributeList* CurrAttr = 0); AttributeList *ParseMicrosoftTypeAttributes(AttributeList* CurrAttr = 0); void ParseTypeofSpecifier(DeclSpec &DS); void ParseDecltypeSpecifier(DeclSpec &DS); + + OwningExprResult ParseCXX0XAlignArgument(SourceLocation Start); /// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to /// enter a new C++ declarator scope and exit it when the function is @@ -1265,7 +1270,8 @@ private: typedef void (Parser::*DirectDeclParseFunction)(Declarator&); void ParseDeclaratorInternal(Declarator &D, DirectDeclParseFunction DirectDeclParser); - void ParseTypeQualifierListOpt(DeclSpec &DS, bool AttributesAllowed = true); + void ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed = true, + bool CXX0XAttributesAllowed = true); void ParseDirectDeclarator(Declarator &D); void ParseParenDeclarator(Declarator &D); void ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, @@ -1278,12 +1284,17 @@ private: //===--------------------------------------------------------------------===// // C++ 7: Declarations [dcl.dcl] + bool isCXX0XAttributeSpecifier(bool FullLookahead = false, + tok::TokenKind *After = 0); + DeclPtrTy ParseNamespace(unsigned Context, SourceLocation &DeclEnd); DeclPtrTy ParseLinkage(unsigned Context); DeclPtrTy ParseUsingDirectiveOrDeclaration(unsigned Context, - SourceLocation &DeclEnd); + SourceLocation &DeclEnd, + CXX0XAttributeList Attrs); DeclPtrTy ParseUsingDirective(unsigned Context, SourceLocation UsingLoc, - SourceLocation &DeclEnd); + SourceLocation &DeclEnd, + AttributeList *Attr); DeclPtrTy ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc, SourceLocation &DeclEnd, AccessSpecifier AS = AS_none); @@ -1353,6 +1364,7 @@ private: SourceLocation &RAngleLoc); bool ParseTemplateParameterList(unsigned Depth, TemplateParameterList &TemplateParams); + bool isStartOfTemplateTypeParameter(); DeclPtrTy ParseTemplateParameter(unsigned Depth, unsigned Position); DeclPtrTy ParseTypeParameter(unsigned Depth, unsigned Position); DeclPtrTy ParseTemplateTemplateParameter(unsigned Depth, unsigned Position); diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index ed74761..84c179f 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -209,7 +209,8 @@ public: void Serialize(llvm::raw_ostream &OS) const; /// \brief Deserialize a code-completion string from the given string. - static CodeCompletionString *Deserialize(llvm::StringRef &Str); + static CodeCompletionString *Deserialize(const char *&Str, + const char *StrEnd); }; llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, @@ -221,6 +222,10 @@ class CodeCompleteConsumer { protected: /// \brief Whether to include macros in the code-completion results. bool IncludeMacros; + + /// \brief Whether the output format for the code-completion consumer is + /// binary. + bool OutputIsBinary; public: /// \brief Captures a result of code completion. @@ -394,17 +399,20 @@ public: Sema &S) const; }; - CodeCompleteConsumer() : IncludeMacros(false) { } + CodeCompleteConsumer() : IncludeMacros(false), OutputIsBinary(false) { } - explicit CodeCompleteConsumer(bool IncludeMacros) - : IncludeMacros(IncludeMacros) { } + CodeCompleteConsumer(bool IncludeMacros, bool OutputIsBinary) + : IncludeMacros(IncludeMacros), OutputIsBinary(OutputIsBinary) { } /// \brief Whether the code-completion consumer wants to see macros. bool includeMacros() const { return IncludeMacros; } + + /// \brief Determine whether the output of this consumer is binary. + bool isOutputBinary() const { return OutputIsBinary; } /// \brief Deregisters and destroys this code-completion consumer. virtual ~CodeCompleteConsumer(); - + /// \name Code-completion callbacks //@{ /// \brief Process the finalized code-completion results. @@ -436,7 +444,7 @@ public: /// results to the given raw output stream. PrintingCodeCompleteConsumer(bool IncludeMacros, llvm::raw_ostream &OS) - : CodeCompleteConsumer(IncludeMacros), OS(OS) { } + : CodeCompleteConsumer(IncludeMacros, false), OS(OS) { } /// \brief Prints the finalized code-completion results. virtual void ProcessCodeCompleteResults(Sema &S, Result *Results, @@ -458,7 +466,7 @@ public: /// results to the given raw output stream in a format readable to the CIndex /// library. CIndexCodeCompleteConsumer(bool IncludeMacros, llvm::raw_ostream &OS) - : CodeCompleteConsumer(IncludeMacros), OS(OS) { } + : CodeCompleteConsumer(IncludeMacros, true), OS(OS) { } /// \brief Prints the finalized code-completion results. virtual void ProcessCodeCompleteResults(Sema &S, Result *Results, |