diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-01-01 10:34:51 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-01-01 10:34:51 +0000 |
commit | bb1e3bc1e0be2b8f891db46457a8943451bf4d8b (patch) | |
tree | 1e68501209c9133fbda8d45171e59f8d6f12dd55 /include | |
parent | 77212133072dc40f070a280af8217032f55a9eb4 (diff) | |
download | FreeBSD-src-bb1e3bc1e0be2b8f891db46457a8943451bf4d8b.zip FreeBSD-src-bb1e3bc1e0be2b8f891db46457a8943451bf4d8b.tar.gz |
Updaet clang to 92395.
Diffstat (limited to 'include')
68 files changed, 1142 insertions, 509 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 4e76809..03b4df1 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -17,6 +17,7 @@ #define CLANG_C_INDEX_H #include <sys/stat.h> +#include <time.h> #ifdef __cplusplus extern "C" { @@ -555,23 +556,16 @@ enum CXCompletionChunkKind { /** * \brief A comma separator (','). */ - CXCompletionChunk_Comma + CXCompletionChunk_Comma, + /** + * \brief Text that specifies the result type of a given result. + * + * This special kind of informative chunk is not meant to be inserted into + * the text buffer. Rather, it is meant to illustrate the type that an + * expression using the given completion string would have. + */ + CXCompletionChunk_ResultType }; - -/** - * \brief Callback function that receives a single code-completion result. - * - * This callback will be invoked by \c clang_codeComplete() for each - * code-completion result. - * - * \param completion_result a pointer to the current code-completion result, - * providing one possible completion. The pointer itself is only valid - * during the execution of the completion callback. - * - * \param client_data the client data provided to \c clang_codeComplete(). - */ -typedef void (*CXCompletionIterator)(CXCompletionResult *completion_result, - CXClientData client_data); /** * \brief Determine the kind of a particular chunk within a completion string. @@ -623,6 +617,26 @@ CINDEX_LINKAGE unsigned clang_getNumCompletionChunks(CXCompletionString completion_string); /** + * \brief Contains the results of code-completion. + * + * This data structure contains the results of code completion, as + * produced by \c clang_codeComplete. Its contents must be freed by + * \c clang_disposeCodeCompleteResults. + */ +typedef struct { + /** + * \brief The code-completion results. + */ + CXCompletionResult *Results; + + /** + * \brief The number of code-completion results stored in the + * \c Results array. + */ + unsigned NumResults; +} CXCodeCompleteResults; + +/** * \brief Perform code completion at a given location in a source file. * * This function performs code completion at a particular file, line, and @@ -634,7 +648,7 @@ clang_getNumCompletionChunks(CXCompletionString completion_string); * to the parser, which recognizes this token and determines, based on the * current location in the C/Objective-C/C++ grammar and the state of * semantic analysis, what completions to provide. These completions are - * enumerated through a callback interface to the client. + * returned via a new \c CXCodeCompleteResults structure. * * Code completion itself is meant to be triggered by the client when the * user types punctuation characters or whitespace, at which point the @@ -649,7 +663,7 @@ clang_getNumCompletionChunks(CXCompletionString completion_string); * the ">" (e.g., pointing at the "g") to this code-completion hook. Then, the * client can filter the results based on the current token text ("get"), only * showing those results that start with "get". The intent of this interface - * is to separate the relatively high-latency acquisition of code-competion + * is to separate the relatively high-latency acquisition of code-completion * results from the filtering of results on a per-character basis, which must * have a lower latency. * @@ -690,24 +704,27 @@ clang_getNumCompletionChunks(CXCompletionString completion_string); * Note that the column should point just after the syntactic construct that * initiated code completion, and not in the middle of a lexical token. * - * \param completion_iterator a callback function that will receive - * code-completion results. - * - * \param client_data client-specific data that will be passed back via the - * code-completion callback function. + * \returns if successful, a new CXCodeCompleteResults structure + * containing code-completion results, which should eventually be + * freed with \c clang_disposeCodeCompleteResults(). If code + * completion fails, returns NULL. + */ +CINDEX_LINKAGE +CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx, + const char *source_filename, + int num_command_line_args, + const char **command_line_args, + unsigned num_unsaved_files, + struct CXUnsavedFile *unsaved_files, + const char *complete_filename, + unsigned complete_line, + unsigned complete_column); + +/** + * \brief Free the given set of code-completion results. */ -CINDEX_LINKAGE void clang_codeComplete(CXIndex CIdx, - const char *source_filename, - int num_command_line_args, - const char **command_line_args, - unsigned num_unsaved_files, - struct CXUnsavedFile *unsaved_files, - const char *complete_filename, - unsigned complete_line, - unsigned complete_column, - CXCompletionIterator completion_iterator, - CXClientData client_data); - +CINDEX_LINKAGE +void clang_disposeCodeCompleteResults(CXCodeCompleteResults *Results); #ifdef __cplusplus } diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 3fc5aab..bcab46d 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -38,6 +38,7 @@ namespace clang { class FileManager; class ASTRecordLayout; class BlockExpr; + class CharUnits; class Expr; class ExternalASTSource; class IdentifierTable; @@ -114,9 +115,6 @@ class ASTContext { /// \brief Mapping from ObjCContainers to their ObjCImplementations. llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls; - llvm::DenseMap<unsigned, FixedWidthIntType*> SignedFixedWidthIntTypes; - llvm::DenseMap<unsigned, FixedWidthIntType*> UnsignedFixedWidthIntTypes; - /// BuiltinVaListType - built-in va list type. /// This is initially null and set by Sema::LazilyCreateBuiltin when /// a builtin that takes a valist is encountered. @@ -724,8 +722,6 @@ public: void setBuiltinVaListType(QualType T); QualType getBuiltinVaListType() const { return BuiltinVaListType; } - QualType getFixedWidthIntType(unsigned Width, bool Signed); - /// getCVRQualifiedType - Returns a type with additional const, /// volatile, or restrict qualifiers. QualType getCVRQualifiedType(QualType T, unsigned CVR) { @@ -812,19 +808,15 @@ public: return getTypeInfo(T).first; } - /// getByteWidth - Return the size of a byte, in bits - uint64_t getByteSize() { + /// getCharWidth - Return the size of the character type, in bits + uint64_t getCharWidth() { return getTypeSize(CharTy); } - /// getTypeSizeInBytes - Return the size of the specified type, in bytes. + /// getTypeSizeInChars - Return the size of the specified type, in characters. /// 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(); - } + CharUnits getTypeSizeInChars(QualType T); + CharUnits getTypeSizeInChars(const Type *T); /// getTypeAlign - Return the ABI-specified alignment of a type, in bits. /// This method does not work on incomplete types. @@ -906,12 +898,29 @@ public: return getCanonicalType(T1) == getCanonicalType(T2); } + /// \brief Returns this type as a completely-unqualified array type, capturing + /// the qualifiers in Quals. This only operates on canonical types in order + /// to ensure the ArrayType doesn't itself have qualifiers. + /// + /// \param T is the canonicalized QualType, which may be an ArrayType + /// + /// \param Quals will receive the full set of qualifiers that were + /// applied to the element type of the array. + /// + /// \returns if this is an array type, the completely unqualified array type + /// that corresponds to it. Otherwise, returns this->getUnqualifiedType(). + QualType getUnqualifiedArrayType(QualType T, Qualifiers &Quals); + /// \brief Determine whether the given types are equivalent after /// cvr-qualifiers have been removed. bool hasSameUnqualifiedType(QualType T1, QualType T2) { CanQualType CT1 = getCanonicalType(T1); CanQualType CT2 = getCanonicalType(T2); - return CT1.getUnqualifiedType() == CT2.getUnqualifiedType(); + + Qualifiers Quals; + QualType UnqualT1 = getUnqualifiedArrayType(CT1, Quals); + QualType UnqualT2 = getUnqualifiedArrayType(CT2, Quals); + return UnqualT1 == UnqualT2; } /// \brief Retrieves the "canonical" declaration of @@ -1251,7 +1260,8 @@ inline void *operator new[](size_t Bytes, clang::ASTContext& C, /// invoking it directly; see the new[] operator for more details. This operator /// is called implicitly by the compiler if a placement new[] expression using /// the ASTContext throws in the object constructor. -inline void operator delete[](void *Ptr, clang::ASTContext &C) throw () { +inline void operator delete[](void *Ptr, clang::ASTContext &C, size_t) + throw () { C.Deallocate(Ptr); } diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index af8d236..93e41d3 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -559,7 +559,7 @@ template<> struct CanProxyAdaptor<FunctionProtoType> : public CanProxyBase<FunctionProtoType> { LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumArgs); + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumArgs) CanQualType getArgType(unsigned i) const { return CanQualType::CreateUnsafe(this->getTypePtr()->getArgType(i)); } diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h new file mode 100644 index 0000000..7b2833c --- /dev/null +++ b/include/clang/AST/CharUnits.h @@ -0,0 +1,149 @@ +//===--- CharUnits.h - Character units for sizes and offsets ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the CharUnits class +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_CHARUNITS_H +#define LLVM_CLANG_AST_CHARUNITS_H + +#include "llvm/System/DataTypes.h" + +namespace clang { + + /// CharUnits - This is an opaque type for sizes expressed in character units. + /// Instances of this type represent a quantity as a multiple of the size + /// of the standard C type, char, on the target architecture. As an opaque + /// type, CharUnits protects you from accidentally combining operations on + /// quantities in bit units and character units. + /// + /// It should be noted that characters and bytes are distinct concepts. Bytes + /// refer to addressable units of data storage on the target machine, and + /// characters are members of a set of elements used for the organization, + /// control, or representation of data. According to C99, bytes are allowed + /// to exceed characters in size, although currently, clang only supports + /// architectures where the two are the same size. + /// + /// For portability, never assume that a target character is 8 bits wide. Use + /// CharUnit values whereever you calculate sizes, offsets, or alignments + /// in character units. + class CharUnits { + public: + typedef int64_t RawType; + + private: + RawType Quantity; + + explicit CharUnits(RawType C) : Quantity(C) {} + + public: + + /// CharUnits - A default constructor. + CharUnits() : Quantity(0) {} + + /// Zero - Construct a CharUnits quantity of zero. + static CharUnits Zero() { + return CharUnits(0); + } + + /// One - Construct a CharUnits quantity of one. + static CharUnits One() { + return CharUnits(1); + } + + /// fromRaw - Construct a CharUnits quantity from a raw integer type. + static CharUnits fromRaw(RawType Quantity) { + return CharUnits(Quantity); + } + + // Compound assignment. + CharUnits& operator+= (const CharUnits &Other) { + Quantity += Other.Quantity; + return *this; + } + CharUnits& operator-= (const CharUnits &Other) { + Quantity -= Other.Quantity; + return *this; + } + + // Comparison operators. + bool operator== (const CharUnits &Other) const { + return Quantity == Other.Quantity; + } + bool operator!= (const CharUnits &Other) const { + return Quantity != Other.Quantity; + } + + // Relational operators. + bool operator< (const CharUnits &Other) const { + return Quantity < Other.Quantity; + } + bool operator<= (const CharUnits &Other) const { + return Quantity <= Other.Quantity; + } + bool operator> (const CharUnits &Other) const { + return Quantity > Other.Quantity; + } + bool operator>= (const CharUnits &Other) const { + return Quantity >= Other.Quantity; + } + + // Other predicates. + + /// isZero - Test whether the quantity equals zero. + bool isZero() const { return Quantity == 0; } + + /// isOne - Test whether the quantity equals one. + bool isOne() const { return Quantity == 1; } + + /// isPositive - Test whether the quanity is greater than zero. + bool isPositive() const { return Quantity > 0; } + + /// isNegative - Test whether the quantity is less than zero. + bool isNegative() const { return Quantity < 0; } + + // Arithmetic operators. + CharUnits operator* (RawType N) const { + return CharUnits(Quantity * N); + } + CharUnits operator/ (RawType N) const { + return CharUnits(Quantity / N); + } + RawType operator/ (const CharUnits &Other) const { + return Quantity / Other.Quantity; + } + CharUnits operator% (RawType N) const { + return CharUnits(Quantity % N); + } + RawType operator% (const CharUnits &Other) const { + return Quantity % Other.Quantity; + } + CharUnits operator+ (const CharUnits &Other) const { + return CharUnits(Quantity + Other.Quantity); + } + CharUnits operator- (const CharUnits &Other) const { + return CharUnits(Quantity - Other.Quantity); + } + + // Conversions. + + /// getRaw - Get the raw integer representation of this quantity. + RawType getRaw() const { return Quantity; } + + + }; // class CharUnit +} // namespace clang + +inline clang::CharUnits operator* (clang::CharUnits::RawType Scale, + const clang::CharUnits &CU) { + return CU * Scale; +} + +#endif // LLVM_CLANG_AST_CHARUNITS_H diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index ff2b302..d0d94aa 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -21,6 +21,7 @@ #include "clang/AST/ExternalASTSource.h" namespace clang { +class CXXTemporary; class Expr; class FunctionTemplateDecl; class Stmt; @@ -84,13 +85,20 @@ public: class TranslationUnitDecl : public Decl, public DeclContext { ASTContext &Ctx; + /// The (most recently entered) anonymous namespace for this + /// translation unit, if one has been created. + NamespaceDecl *AnonymousNamespace; + explicit TranslationUnitDecl(ASTContext &ctx) : Decl(TranslationUnit, 0, SourceLocation()), DeclContext(TranslationUnit), - Ctx(ctx) {} + Ctx(ctx), AnonymousNamespace(0) {} public: ASTContext &getASTContext() const { return Ctx; } + NamespaceDecl *getAnonymousNamespace() const { return AnonymousNamespace; } + void setAnonymousNamespace(NamespaceDecl *D) { AnonymousNamespace = D; } + static TranslationUnitDecl *Create(ASTContext &C); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == TranslationUnit; } @@ -198,6 +206,20 @@ public: /// \brief Determine whether this declaration has linkage. bool hasLinkage() const; + /// \brief Determine whether this declaration is a C++ class member. + bool isCXXClassMember() const { + const DeclContext *DC = getDeclContext(); + + // C++0x [class.mem]p1: + // The enumerators of an unscoped enumeration defined in + // the class are members of the class. + // FIXME: support C++0x scoped enumerations. + if (isa<EnumDecl>(DC)) + DC = DC->getParent(); + + return DC->isRecord(); + } + /// \brief Describes the different kinds of linkage /// (C++ [basic.link], C99 6.2.2) that an entity may have. enum Linkage { @@ -246,10 +268,15 @@ class NamespaceDecl : public NamedDecl, public DeclContext { // OrigNamespace of the first namespace decl points to itself. NamespaceDecl *OrigNamespace, *NextNamespace; + // The (most recently entered) anonymous namespace inside this + // namespace. + NamespaceDecl *AnonymousNamespace; + NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id) : NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace) { OrigNamespace = this; NextNamespace = 0; + AnonymousNamespace = 0; } public: static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, @@ -277,6 +304,16 @@ public: } void setOriginalNamespace(NamespaceDecl *ND) { OrigNamespace = ND; } + NamespaceDecl *getAnonymousNamespace() const { + return AnonymousNamespace; + } + + void setAnonymousNamespace(NamespaceDecl *D) { + assert(D->isAnonymousNamespace()); + assert(D->getParent() == this); + AnonymousNamespace = D; + } + virtual NamespaceDecl *getCanonicalDecl() { return OrigNamespace; } const NamespaceDecl *getCanonicalDecl() const { return OrigNamespace; } @@ -769,14 +806,6 @@ class ParmVarDecl : public VarDecl { /// in, inout, etc. unsigned objcDeclQualifier : 6; - /// \brief Retrieves the fake "value" of an unparsed - static Expr *getUnparsedDefaultArgValue() { - uintptr_t Value = (uintptr_t)-1; - // Mask off the low bits - Value &= ~(uintptr_t)0x07; - return reinterpret_cast<Expr*> (Value); - } - protected: ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, @@ -798,22 +827,21 @@ public: objcDeclQualifier = QTVal; } + Expr *getDefaultArg(); const Expr *getDefaultArg() const { - assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!"); - assert(!hasUninstantiatedDefaultArg() && - "Default argument is not yet instantiated!"); - return getInit(); - } - Expr *getDefaultArg() { - assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!"); - assert(!hasUninstantiatedDefaultArg() && - "Default argument is not yet instantiated!"); - return getInit(); + return const_cast<ParmVarDecl *>(this)->getDefaultArg(); } + void setDefaultArg(Expr *defarg) { Init = reinterpret_cast<Stmt *>(defarg); } + unsigned getNumDefaultArgTemporaries() const; + CXXTemporary *getDefaultArgTemporary(unsigned i); + const CXXTemporary *getDefaultArgTemporary(unsigned i) const { + return const_cast<ParmVarDecl *>(this)->getDefaultArgTemporary(i); + } + /// \brief Retrieve the source range that covers the entire default /// argument. SourceRange getDefaultArgRange() const; @@ -1152,7 +1180,7 @@ public: /// represents an C++ overloaded operator, e.g., "operator+". bool isOverloadedOperator() const { return getOverloadedOperator() != OO_None; - }; + } OverloadedOperatorKind getOverloadedOperator() const; @@ -1421,7 +1449,7 @@ public: }; -class TypedefDecl : public TypeDecl { +class TypedefDecl : public TypeDecl, public Redeclarable<TypedefDecl> { /// UnderlyingType - This is the type the typedef is set to. TypeSourceInfo *TInfo; @@ -1429,7 +1457,7 @@ class TypedefDecl : public TypeDecl { IdentifierInfo *Id, TypeSourceInfo *TInfo) : TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {} - virtual ~TypedefDecl() {} + virtual ~TypedefDecl(); public: static TypedefDecl *Create(ASTContext &C, DeclContext *DC, @@ -1440,6 +1468,14 @@ public: return TInfo; } + /// Retrieves the canonical declaration of this typedef. + TypedefDecl *getCanonicalDecl() { + return getFirstDeclaration(); + } + const TypedefDecl *getCanonicalDecl() const { + return getFirstDeclaration(); + } + QualType getUnderlyingType() const { return TInfo->getType(); } diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 5507e99..02581c1 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -1178,14 +1178,14 @@ public: /// X(const X&); /// }; /// @endcode - bool isCopyConstructor(ASTContext &Context, unsigned &TypeQuals) const; + bool isCopyConstructor(unsigned &TypeQuals) const; /// isCopyConstructor - Whether this constructor is a copy /// constructor (C++ [class.copy]p2, which can be used to copy the /// class. - bool isCopyConstructor(ASTContext &Context) const { + bool isCopyConstructor() const { unsigned TypeQuals = 0; - return isCopyConstructor(Context, TypeQuals); + return isCopyConstructor(TypeQuals); } /// isConvertingConstructor - Whether this constructor is a @@ -1338,11 +1338,16 @@ private: // Location of the 'friend' specifier. SourceLocation FriendLoc; + // FIXME: Hack to keep track of whether this was a friend function + // template specialization. + bool WasSpecialization; + FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend, SourceLocation FriendL) : Decl(Decl::Friend, DC, L), Friend(Friend), - FriendLoc(FriendL) { + FriendLoc(FriendL), + WasSpecialization(false) { } public: @@ -1369,6 +1374,9 @@ public: return FriendLoc; } + bool wasSpecialization() const { return WasSpecialization; } + void setSpecialization(bool WS) { WasSpecialization = WS; } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == Decl::Friend; diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index fd8c3ef..ba17eb1 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -527,7 +527,7 @@ public: // Location information, modeled after the Stmt API. SourceLocation getLocStart() const { return getLocation(); } // '@'interface SourceLocation getLocEnd() const { return EndLoc; } - void setLocEnd(SourceLocation LE) { EndLoc = LE; }; + void setLocEnd(SourceLocation LE) { EndLoc = LE; } void setClassLoc(SourceLocation Loc) { ClassLoc = Loc; } SourceLocation getClassLoc() const { return ClassLoc; } @@ -707,7 +707,7 @@ public: // Location information, modeled after the Stmt API. SourceLocation getLocStart() const { return getLocation(); } // '@'protocol SourceLocation getLocEnd() const { return EndLoc; } - void setLocEnd(SourceLocation LE) { EndLoc = LE; }; + void setLocEnd(SourceLocation LE) { EndLoc = LE; } static bool classof(const Decl *D) { return D->getKind() == ObjCProtocol; } static bool classof(const ObjCProtocolDecl *D) { return true; } @@ -871,7 +871,7 @@ public: // Location information, modeled after the Stmt API. SourceLocation getLocStart() const { return getLocation(); } // '@'interface SourceLocation getLocEnd() const { return EndLoc; } - void setLocEnd(SourceLocation LE) { EndLoc = LE; }; + void setLocEnd(SourceLocation LE) { EndLoc = LE; } static bool classof(const Decl *D) { return D->getKind() == ObjCCategory; } static bool classof(const ObjCCategoryDecl *D) { return true; } diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 469598f..0cb22df 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -53,14 +53,6 @@ protected: /// (C++ [temp.dep.constexpr]). bool ValueDependent : 1; - // FIXME: Eventually, this constructor should go away and we should - // require every subclass to provide type/value-dependence - // information. - Expr(StmtClass SC, QualType T) - : Stmt(SC), TypeDependent(false), ValueDependent(false) { - setType(T); - } - Expr(StmtClass SC, QualType T, bool TD, bool VD) : Stmt(SC), TypeDependent(TD), ValueDependent(VD) { setType(T); @@ -156,7 +148,8 @@ public: LV_IncompleteVoidType, LV_DuplicateVectorComponents, LV_InvalidExpression, - LV_MemberFunction + LV_MemberFunction, + LV_SubObjCPropertySetting }; isLvalueResult isLvalue(ASTContext &Ctx) const; @@ -185,7 +178,8 @@ public: MLV_NotBlockQualified, MLV_ReadonlyProperty, MLV_NoSetterProperty, - MLV_MemberFunction + MLV_MemberFunction, + MLV_SubObjCPropertySetting }; isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc = 0) const; @@ -607,7 +601,7 @@ public: // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy, // or UnsignedLongLongTy IntegerLiteral(const llvm::APInt &V, QualType type, SourceLocation l) - : Expr(IntegerLiteralClass, type), Value(V), Loc(l) { + : Expr(IntegerLiteralClass, type, false, false), Value(V), Loc(l) { assert(type->isIntegerType() && "Illegal type in IntegerLiteral"); } @@ -641,7 +635,8 @@ class CharacterLiteral : public Expr { public: // type should be IntTy CharacterLiteral(unsigned value, bool iswide, QualType type, SourceLocation l) - : Expr(CharacterLiteralClass, type), Value(value), Loc(l), IsWide(iswide) { + : Expr(CharacterLiteralClass, type, false, false), Value(value), Loc(l), + IsWide(iswide) { } /// \brief Construct an empty character literal. @@ -675,7 +670,8 @@ class FloatingLiteral : public Expr { public: FloatingLiteral(const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L) - : Expr(FloatingLiteralClass, Type), Value(V), IsExact(isexact), Loc(L) {} + : Expr(FloatingLiteralClass, Type, false, false), Value(V), + IsExact(isexact), Loc(L) {} /// \brief Construct an empty floating-point literal. explicit FloatingLiteral(EmptyShell Empty) @@ -716,7 +712,7 @@ class ImaginaryLiteral : public Expr { Stmt *Val; public: ImaginaryLiteral(Expr *val, QualType Ty) - : Expr(ImaginaryLiteralClass, Ty), Val(val) {} + : Expr(ImaginaryLiteralClass, Ty, false, false), Val(val) {} /// \brief Build an empty imaginary literal. explicit ImaginaryLiteral(EmptyShell Empty) @@ -760,7 +756,7 @@ class StringLiteral : public Expr { unsigned NumConcatenated; SourceLocation TokLocs[1]; - StringLiteral(QualType Ty) : Expr(StringLiteralClass, Ty) {} + StringLiteral(QualType Ty) : Expr(StringLiteralClass, Ty, false, false) {} protected: virtual void DoDestroy(ASTContext &C); @@ -1174,6 +1170,11 @@ public: Expr *getCallee() { return cast<Expr>(SubExprs[FN]); } void setCallee(Expr *F) { SubExprs[FN] = F; } + Decl *getCalleeDecl(); + const Decl *getCalleeDecl() const { + return const_cast<CallExpr*>(this)->getCalleeDecl(); + } + /// \brief If the callee is a FunctionDecl, return it. Otherwise return 0. FunctionDecl *getDirectCallee(); const FunctionDecl *getDirectCallee() const { @@ -1459,10 +1460,11 @@ class CompoundLiteralExpr : public Expr { Stmt *Init; bool FileScope; public: + // FIXME: Can compound literals be value-dependent? CompoundLiteralExpr(SourceLocation lparenloc, QualType ty, Expr *init, bool fileScope) - : Expr(CompoundLiteralExprClass, ty), LParenLoc(lparenloc), Init(init), - FileScope(fileScope) {} + : Expr(CompoundLiteralExprClass, ty, ty->isDependentType(), false), + LParenLoc(lparenloc), Init(init), FileScope(fileScope) {} /// \brief Construct an empty compound literal. explicit CompoundLiteralExpr(EmptyShell Empty) @@ -1896,8 +1898,11 @@ public: protected: BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, - SourceLocation oploc, bool dead) - : Expr(CompoundAssignOperatorClass, ResTy), Opc(opc), OpLoc(oploc) { + SourceLocation opLoc, bool dead) + : Expr(CompoundAssignOperatorClass, ResTy, + lhs->isTypeDependent() || rhs->isTypeDependent(), + lhs->isValueDependent() || rhs->isValueDependent()), + Opc(opc), OpLoc(opLoc) { SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; } @@ -2026,7 +2031,8 @@ class AddrLabelExpr : public Expr { public: AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelStmt *L, QualType t) - : Expr(AddrLabelExprClass, t), AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {} + : Expr(AddrLabelExprClass, t, false, false), + AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {} /// \brief Build an empty address of a label expression. explicit AddrLabelExpr(EmptyShell Empty) @@ -2061,9 +2067,11 @@ class StmtExpr : public Expr { Stmt *SubStmt; SourceLocation LParenLoc, RParenLoc; public: + // FIXME: Does type-dependence need to be computed differently? StmtExpr(CompoundStmt *substmt, QualType T, SourceLocation lp, SourceLocation rp) : - Expr(StmtExprClass, T), SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { } + Expr(StmtExprClass, T, T->isDependentType(), false), + SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { } /// \brief Build an empty statement expression. explicit StmtExpr(EmptyShell Empty) : Expr(StmtExprClass, Empty) { } @@ -2102,8 +2110,8 @@ class TypesCompatibleExpr : public Expr { public: TypesCompatibleExpr(QualType ReturnType, SourceLocation BLoc, QualType t1, QualType t2, SourceLocation RP) : - Expr(TypesCompatibleExprClass, ReturnType), Type1(t1), Type2(t2), - BuiltinLoc(BLoc), RParenLoc(RP) {} + Expr(TypesCompatibleExprClass, ReturnType, false, false), + Type1(t1), Type2(t2), BuiltinLoc(BLoc), RParenLoc(RP) {} /// \brief Build an empty __builtin_type_compatible_p expression. explicit TypesCompatibleExpr(EmptyShell Empty) @@ -2153,11 +2161,13 @@ protected: virtual void DoDestroy(ASTContext &C); public: + // FIXME: Can a shufflevector be value-dependent? Does type-dependence need + // to be computed differently? ShuffleVectorExpr(ASTContext &C, Expr **args, unsigned nexpr, QualType Type, SourceLocation BLoc, SourceLocation RP) : - Expr(ShuffleVectorExprClass, Type), BuiltinLoc(BLoc), - RParenLoc(RP), NumExprs(nexpr) { + Expr(ShuffleVectorExprClass, Type, Type->isDependentType(), false), + BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(nexpr) { SubExprs = new (C) Stmt*[nexpr]; for (unsigned i = 0; i < nexpr; i++) @@ -2285,7 +2295,7 @@ class GNUNullExpr : public Expr { public: GNUNullExpr(QualType Ty, SourceLocation Loc) - : Expr(GNUNullExprClass, Ty), TokenLoc(Loc) { } + : Expr(GNUNullExprClass, Ty, false, false), TokenLoc(Loc) { } /// \brief Build an empty GNU __null expression. explicit GNUNullExpr(EmptyShell Empty) : Expr(GNUNullExprClass, Empty) { } @@ -2313,7 +2323,7 @@ class VAArgExpr : public Expr { SourceLocation BuiltinLoc, RParenLoc; public: VAArgExpr(SourceLocation BLoc, Expr* e, QualType t, SourceLocation RPLoc) - : Expr(VAArgExprClass, t), + : Expr(VAArgExprClass, t, t->isDependentType(), false), Val(e), BuiltinLoc(BLoc), RParenLoc(RPLoc) { } @@ -2795,7 +2805,7 @@ public: class ImplicitValueInitExpr : public Expr { public: explicit ImplicitValueInitExpr(QualType ty) - : Expr(ImplicitValueInitExprClass, ty) { } + : Expr(ImplicitValueInitExprClass, ty, false, false) { } /// \brief Construct an empty implicit value initialization. explicit ImplicitValueInitExpr(EmptyShell Empty) @@ -2883,7 +2893,8 @@ class ExtVectorElementExpr : public Expr { public: ExtVectorElementExpr(QualType ty, Expr *base, IdentifierInfo &accessor, SourceLocation loc) - : Expr(ExtVectorElementExprClass, ty), + : Expr(ExtVectorElementExprClass, ty, base->isTypeDependent(), + base->isValueDependent()), Base(base), Accessor(&accessor), AccessorLoc(loc) {} /// \brief Build an empty vector element expression. @@ -2938,7 +2949,7 @@ protected: bool HasBlockDeclRefExprs; public: BlockExpr(BlockDecl *BD, QualType ty, bool hasBlockDeclRefExprs) - : Expr(BlockExprClass, ty), + : Expr(BlockExprClass, ty, ty->isDependentType(), false), TheBlock(BD), HasBlockDeclRefExprs(hasBlockDeclRefExprs) {} /// \brief Build an empty block expression. @@ -2983,10 +2994,11 @@ class BlockDeclRefExpr : public Expr { bool IsByRef : 1; bool ConstQualAdded : 1; public: + // FIXME: Fix type/value dependence! BlockDeclRefExpr(ValueDecl *d, QualType t, SourceLocation l, bool ByRef, - bool constAdded = false) : - Expr(BlockDeclRefExprClass, t), D(d), Loc(l), IsByRef(ByRef), - ConstQualAdded(constAdded) {} + bool constAdded = false) + : Expr(BlockDeclRefExprClass, t, false, false), D(d), Loc(l), IsByRef(ByRef), + ConstQualAdded(constAdded) {} // \brief Build an empty reference to a declared variable in a // block. diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 00ea202..d0e21f5 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -224,7 +224,7 @@ class CXXBoolLiteralExpr : public Expr { SourceLocation Loc; public: CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) : - Expr(CXXBoolLiteralExprClass, Ty), Value(val), Loc(l) {} + Expr(CXXBoolLiteralExprClass, Ty, false, false), Value(val), Loc(l) {} bool getValue() const { return Value; } @@ -245,7 +245,7 @@ class CXXNullPtrLiteralExpr : public Expr { SourceLocation Loc; public: CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l) : - Expr(CXXNullPtrLiteralExprClass, Ty), Loc(l) {} + Expr(CXXNullPtrLiteralExprClass, Ty, false, false), Loc(l) {} virtual SourceRange getSourceRange() const { return SourceRange(Loc); } @@ -386,30 +386,70 @@ public: /// parameter's default argument, when the call did not explicitly /// supply arguments for all of the parameters. class CXXDefaultArgExpr : public Expr { - ParmVarDecl *Param; + /// \brief The parameter whose default is being used. + /// + /// When the bit is set, the subexpression is stored after the + /// CXXDefaultArgExpr itself. When the bit is clear, the parameter's + /// actual default expression is the subexpression. + llvm::PointerIntPair<ParmVarDecl *, 1, bool> Param; + /// \brief The location where the default argument expression was used. + SourceLocation Loc; + protected: - CXXDefaultArgExpr(StmtClass SC, ParmVarDecl *param) - : Expr(SC, param->hasUnparsedDefaultArg() ? - param->getType().getNonReferenceType() - : param->getDefaultArg()->getType()), - Param(param) { } - + CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param) + : Expr(SC, + param->hasUnparsedDefaultArg() + ? param->getType().getNonReferenceType() + : param->getDefaultArg()->getType(), + false, false), + Param(param, false), Loc(Loc) { } + + CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param, + Expr *SubExpr) + : Expr(SC, SubExpr->getType(), false, false), Param(param, true), Loc(Loc) + { + *reinterpret_cast<Expr **>(this + 1) = SubExpr; + } + +protected: + virtual void DoDestroy(ASTContext &C); + public: // Param is the parameter whose default argument is used by this // expression. - static CXXDefaultArgExpr *Create(ASTContext &C, ParmVarDecl *Param) { - return new (C) CXXDefaultArgExpr(CXXDefaultArgExprClass, Param); + static CXXDefaultArgExpr *Create(ASTContext &C, SourceLocation Loc, + ParmVarDecl *Param) { + return new (C) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param); } + // Param is the parameter whose default argument is used by this + // expression, and SubExpr is the expression that will actually be used. + static CXXDefaultArgExpr *Create(ASTContext &C, + SourceLocation Loc, + ParmVarDecl *Param, + Expr *SubExpr); + // Retrieve the parameter that the argument was created from. - const ParmVarDecl *getParam() const { return Param; } - ParmVarDecl *getParam() { return Param; } + const ParmVarDecl *getParam() const { return Param.getPointer(); } + ParmVarDecl *getParam() { return Param.getPointer(); } // Retrieve the actual argument to the function call. - const Expr *getExpr() const { return Param->getDefaultArg(); } - Expr *getExpr() { return Param->getDefaultArg(); } + const Expr *getExpr() const { + if (Param.getInt()) + return *reinterpret_cast<Expr const * const*> (this + 1); + return getParam()->getDefaultArg(); + } + Expr *getExpr() { + if (Param.getInt()) + return *reinterpret_cast<Expr **> (this + 1); + return getParam()->getDefaultArg(); + } + /// \brief Retrieve the location where this default argument was actually + /// used. + SourceLocation getUsedLocation() const { return Loc; } + virtual SourceRange getSourceRange() const { // Default argument expressions have no representation in the // source, so they have an empty source range. @@ -452,8 +492,8 @@ class CXXBindTemporaryExpr : public Expr { Stmt *SubExpr; CXXBindTemporaryExpr(CXXTemporary *temp, Expr* subexpr) - : Expr(CXXBindTemporaryExprClass, - subexpr->getType()), Temp(temp), SubExpr(subexpr) { } + : Expr(CXXBindTemporaryExprClass, subexpr->getType(), false, false), + Temp(temp), SubExpr(subexpr) { } ~CXXBindTemporaryExpr() { } protected: @@ -489,15 +529,18 @@ public: class CXXConstructExpr : public Expr { CXXConstructorDecl *Constructor; - bool Elidable; - + SourceLocation Loc; + bool Elidable : 1; + bool ZeroInitialization : 1; Stmt **Args; unsigned NumArgs; protected: CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, + SourceLocation Loc, CXXConstructorDecl *d, bool elidable, - Expr **args, unsigned numargs); + Expr **args, unsigned numargs, + bool ZeroInitialization = false); ~CXXConstructExpr() { } virtual void DoDestroy(ASTContext &C); @@ -508,17 +551,29 @@ public: CXXConstructExpr(EmptyShell Empty, ASTContext &C, unsigned numargs); static CXXConstructExpr *Create(ASTContext &C, QualType T, + SourceLocation Loc, CXXConstructorDecl *D, bool Elidable, - Expr **Args, unsigned NumArgs); + Expr **Args, unsigned NumArgs, + bool ZeroInitialization = false); CXXConstructorDecl* getConstructor() const { return Constructor; } void setConstructor(CXXConstructorDecl *C) { Constructor = C; } + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation Loc) { this->Loc = Loc; } + /// \brief Whether this construction is elidable. bool isElidable() const { return Elidable; } void setElidable(bool E) { Elidable = E; } + /// \brief Whether this construction first requires + /// zero-initialization before the initializer is called. + bool requiresZeroInitialization() const { return ZeroInitialization; } + void setRequiresZeroInitialization(bool ZeroInit) { + ZeroInitialization = ZeroInit; + } + typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; @@ -546,13 +601,7 @@ public: Args[Arg] = ArgExpr; } - virtual SourceRange getSourceRange() const { - // FIXME: Should we know where the parentheses are, if there are any? - if (NumArgs == 0) - return SourceRange(); - - return SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd()); - } + virtual SourceRange getSourceRange() const; static bool classof(const Stmt *T) { return T->getStmtClass() == CXXConstructExprClass || @@ -1264,10 +1313,8 @@ class CXXExprWithTemporaries : public Expr { CXXTemporary **Temps; unsigned NumTemps; - bool ShouldDestroyTemps; - CXXExprWithTemporaries(Expr *SubExpr, CXXTemporary **Temps, - unsigned NumTemps, bool ShouldDestroyTemps); + unsigned NumTemps); ~CXXExprWithTemporaries(); protected: @@ -1275,8 +1322,8 @@ protected: public: static CXXExprWithTemporaries *Create(ASTContext &C, Expr *SubExpr, - CXXTemporary **Temps, unsigned NumTemps, - bool ShouldDestroyTemporaries); + CXXTemporary **Temps, + unsigned NumTemps); unsigned getNumTemporaries() const { return NumTemps; } CXXTemporary *getTemporary(unsigned i) { @@ -1284,14 +1331,9 @@ public: return Temps[i]; } const CXXTemporary *getTemporary(unsigned i) const { - assert(i < NumTemps && "Index out of range"); - return Temps[i]; + return const_cast<CXXExprWithTemporaries*>(this)->getTemporary(i); } - bool shouldDestroyTemporaries() const { return ShouldDestroyTemps; } - - void removeLastTemporary() { NumTemps--; } - Expr *getSubExpr() { return cast<Expr>(SubExpr); } const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } void setSubExpr(Expr *E) { SubExpr = E; } diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index 0613f4c..0b0cd64 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -30,7 +30,7 @@ class ObjCStringLiteral : public Expr { SourceLocation AtLoc; public: ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L) - : Expr(ObjCStringLiteralClass, T), String(SL), AtLoc(L) {} + : Expr(ObjCStringLiteralClass, T, false, false), String(SL), AtLoc(L) {} explicit ObjCStringLiteral(EmptyShell Empty) : Expr(ObjCStringLiteralClass, Empty) {} @@ -100,7 +100,8 @@ class ObjCSelectorExpr : public Expr { public: ObjCSelectorExpr(QualType T, Selector selInfo, SourceLocation at, SourceLocation rp) - : Expr(ObjCSelectorExprClass, T), SelName(selInfo), AtLoc(at), RParenLoc(rp){} + : Expr(ObjCSelectorExprClass, T, false, false), SelName(selInfo), AtLoc(at), + RParenLoc(rp){} explicit ObjCSelectorExpr(EmptyShell Empty) : Expr(ObjCSelectorExprClass, Empty) {} @@ -139,7 +140,7 @@ class ObjCProtocolExpr : public Expr { public: ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol, SourceLocation at, SourceLocation rp) - : Expr(ObjCProtocolExprClass, T), TheProtocol(protocol), + : Expr(ObjCProtocolExprClass, T, false, false), TheProtocol(protocol), AtLoc(at), RParenLoc(rp) {} explicit ObjCProtocolExpr(EmptyShell Empty) : Expr(ObjCProtocolExprClass, Empty) {} @@ -178,7 +179,7 @@ public: ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t, SourceLocation l, Expr *base=0, bool arrow = false, bool freeIvar = false) : - Expr(ObjCIvarRefExprClass, t), D(d), + Expr(ObjCIvarRefExprClass, t, false, false), D(d), Loc(l), Base(base), IsArrow(arrow), IsFreeIvar(freeIvar) {} @@ -227,7 +228,8 @@ private: public: ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, SourceLocation l, Expr *base) - : Expr(ObjCPropertyRefExprClass, t), AsProperty(PD), IdLoc(l), Base(base) { + : Expr(ObjCPropertyRefExprClass, t, false, false), AsProperty(PD), + IdLoc(l), Base(base) { } explicit ObjCPropertyRefExpr(EmptyShell Empty) @@ -291,16 +293,17 @@ public: QualType t, ObjCMethodDecl *setter, SourceLocation l, Expr *base) - : Expr(ObjCImplicitSetterGetterRefExprClass, t), Setter(setter), - Getter(getter), MemberLoc(l), Base(base), InterfaceDecl(0), - ClassLoc(SourceLocation()) { + : Expr(ObjCImplicitSetterGetterRefExprClass, t, false, false), + Setter(setter), Getter(getter), MemberLoc(l), Base(base), + InterfaceDecl(0), ClassLoc(SourceLocation()) { } ObjCImplicitSetterGetterRefExpr(ObjCMethodDecl *getter, QualType t, ObjCMethodDecl *setter, SourceLocation l, ObjCInterfaceDecl *C, SourceLocation CL) - : Expr(ObjCImplicitSetterGetterRefExprClass, t), Setter(setter), - Getter(getter), MemberLoc(l), Base(0), InterfaceDecl(C), ClassLoc(CL) { + : Expr(ObjCImplicitSetterGetterRefExprClass, t, false, false), + Setter(setter), Getter(getter), MemberLoc(l), Base(0), InterfaceDecl(C), + ClassLoc(CL) { } explicit ObjCImplicitSetterGetterRefExpr(EmptyShell Empty) : Expr(ObjCImplicitSetterGetterRefExprClass, Empty){} @@ -488,7 +491,7 @@ class ObjCSuperExpr : public Expr { SourceLocation Loc; public: ObjCSuperExpr(SourceLocation L, QualType Type) - : Expr(ObjCSuperExprClass, Type), Loc(L) { } + : Expr(ObjCSuperExprClass, Type, false, false), Loc(L) { } explicit ObjCSuperExpr(EmptyShell Empty) : Expr(ObjCSuperExprClass, Empty) {} SourceLocation getLoc() const { return Loc; } @@ -519,7 +522,7 @@ class ObjCIsaExpr : public Expr { bool IsArrow; public: ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, QualType ty) - : Expr(ObjCIsaExprClass, ty), + : Expr(ObjCIsaExprClass, ty, false, false), Base(base), IsaMemberLoc(l), IsArrow(isarrow) {} /// \brief Build an empty expression. diff --git a/include/clang/AST/FullExpr.h b/include/clang/AST/FullExpr.h new file mode 100644 index 0000000..bb81bf0 --- /dev/null +++ b/include/clang/AST/FullExpr.h @@ -0,0 +1,89 @@ +//===--- FullExpr.h - C++ full expression class -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the FullExpr interface, to be used for type safe handling +// of full expressions. +// +// Full expressions are described in C++ [intro.execution]p12. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_FULLEXPR_H +#define LLVM_CLANG_AST_FULLEXPR_H + +#include "llvm/ADT/PointerUnion.h" + +namespace clang { + class ASTContext; + class CXXTemporary; + class Expr; + +class FullExpr { + struct ExprAndTemporaries { + Expr *SubExpr; + + unsigned NumTemps; + + typedef CXXTemporary** temps_iterator; + + temps_iterator temps_begin() { + return reinterpret_cast<CXXTemporary **>(this + 1); + } + temps_iterator temps_end() { + return temps_begin() + NumTemps; + } + }; + + typedef llvm::PointerUnion<Expr *, ExprAndTemporaries *> SubExprTy; + SubExprTy SubExpr; + + FullExpr() { } + +public: + static FullExpr Create(ASTContext &Context, Expr *SubExpr, + CXXTemporary **Temps, unsigned NumTemps); + void Destroy(ASTContext &Context); + + Expr *getExpr() { + if (Expr *E = SubExpr.dyn_cast<Expr *>()) + return E; + + return SubExpr.get<ExprAndTemporaries *>()->SubExpr; + } + + const Expr *getExpr() const { + return const_cast<FullExpr*>(this)->getExpr(); + } + + typedef CXXTemporary** temps_iterator; + + temps_iterator temps_begin() { + if (ExprAndTemporaries *ET = SubExpr.dyn_cast<ExprAndTemporaries *>()) + return ET->temps_begin(); + + return 0; + } + temps_iterator temps_end() { + if (ExprAndTemporaries *ET = SubExpr.dyn_cast<ExprAndTemporaries *>()) + return ET->temps_end(); + + return 0; + } + + void *getAsOpaquePtr() const { return SubExpr.getOpaqueValue(); } + + static FullExpr getFromOpaquePtr(void *Ptr) { + FullExpr E; + E.SubExpr = SubExprTy::getFromOpaqueValue(Ptr); + return E; + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index a8334b6..e8d1788 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -53,7 +53,7 @@ public: PrimaryBaseInfo() {} PrimaryBaseInfo(const CXXRecordDecl *Base, bool IsVirtual) - : Value(Base, IsVirtual) {} + : Value(Base, Base && IsVirtual) {} /// Value - Points to the primary base. The single-bit value /// will be non-zero when the primary base is virtual. diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index d6f6a83..33edadc 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -20,6 +20,7 @@ #include "clang/AST/PrettyPrinter.h" #include "clang/AST/StmtIterator.h" #include "clang/AST/DeclGroup.h" +#include "clang/AST/FullExpr.h" #include "llvm/ADT/SmallVector.h" #include "clang/AST/ASTContext.h" #include <string> @@ -293,6 +294,9 @@ class DeclStmt : public Stmt { DeclGroupRef DG; SourceLocation StartLoc, EndLoc; +protected: + virtual void DoDestroy(ASTContext &Ctx); + public: DeclStmt(DeclGroupRef dg, SourceLocation startLoc, SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg), @@ -620,9 +624,9 @@ class IfStmt : public Stmt { SourceLocation ElseLoc; public: - IfStmt(SourceLocation IL, VarDecl *Var, Expr *cond, Stmt *then, + IfStmt(SourceLocation IL, VarDecl *var, Expr *cond, Stmt *then, SourceLocation EL = SourceLocation(), Stmt *elsev = 0) - : Stmt(IfStmtClass), Var(Var), IfLoc(IL), ElseLoc(EL) { + : Stmt(IfStmtClass), Var(var), IfLoc(IL), ElseLoc(EL) { SubExprs[COND] = reinterpret_cast<Stmt*>(cond); SubExprs[THEN] = then; SubExprs[ELSE] = elsev; @@ -670,9 +674,13 @@ public: } static bool classof(const IfStmt *) { return true; } - // Iterators + // Iterators over subexpressions. The iterators will include iterating + // over the initialization expression referenced by the condition variable. virtual child_iterator child_begin(); virtual child_iterator child_end(); + +protected: + virtual void DoDestroy(ASTContext &Ctx); }; /// SwitchStmt - This represents a 'switch' stmt. @@ -805,6 +813,9 @@ public: // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); + +protected: + virtual void DoDestroy(ASTContext &Ctx); }; /// DoStmt - This represents a 'do/while' stmt. @@ -868,9 +879,9 @@ class ForStmt : public Stmt { SourceLocation LParenLoc, RParenLoc; public: - ForStmt(Stmt *Init, Expr *Cond, VarDecl *CondVar, Expr *Inc, Stmt *Body, + 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), + : Stmt(ForStmtClass), CondVar(condVar), ForLoc(FL), LParenLoc(LP), RParenLoc(RP) { SubExprs[INIT] = Init; @@ -927,6 +938,9 @@ public: // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); + +protected: + virtual void DoDestroy(ASTContext &Ctx); }; /// GotoStmt - This represents a direct goto. diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h index f1aa2cd5..a48f4e6 100644 --- a/include/clang/AST/StmtIterator.h +++ b/include/clang/AST/StmtIterator.h @@ -28,11 +28,12 @@ class StmtIteratorBase { protected: enum { DeclMode = 0x1, SizeOfTypeVAMode = 0x2, DeclGroupMode = 0x3, Flags = 0x3 }; - - union { Stmt** stmt; Decl* decl; Decl** DGI; }; + + Stmt **stmt; + union { Decl *decl; Decl **DGI; }; uintptr_t RawVAPtr; - Decl** DGE; - + Decl **DGE; + bool inDecl() const { return (RawVAPtr & Flags) == DeclMode; } @@ -64,11 +65,11 @@ protected: Stmt*& GetDeclExpr() const; - StmtIteratorBase(Stmt** s) : stmt(s), RawVAPtr(0) {} - StmtIteratorBase(Decl* d); - StmtIteratorBase(VariableArrayType* t); - StmtIteratorBase(Decl** dgi, Decl** dge); - StmtIteratorBase() : stmt(NULL), RawVAPtr(0) {} + StmtIteratorBase(Stmt **s) : stmt(s), decl(0), RawVAPtr(0) {} + StmtIteratorBase(Decl *d, Stmt **s); + StmtIteratorBase(VariableArrayType *t); + StmtIteratorBase(Decl **dgi, Decl **dge); + StmtIteratorBase() : stmt(0), decl(0), RawVAPtr(0) {} }; @@ -81,9 +82,9 @@ protected: StmtIteratorImpl(const StmtIteratorBase& RHS) : StmtIteratorBase(RHS) {} public: StmtIteratorImpl() {} - StmtIteratorImpl(Stmt** s) : StmtIteratorBase(s) {} - StmtIteratorImpl(Decl** dgi, Decl** dge) : StmtIteratorBase(dgi, dge) {} - StmtIteratorImpl(Decl* d) : StmtIteratorBase(d) {} + StmtIteratorImpl(Stmt **s) : StmtIteratorBase(s) {} + StmtIteratorImpl(Decl **dgi, Decl **dge) : StmtIteratorBase(dgi, dge) {} + StmtIteratorImpl(Decl *d, Stmt **s) : StmtIteratorBase(d, s) {} StmtIteratorImpl(VariableArrayType* t) : StmtIteratorBase(t) {} DERIVED& operator++() { @@ -106,11 +107,11 @@ public: } bool operator==(const DERIVED& RHS) const { - return stmt == RHS.stmt && RawVAPtr == RHS.RawVAPtr; + return stmt == RHS.stmt && decl == RHS.decl && RawVAPtr == RHS.RawVAPtr; } bool operator!=(const DERIVED& RHS) const { - return stmt != RHS.stmt || RawVAPtr != RHS.RawVAPtr; + return stmt != RHS.stmt || decl != RHS.decl || RawVAPtr != RHS.RawVAPtr; } REFERENCE operator*() const { @@ -124,11 +125,15 @@ struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> { explicit StmtIterator() : StmtIteratorImpl<StmtIterator,Stmt*&>() {} StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator,Stmt*&>(S) {} + StmtIterator(Decl** dgi, Decl** dge) : StmtIteratorImpl<StmtIterator,Stmt*&>(dgi, dge) {} - StmtIterator(VariableArrayType* t):StmtIteratorImpl<StmtIterator,Stmt*&>(t) {} - StmtIterator(Decl* D) : StmtIteratorImpl<StmtIterator,Stmt*&>(D) {} + StmtIterator(VariableArrayType* t) + : StmtIteratorImpl<StmtIterator,Stmt*&>(t) {} + + StmtIterator(Decl* D, Stmt **s = 0) + : StmtIteratorImpl<StmtIterator,Stmt*&>(D, s) {} }; struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator, diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index fe03799..50a100c 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -221,7 +221,7 @@ public: assert(Kind == Integral && "Cannot set the integral type of a non-integral template argument"); Integer.Type = T.getAsOpaquePtr(); - }; + } /// \brief Retrieve the template argument as an expression. Expr *getAsExpr() const { diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index d22a646..9b0cdc3 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -531,7 +531,12 @@ public: /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers /// applied to this type. unsigned getCVRQualifiers() const; - + + /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers + /// applied to this type, looking through any number of unqualified array + /// types to their element types' qualifiers. + unsigned getCVRQualifiersThroughArrayTypes() const; + bool isConstant(ASTContext& Ctx) const { return QualType::isConstant(*this, Ctx); } @@ -1049,28 +1054,6 @@ public: static bool classof(const BuiltinType *) { return true; } }; -/// FixedWidthIntType - Used for arbitrary width types that we either don't -/// want to or can't map to named integer types. These always have a lower -/// integer rank than builtin types of the same width. -class FixedWidthIntType : public Type { -private: - unsigned Width; - bool Signed; -public: - FixedWidthIntType(unsigned W, bool S) : Type(FixedWidthInt, QualType(), false), - Width(W), Signed(S) {} - - unsigned getWidth() const { return Width; } - bool isSigned() const { return Signed; } - const char *getName() const; - - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } - - static bool classof(const Type *T) { return T->getTypeClass() == FixedWidthInt; } - static bool classof(const FixedWidthIntType *) { return true; } -}; - /// ComplexType - C99 6.2.5p11 - Complex values. This supports the C99 complex /// types (_Complex float etc) as well as the GCC integer complex extensions. /// @@ -2708,7 +2691,20 @@ inline unsigned QualType::getCVRQualifiers() const { return getLocalCVRQualifiers() | getTypePtr()->getCanonicalTypeInternal().getLocalCVRQualifiers(); } - + +/// getCVRQualifiersThroughArrayTypes - If there are CVR qualifiers for this +/// type, returns them. Otherwise, if this is an array type, recurses +/// on the element type until some qualifiers have been found or a non-array +/// type reached. +inline unsigned QualType::getCVRQualifiersThroughArrayTypes() const { + if (unsigned Quals = getCVRQualifiers()) + return Quals; + QualType CT = getTypePtr()->getCanonicalTypeInternal(); + if (const ArrayType *AT = dyn_cast<ArrayType>(CT)) + return AT->getElementType().getCVRQualifiersThroughArrayTypes(); + return 0; +} + inline void QualType::removeConst() { removeFastQualifiers(Qualifiers::Const); } @@ -2808,8 +2804,8 @@ inline bool QualType::getNoReturnAttr() const { /// int". inline bool QualType::isMoreQualifiedThan(QualType Other) const { // FIXME: work on arbitrary qualifiers - unsigned MyQuals = this->getCVRQualifiers(); - unsigned OtherQuals = Other.getCVRQualifiers(); + unsigned MyQuals = this->getCVRQualifiersThroughArrayTypes(); + unsigned OtherQuals = Other.getCVRQualifiersThroughArrayTypes(); if (getAddressSpace() != Other.getAddressSpace()) return false; return MyQuals != OtherQuals && (MyQuals | OtherQuals) == MyQuals; @@ -2821,8 +2817,8 @@ inline bool QualType::isMoreQualifiedThan(QualType Other) const { /// "int", and "const volatile int". inline bool QualType::isAtLeastAsQualifiedAs(QualType Other) const { // FIXME: work on arbitrary qualifiers - unsigned MyQuals = this->getCVRQualifiers(); - unsigned OtherQuals = Other.getCVRQualifiers(); + unsigned MyQuals = this->getCVRQualifiersThroughArrayTypes(); + unsigned OtherQuals = Other.getCVRQualifiersThroughArrayTypes(); if (getAddressSpace() != Other.getAddressSpace()) return false; return (MyQuals | OtherQuals) == MyQuals; diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index a9b7f7e..3e74d07 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -1023,13 +1023,6 @@ class DependentSizedExtVectorTypeLoc : DependentSizedExtVectorType> { }; -// FIXME: I'm not sure how you actually specify these; with attributes? -class FixedWidthIntTypeLoc : - public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - FixedWidthIntTypeLoc, - FixedWidthIntType> { -}; - // FIXME: location of the '_Complex' keyword. class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, ComplexTypeLoc, diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index b9d3799..575011a 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -52,7 +52,6 @@ #endif TYPE(Builtin, Type) -TYPE(FixedWidthInt, Type) TYPE(Complex, Type) TYPE(Pointer, Type) TYPE(BlockPointer, Type) @@ -92,7 +91,6 @@ TYPE(ObjCObjectPointer, Type) #ifdef LEAF_TYPE LEAF_TYPE(Enum) LEAF_TYPE(Builtin) -LEAF_TYPE(FixedWidthInt) LEAF_TYPE(ObjCInterface) LEAF_TYPE(TemplateTypeParm) #undef LEAF_TYPE diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h index 0077a85..44ab080 100644 --- a/include/clang/Analysis/Analyses/LiveVariables.h +++ b/include/clang/Analysis/Analyses/LiveVariables.h @@ -70,7 +70,7 @@ public: LiveVariables(AnalysisContext &AC); - /// IsLive - Return true if a variable is live at beginning of a + /// IsLive - Return true if a variable is live at the end of a /// specified block. bool isLive(const CFGBlock* B, const VarDecl* D) const; diff --git a/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h index 8a967c3..2b367b7 100644 --- a/include/clang/Analysis/Analyses/UninitializedValues.h +++ b/include/clang/Analysis/Analyses/UninitializedValues.h @@ -35,7 +35,7 @@ public: struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy { AnalysisDataTy() : Observer(NULL), FullUninitTaint(true) {} - virtual ~AnalysisDataTy() {}; + virtual ~AnalysisDataTy() {} ObserverTy* Observer; bool FullUninitTaint; diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index e6f4cf9..38d4bdf 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -15,8 +15,10 @@ #ifndef LLVM_CLANG_CFG_H #define LLVM_CLANG_CFG_H +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/Casting.h" #include "clang/Analysis/Support/BumpVector.h" #include <cassert> @@ -31,6 +33,17 @@ namespace clang { class LangOptions; class ASTContext; +/// CFGElement - Represents a top-level expression in a basic block. +class CFGElement { + llvm::PointerIntPair<Stmt *, 1> Data; +public: + explicit CFGElement() {} + CFGElement(Stmt *S, bool lvalue) : Data(S, lvalue ? 1 : 0) {} + Stmt *getStmt() const { return Data.getPointer(); } + bool asLValue() const { return Data.getInt() == 1; } + operator Stmt*() const { return getStmt(); } +}; + /// CFGBlock - Represents a single basic block in a source-level CFG. /// It consists of: /// @@ -57,7 +70,7 @@ namespace clang { /// class CFGBlock { class StatementList { - typedef BumpVector<Stmt*> ImplTy; + typedef BumpVector<CFGElement> ImplTy; ImplTy Impl; public: StatementList(BumpVectorContext &C) : Impl(C, 4) {} @@ -67,9 +80,9 @@ class CFGBlock { typedef ImplTy::iterator reverse_iterator; typedef ImplTy::const_iterator const_reverse_iterator; - void push_back(Stmt *s, BumpVectorContext &C) { Impl.push_back(s, C); } - Stmt *front() const { return Impl.back(); } - Stmt *back() const { return Impl.front(); } + void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); } + CFGElement front() const { return Impl.back(); } + CFGElement back() const { return Impl.front(); } iterator begin() { return Impl.rbegin(); } iterator end() { return Impl.rend(); } @@ -80,7 +93,7 @@ class CFGBlock { const_reverse_iterator rbegin() const { return Impl.begin(); } const_reverse_iterator rend() const { return Impl.end(); } - Stmt* operator[](size_t i) const { + CFGElement operator[](size_t i) const { assert(i < Impl.size()); return Impl[Impl.size() - 1 - i]; } @@ -121,7 +134,7 @@ public: explicit CFGBlock(unsigned blockid, BumpVectorContext &C) : Stmts(C), Label(NULL), Terminator(NULL), LoopTarget(NULL), BlockID(blockid), Preds(C, 1), Succs(C, 1) {} - ~CFGBlock() {}; + ~CFGBlock() {} // Statement iterators typedef StatementList::iterator iterator; @@ -129,8 +142,8 @@ public: typedef StatementList::reverse_iterator reverse_iterator; typedef StatementList::const_reverse_iterator const_reverse_iterator; - Stmt* front() const { return Stmts.front(); } - Stmt* back() const { return Stmts.back(); } + CFGElement front() const { return Stmts.front(); } + CFGElement back() const { return Stmts.back(); } iterator begin() { return Stmts.begin(); } iterator end() { return Stmts.end(); } @@ -145,8 +158,7 @@ public: unsigned size() const { return Stmts.size(); } bool empty() const { return Stmts.empty(); } - Stmt* operator[](size_t i) const { return Stmts[i]; } - + CFGElement operator[](size_t i) const { return Stmts[i]; } // CFG iterators typedef AdjacentBlocks::iterator pred_iterator; @@ -221,8 +233,8 @@ public: Succs.push_back(Block, C); } - void appendStmt(Stmt* Statement, BumpVectorContext &C) { - Stmts.push_back(Statement, C); + void appendStmt(Stmt* Statement, BumpVectorContext &C, bool asLValue) { + Stmts.push_back(CFGElement(Statement, asLValue), C); } }; @@ -333,7 +345,7 @@ public: //===--------------------------------------------------------------------===// CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0), - BlkExprMap(NULL), Blocks(BlkBVC, 10) {}; + BlkExprMap(NULL), Blocks(BlkBVC, 10) {} ~CFG(); @@ -370,13 +382,25 @@ private: namespace llvm { +/// Implement simplify_type for CFGElement, so that we can dyn_cast from +/// CFGElement to a specific Stmt class. +template <> struct simplify_type<const ::clang::CFGElement> { + typedef ::clang::Stmt* SimpleType; + static SimpleType getSimplifiedValue(const ::clang::CFGElement &Val) { + return Val.getStmt(); + } +}; + +template <> struct simplify_type< ::clang::CFGElement> + : public simplify_type<const ::clang::CFGElement> {}; + // Traits for: CFGBlock -template <> struct GraphTraits<clang::CFGBlock* > { - typedef clang::CFGBlock NodeType; - typedef clang::CFGBlock::succ_iterator ChildIteratorType; +template <> struct GraphTraits< ::clang::CFGBlock* > { + typedef ::clang::CFGBlock NodeType; + typedef ::clang::CFGBlock::succ_iterator ChildIteratorType; - static NodeType* getEntryNode(clang::CFGBlock* BB) + static NodeType* getEntryNode(::clang::CFGBlock* BB) { return BB; } static inline ChildIteratorType child_begin(NodeType* N) @@ -386,9 +410,9 @@ template <> struct GraphTraits<clang::CFGBlock* > { { return N->succ_end(); } }; -template <> struct GraphTraits<const clang::CFGBlock* > { - typedef const clang::CFGBlock NodeType; - typedef clang::CFGBlock::const_succ_iterator ChildIteratorType; +template <> struct GraphTraits< const ::clang::CFGBlock* > { + typedef const ::clang::CFGBlock NodeType; + typedef ::clang::CFGBlock::const_succ_iterator ChildIteratorType; static NodeType* getEntryNode(const clang::CFGBlock* BB) { return BB; } @@ -400,11 +424,11 @@ template <> struct GraphTraits<const clang::CFGBlock* > { { return N->succ_end(); } }; -template <> struct GraphTraits<Inverse<const clang::CFGBlock*> > { - typedef const clang::CFGBlock NodeType; - typedef clang::CFGBlock::const_pred_iterator ChildIteratorType; +template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > { + typedef const ::clang::CFGBlock NodeType; + typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType; - static NodeType *getEntryNode(Inverse<const clang::CFGBlock*> G) + static NodeType *getEntryNode(Inverse<const ::clang::CFGBlock*> G) { return G.Graph; } static inline ChildIteratorType child_begin(NodeType* N) @@ -416,36 +440,40 @@ template <> struct GraphTraits<Inverse<const clang::CFGBlock*> > { // Traits for: CFG -template <> struct GraphTraits<clang::CFG* > - : public GraphTraits<clang::CFGBlock* > { +template <> struct GraphTraits< ::clang::CFG* > + : public GraphTraits< ::clang::CFGBlock* > { - typedef clang::CFG::iterator nodes_iterator; + typedef ::clang::CFG::iterator nodes_iterator; - static NodeType *getEntryNode(clang::CFG* F) { return &F->getEntry(); } - static nodes_iterator nodes_begin(clang::CFG* F) { return F->begin(); } - static nodes_iterator nodes_end(clang::CFG* F) { return F->end(); } + static NodeType *getEntryNode(::clang::CFG* F) { return &F->getEntry(); } + static nodes_iterator nodes_begin(::clang::CFG* F) { return F->begin(); } + static nodes_iterator nodes_end(::clang::CFG* F) { return F->end(); } }; -template <> struct GraphTraits< const clang::CFG* > - : public GraphTraits< const clang::CFGBlock* > { +template <> struct GraphTraits<const ::clang::CFG* > + : public GraphTraits<const ::clang::CFGBlock* > { - typedef clang::CFG::const_iterator nodes_iterator; + typedef ::clang::CFG::const_iterator nodes_iterator; - static NodeType *getEntryNode( const clang::CFG* F) { return &F->getEntry(); } - static nodes_iterator nodes_begin( const clang::CFG* F) { return F->begin(); } - static nodes_iterator nodes_end( const clang::CFG* F) { return F->end(); } + static NodeType *getEntryNode( const ::clang::CFG* F) { + return &F->getEntry(); + } + static nodes_iterator nodes_begin( const ::clang::CFG* F) { + return F->begin(); + } + static nodes_iterator nodes_end( const ::clang::CFG* F) { + return F->end(); + } }; -template <> struct GraphTraits<Inverse<const clang::CFG*> > - : public GraphTraits<Inverse<const clang::CFGBlock*> > { +template <> struct GraphTraits<Inverse<const ::clang::CFG*> > + : public GraphTraits<Inverse<const ::clang::CFGBlock*> > { - typedef clang::CFG::const_iterator nodes_iterator; + typedef ::clang::CFG::const_iterator nodes_iterator; - static NodeType *getEntryNode(const clang::CFG* F) { return &F->getExit(); } - static nodes_iterator nodes_begin(const clang::CFG* F) { return F->begin();} - static nodes_iterator nodes_end(const clang::CFG* F) { return F->end(); } + static NodeType *getEntryNode(const ::clang::CFG* F) { return &F->getExit(); } + static nodes_iterator nodes_begin(const ::clang::CFG* F) { return F->begin();} + static nodes_iterator nodes_end(const ::clang::CFG* F) { return F->end(); } }; - } // end llvm namespace - #endif diff --git a/include/clang/Analysis/FlowSensitive/DataflowValues.h b/include/clang/Analysis/FlowSensitive/DataflowValues.h index 648fe33..7aa15c5 100644 --- a/include/clang/Analysis/FlowSensitive/DataflowValues.h +++ b/include/clang/Analysis/FlowSensitive/DataflowValues.h @@ -79,7 +79,7 @@ public: /// InitializeValues - Invoked by the solver to initialize state needed for /// dataflow analysis. This method is usually specialized by subclasses. - void InitializeValues(const CFG& cfg) {}; + void InitializeValues(const CFG& cfg) {} /// getEdgeData - Retrieves the dataflow values associated with a diff --git a/include/clang/Analysis/LocalCheckers.h b/include/clang/Analysis/LocalCheckers.h index 8c70e4f..9c343e0 100644 --- a/include/clang/Analysis/LocalCheckers.h +++ b/include/clang/Analysis/LocalCheckers.h @@ -56,6 +56,8 @@ void RegisterExperimentalInternalChecks(GRExprEngine &Eng); void CheckSecuritySyntaxOnly(const Decl *D, BugReporter &BR); void CheckSizeofPointer(const Decl *D, BugReporter &BR); + +void RegisterCallInliner(GRExprEngine &Eng); } // end namespace clang #endif diff --git a/include/clang/Analysis/PathDiagnostic.h b/include/clang/Analysis/PathDiagnostic.h index 970b523..d380c45 100644 --- a/include/clang/Analysis/PathDiagnostic.h +++ b/include/clang/Analysis/PathDiagnostic.h @@ -37,7 +37,7 @@ class PathDiagnosticClient : public DiagnosticClient { public: PathDiagnosticClient() {} - virtual ~PathDiagnosticClient() {}; + virtual ~PathDiagnosticClient() {} virtual void FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade = 0) = 0; diff --git a/include/clang/Analysis/PathSensitive/AnalysisContext.h b/include/clang/Analysis/PathSensitive/AnalysisContext.h index abc33b7..63ba558 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisContext.h +++ b/include/clang/Analysis/PathSensitive/AnalysisContext.h @@ -27,6 +27,7 @@ namespace clang { class Decl; class Stmt; class CFG; +class CFGBlock; class LiveVariables; class ParentMap; class ImplicitParamDecl; @@ -136,23 +137,38 @@ public: }; class StackFrameContext : public LocationContext { + // The callsite where this stack frame is established. const Stmt *CallSite; + // The parent block of the callsite. + const CFGBlock *Block; + + // The index of the callsite in the CFGBlock. + unsigned Index; + friend class LocationContextManager; StackFrameContext(AnalysisContext *ctx, const LocationContext *parent, - const Stmt *s) - : LocationContext(StackFrame, ctx, parent), CallSite(s) {} + const Stmt *s, const CFGBlock *blk, unsigned idx) + : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk), + Index(idx) {} public: ~StackFrameContext() {} const Stmt *getCallSite() const { return CallSite; } + const CFGBlock *getCallSiteBlock() const { return Block; } + + unsigned getIndex() const { return Index; } + void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, - const LocationContext *parent, const Stmt *s) { + const LocationContext *parent, const Stmt *s, + const CFGBlock *blk, unsigned idx) { ProfileCommon(ID, StackFrame, ctx, parent, s); + ID.AddPointer(blk); + ID.AddInteger(idx); } static bool classof(const LocationContext* Ctx) { @@ -230,7 +246,8 @@ public: const StackFrameContext *getStackFrame(AnalysisContext *ctx, const LocationContext *parent, - const Stmt *s); + const Stmt *s, const CFGBlock *blk, + unsigned idx); const ScopeContext *getScope(AnalysisContext *ctx, const LocationContext *parent, diff --git a/include/clang/Analysis/PathSensitive/AnalysisManager.h b/include/clang/Analysis/PathSensitive/AnalysisManager.h index 9ef5cce..8288864 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisManager.h +++ b/include/clang/Analysis/PathSensitive/AnalysisManager.h @@ -73,7 +73,7 @@ public: StoreManagerCreator getStoreManagerCreator() { return CreateStoreMgr; - }; + } ConstraintManagerCreator getConstraintManagerCreator() { return CreateConstraintMgr; @@ -132,14 +132,15 @@ public: // Get the top level stack frame. const StackFrameContext *getStackFrame(Decl const *D) { - return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), 0, 0); + return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), 0, 0, 0, 0); } // Get a stack frame with parent. StackFrameContext const *getStackFrame(Decl const *D, LocationContext const *Parent, - Stmt const *S) { - return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S); + Stmt const *S, const CFGBlock *Blk, + unsigned Idx) { + return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S, Blk,Idx); } }; diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Analysis/PathSensitive/BugReporter.h index 58c8018..ccebf01 100644 --- a/include/clang/Analysis/PathSensitive/BugReporter.h +++ b/include/clang/Analysis/PathSensitive/BugReporter.h @@ -203,7 +203,10 @@ public: ~RangedBugReport(); // FIXME: Move this out of line. - void addRange(SourceRange R) { Ranges.push_back(R); } + void addRange(SourceRange R) { + assert(R.isValid()); + Ranges.push_back(R); + } // FIXME: Move this out of line. void getRanges(const SourceRange*& beg, const SourceRange*& end) { diff --git a/include/clang/Analysis/PathSensitive/Checker.h b/include/clang/Analysis/PathSensitive/Checker.h index a625a7a..924a8b1 100644 --- a/include/clang/Analysis/PathSensitive/Checker.h +++ b/include/clang/Analysis/PathSensitive/Checker.h @@ -61,8 +61,12 @@ public: return Eng; } + AnalysisManager &getAnalysisManager() { + return Eng.getAnalysisManager(); + } + ConstraintManager &getConstraintManager() { - return Eng.getConstraintManager(); + return Eng.getConstraintManager(); } StoreManager &getStoreManager() { @@ -265,6 +269,11 @@ public: virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE) { return false; } + + virtual const GRState *EvalAssume(const GRState *state, SVal Cond, + bool Assumption) { + return state; + } }; } // end clang namespace diff --git a/include/clang/Analysis/PathSensitive/CheckerVisitor.def b/include/clang/Analysis/PathSensitive/CheckerVisitor.def index 4144d1a..7ec27ef 100644 --- a/include/clang/Analysis/PathSensitive/CheckerVisitor.def +++ b/include/clang/Analysis/PathSensitive/CheckerVisitor.def @@ -12,24 +12,27 @@ //===---------------------------------------------------------------------===// #ifndef PREVISIT -#define PREVISIT(NODE) +#define PREVISIT(NODE, FALLBACK) #endif #ifndef POSTVISIT -#define POSTVISIT(NODE) +#define POSTVISIT(NODE, FALLBACK) #endif -PREVISIT(ArraySubscriptExpr) -PREVISIT(BinaryOperator) -PREVISIT(CallExpr) -PREVISIT(CastExpr) -PREVISIT(DeclStmt) -PREVISIT(ObjCMessageExpr) -PREVISIT(ReturnStmt) +PREVISIT(ArraySubscriptExpr, Stmt) +PREVISIT(BinaryOperator, Stmt) +PREVISIT(CallExpr, Stmt) +PREVISIT(CastExpr, Stmt) +PREVISIT(CXXOperatorCallExpr, CallExpr) +PREVISIT(DeclStmt, Stmt) +PREVISIT(ObjCMessageExpr, Stmt) +PREVISIT(ReturnStmt, Stmt) -POSTVISIT(CallExpr) -POSTVISIT(BlockExpr) -POSTVISIT(BinaryOperator) +POSTVISIT(BlockExpr, Stmt) +POSTVISIT(BinaryOperator, Stmt) +POSTVISIT(CallExpr, Stmt) +POSTVISIT(CXXOperatorCallExpr, CallExpr) +POSTVISIT(ObjCMessageExpr, Stmt) #undef PREVISIT #undef POSTVISIT diff --git a/include/clang/Analysis/PathSensitive/CheckerVisitor.h b/include/clang/Analysis/PathSensitive/CheckerVisitor.h index 7cef17e..f5145bb 100644 --- a/include/clang/Analysis/PathSensitive/CheckerVisitor.h +++ b/include/clang/Analysis/PathSensitive/CheckerVisitor.h @@ -53,20 +53,20 @@ public: static_cast<const BinaryOperator*>(S)); break; -#define PREVISIT(NAME) \ +#define PREVISIT(NAME, FALLBACK) \ case Stmt::NAME ## Class:\ static_cast<ImplClass*>(this)->PreVisit ## NAME(C,static_cast<const NAME*>(S));\ break; #include "clang/Analysis/PathSensitive/CheckerVisitor.def" } } - + void PostVisit(CheckerContext &C, const Stmt *S) { switch (S->getStmtClass()) { default: assert(false && "Unsupport statement."); return; -#define POSTVISIT(NAME) \ +#define POSTVISIT(NAME, FALLBACK) \ case Stmt::NAME ## Class:\ static_cast<ImplClass*>(this)->\ PostVisit ## NAME(C,static_cast<const NAME*>(S));\ @@ -75,12 +75,19 @@ break; } } -#define PREVISIT(NAME) \ -void PreVisit ## NAME(CheckerContext &C, const NAME* S) {} + void PreVisitStmt(CheckerContext &C, const Stmt *S) {} + void PostVisitStmt(CheckerContext &C, const Stmt *S) {} + +#define PREVISIT(NAME, FALLBACK) \ +void PreVisit ## NAME(CheckerContext &C, const NAME* S) {\ + PreVisit ## FALLBACK(C, S);\ +} #include "clang/Analysis/PathSensitive/CheckerVisitor.def" -#define POSTVISIT(NAME) \ -void PostVisit ## NAME(CheckerContext &C, const NAME* S) {} +#define POSTVISIT(NAME, FALLBACK) \ +void PostVisit ## NAME(CheckerContext &C, const NAME* S) {\ + PostVisit ## FALLBACK(C, S);\ +} #include "clang/Analysis/PathSensitive/CheckerVisitor.def" }; diff --git a/include/clang/Analysis/PathSensitive/ExplodedGraph.h b/include/clang/Analysis/PathSensitive/ExplodedGraph.h index 76cab1d..fb5e1b8 100644 --- a/include/clang/Analysis/PathSensitive/ExplodedGraph.h +++ b/include/clang/Analysis/PathSensitive/ExplodedGraph.h @@ -207,7 +207,7 @@ class InterExplodedGraphMap { public: ExplodedNode* getMappedNode(const ExplodedNode* N) const; - InterExplodedGraphMap() {}; + InterExplodedGraphMap() {} virtual ~InterExplodedGraphMap() {} }; diff --git a/include/clang/Analysis/PathSensitive/GRCoreEngine.h b/include/clang/Analysis/PathSensitive/GRCoreEngine.h index b78cc6a..74f7a14 100644 --- a/include/clang/Analysis/PathSensitive/GRCoreEngine.h +++ b/include/clang/Analysis/PathSensitive/GRCoreEngine.h @@ -75,8 +75,7 @@ class GRCoreEngine { void ProcessEndPath(GREndPathNodeBuilder& Builder); - void ProcessStmt(Stmt* S, GRStmtNodeBuilder& Builder); - + void ProcessStmt(CFGElement E, GRStmtNodeBuilder& Builder); bool ProcessBlockEntrance(CFGBlock* Blk, const GRState* State, GRBlockCounter BC); @@ -212,6 +211,8 @@ public: /// of this builder. CFGBlock* getBlock() const { return &B; } + unsigned getIndex() const { return Idx; } + void setAuditor(GRAuditor* A) { Auditor = A; } const GRState* GetState(ExplodedNode* Pred) const { @@ -402,7 +403,7 @@ public: }; class GREndPathNodeBuilder { - GRCoreEngine& Eng; + GRCoreEngine &Eng; CFGBlock& B; ExplodedNode* Pred; @@ -415,6 +416,8 @@ public: ~GREndPathNodeBuilder(); + GRWorkList &getWorkList() { return *Eng.WList; } + ExplodedNode* getPredecessor() const { return Pred; } GRBlockCounter getBlockCounter() const { diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index 8b20a82..e05c624 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -25,6 +25,7 @@ #include "clang/Analysis/PathSensitive/BugReporter.h" #include "clang/AST/Type.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprCXX.h" namespace clang { @@ -79,7 +80,7 @@ class GRExprEngine : public GRSubEngine { typedef llvm::DenseMap<void *, unsigned> CheckerMap; CheckerMap CheckerM; - typedef std::vector<std::pair<void *, Checker*> >CheckersOrdered; + typedef std::vector<std::pair<void *, Checker*> > CheckersOrdered; CheckersOrdered Checkers; /// BR - The BugReporter associated with this engine. It is important that @@ -110,10 +111,10 @@ public: GRStmtNodeBuilder &getBuilder() { assert(Builder); return *Builder; } /// setTransferFunctions - void setTransferFunctions(GRTransferFuncs* tf); + void setTransferFunctionsAndCheckers(GRTransferFuncs* tf); void setTransferFunctions(GRTransferFuncs& tf) { - setTransferFunctions(&tf); + setTransferFunctionsAndCheckers(&tf); } /// ViewGraph - Visualize the ExplodedGraph created by executing the @@ -149,7 +150,7 @@ public: /// ProcessStmt - Called by GRCoreEngine. Used to generate new successor /// nodes by processing the 'effects' of a block-level statement. - void ProcessStmt(Stmt* S, GRStmtNodeBuilder& builder); + void ProcessStmt(CFGElement E, GRStmtNodeBuilder& builder); /// ProcessBlockEntrance - Called by GRCoreEngine when start processing /// a CFGBlock. This method returns true if the analysis should continue @@ -203,9 +204,10 @@ protected: } public: - ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred, const GRState* St, - ProgramPoint::Kind K = ProgramPoint::PostStmtKind, - const void *tag = 0); + ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred, + const GRState* St, + ProgramPoint::Kind K = ProgramPoint::PostStmtKind, + const void *tag = 0); protected: /// CheckerVisit - Dispatcher for performing checker-specific logic /// at specific statements. @@ -263,15 +265,11 @@ protected: /// VisitCall - Transfer function for function calls. void VisitCall(CallExpr* CE, ExplodedNode* Pred, CallExpr::arg_iterator AI, CallExpr::arg_iterator AE, - ExplodedNodeSet& Dst); - void VisitCallRec(CallExpr* CE, ExplodedNode* Pred, - CallExpr::arg_iterator AI, CallExpr::arg_iterator AE, - ExplodedNodeSet& Dst, const FunctionProtoType *, - unsigned ParamIdx = 0); + ExplodedNodeSet& Dst, bool asLValue); /// VisitCast - Transfer function logic for all casts (implicit and explicit). void VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred, - ExplodedNodeSet& Dst); + ExplodedNodeSet& Dst, bool asLValue); /// VisitCompoundLiteralExpr - Transfer function logic for compound literals. void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, ExplodedNode* Pred, @@ -295,6 +293,11 @@ protected: void VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, ExplodedNode* Pred, ExplodedNodeSet& Dst); + /// VisitCondInit - Transfer function for handling the initialization + /// of a condition variable in an IfStmt, SwitchStmt, etc. + void VisitCondInit(VarDecl *VD, Stmt *S, ExplodedNode *Pred, + ExplodedNodeSet& Dst); + void VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred, ExplodedNodeSet& Dst); @@ -315,19 +318,24 @@ protected: void VisitObjCForCollectionStmt(ObjCForCollectionStmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst); - void VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S, ExplodedNode* Pred, + void VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S, + ExplodedNode* Pred, ExplodedNodeSet& Dst, SVal ElementV); /// VisitObjCMessageExpr - Transfer function for ObjC message expressions. - void VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred, ExplodedNodeSet& Dst); + void VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); void VisitObjCMessageExprArgHelper(ObjCMessageExpr* ME, ObjCMessageExpr::arg_iterator I, ObjCMessageExpr::arg_iterator E, - ExplodedNode* Pred, ExplodedNodeSet& Dst); + ExplodedNode* Pred, ExplodedNodeSet& Dst, + bool asLValue); - void VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, ExplodedNode* Pred, - ExplodedNodeSet& Dst); + void VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, + ExplodedNode* Pred, + ExplodedNodeSet& Dst, + bool asLValue); /// VisitReturnStmt - Transfer function logic for return statements. void VisitReturnStmt(ReturnStmt* R, ExplodedNode* Pred, ExplodedNodeSet& Dst); @@ -337,8 +345,11 @@ protected: ExplodedNodeSet& Dst); /// VisitUnaryOperator - Transfer function logic for unary operators. - void VisitUnaryOperator(UnaryOperator* B, ExplodedNode* Pred, ExplodedNodeSet& Dst, - bool asLValue); + void VisitUnaryOperator(UnaryOperator* B, ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); + + void VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred, + ExplodedNodeSet & Dst); /// EvalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic /// expressions of the form 'x != 0' and generate new nodes (stored in Dst) @@ -353,9 +364,6 @@ protected: return X.isValid() ? SVator.EvalComplement(cast<NonLoc>(X)) : X; } - bool EvalBuiltinFunction(const FunctionDecl *FD, CallExpr *CE, - ExplodedNode *Pred, ExplodedNodeSet &Dst); - public: SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode op, @@ -365,7 +373,7 @@ public: SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode op, NonLoc L, SVal R, QualType T) { - return R.isValid() ? SVator.EvalBinOpNN(state, op, L, cast<NonLoc>(R), T) : R; + return R.isValid() ? SVator.EvalBinOpNN(state,op,L, cast<NonLoc>(R), T) : R; } SVal EvalBinOp(const GRState *ST, BinaryOperator::Opcode Op, @@ -399,15 +407,19 @@ public: // FIXME: 'tag' should be removed, and a LocationContext should be used // instead. - void EvalLocation(ExplodedNodeSet &Dst, Stmt *S, ExplodedNode* Pred, - const GRState* St, SVal location, - const void *tag, bool isLoad); - - // FIXME: 'tag' should be removed, and a LocationContext should be used - // instead. void EvalStore(ExplodedNodeSet& Dst, Expr* AssignE, Expr* StoreE, ExplodedNode* Pred, const GRState* St, SVal TargetLV, SVal Val, const void *tag = 0); +private: + void EvalLoadCommon(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred, + const GRState* St, SVal location, const void *tag, + QualType LoadTy); + + // FIXME: 'tag' should be removed, and a LocationContext should be used + // instead. + void EvalLocation(ExplodedNodeSet &Dst, Stmt *S, ExplodedNode* Pred, + const GRState* St, SVal location, + const void *tag, bool isLoad); }; } // end clang namespace diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h index 421ebbf..424b0d7 100644 --- a/include/clang/Analysis/PathSensitive/GRState.h +++ b/include/clang/Analysis/PathSensitive/GRState.h @@ -41,6 +41,7 @@ namespace clang { class GRStateManager; class GRTransferFuncs; +class Checker; typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&); typedef StoreManager* (*StoreManagerCreator)(GRStateManager&); @@ -160,6 +161,9 @@ public: SymbolManager &getSymbolManager() const; GRTransferFuncs &getTransferFuncs() const; + std::vector<std::pair<void *, Checker *> >::iterator checker_begin() const; + std::vector<std::pair<void *, Checker *> >::iterator checker_end() const; + //==---------------------------------------------------------------------==// // Constraints on values. //==---------------------------------------------------------------------==// @@ -418,6 +422,9 @@ private: /// for manipulating and creating SVals. GRTransferFuncs* TF; + /// Reference to all checkers in GRExprEngine. + std::vector<std::pair<void *, Checker*> > *Checkers; + public: GRStateManager(ASTContext& Ctx, @@ -441,6 +448,8 @@ public: GRTransferFuncs& getTransferFuncs() { return *TF; } + std::vector<std::pair<void *, Checker *> > &getCheckers() { return *Checkers;} + BasicValueFactory &getBasicVals() { return ValueMgr.getBasicValueFactory(); } @@ -697,6 +706,16 @@ inline GRTransferFuncs &GRState::getTransferFuncs() const { return getStateManager().getTransferFuncs(); } +inline std::vector<std::pair<void *, Checker *> >::iterator +GRState::checker_begin() const { + return getStateManager().getCheckers().begin(); +} + +inline std::vector<std::pair<void *, Checker *> >::iterator +GRState::checker_end() const { + return getStateManager().getCheckers().end(); +} + template<typename T> const GRState *GRState::add(typename GRStateTrait<T>::key_type K) const { return getStateManager().add<T>(this, K, get_context<T>()); diff --git a/include/clang/Analysis/PathSensitive/GRSubEngine.h b/include/clang/Analysis/PathSensitive/GRSubEngine.h index 62e36f9..330742d 100644 --- a/include/clang/Analysis/PathSensitive/GRSubEngine.h +++ b/include/clang/Analysis/PathSensitive/GRSubEngine.h @@ -17,6 +17,7 @@ namespace clang { class Stmt; class CFGBlock; +class CFGElement; class GRState; class GRStateManager; class GRBlockCounter; @@ -37,7 +38,7 @@ public: /// ProcessStmt - Called by GRCoreEngine. Used to generate new successor /// nodes by processing the 'effects' of a block-level statement. - virtual void ProcessStmt(Stmt* S, GRStmtNodeBuilder& builder) = 0; + virtual void ProcessStmt(CFGElement E, GRStmtNodeBuilder& builder) = 0; /// ProcessBlockEntrance - Called by GRCoreEngine when start processing /// a CFGBlock. This method returns true if the analysis should continue diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h index 2594618..b058460 100644 --- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h +++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h @@ -80,9 +80,6 @@ public: return state; } }; - -GRTransferFuncs *CreateCallInliner(ASTContext &ctx); - } // end clang namespace #endif diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h index 2fe5ea0..b57cfd7 100644 --- a/include/clang/Analysis/PathSensitive/MemRegion.h +++ b/include/clang/Analysis/PathSensitive/MemRegion.h @@ -72,8 +72,8 @@ public: VarRegionKind = BEG_DECL_REGIONS, FieldRegionKind, ObjCIvarRegionKind, - ObjCObjectRegionKind, - END_DECL_REGIONS = ObjCObjectRegionKind, + CXXObjectRegionKind, + END_DECL_REGIONS = CXXObjectRegionKind, END_TYPED_REGIONS = END_DECL_REGIONS }; @@ -662,33 +662,6 @@ public: } }; -class ObjCObjectRegion : public DeclRegion { - - friend class MemRegionManager; - - ObjCObjectRegion(const ObjCInterfaceDecl* ivd, const MemRegion* sReg) - : DeclRegion(ivd, sReg, ObjCObjectRegionKind) {} - - static void ProfileRegion(llvm::FoldingSetNodeID& ID, - const ObjCInterfaceDecl* ivd, - const MemRegion* superRegion) { - DeclRegion::ProfileRegion(ID, ivd, superRegion, ObjCObjectRegionKind); - } - -public: - const ObjCInterfaceDecl* getInterface() const { - return cast<ObjCInterfaceDecl>(D); - } - - QualType getValueType(ASTContext& C) const { - return C.getObjCInterfaceType(getInterface()); - } - - static bool classof(const MemRegion* R) { - return R->getKind() == ObjCObjectRegionKind; - } -}; - class ObjCIvarRegion : public DeclRegion { friend class MemRegionManager; @@ -752,6 +725,30 @@ public: } }; +class CXXObjectRegion : public TypedRegion { + friend class MemRegionManager; + + // T - The object type. + QualType T; + + CXXObjectRegion(QualType t, const MemRegion *sReg) + : TypedRegion(sReg, CXXObjectRegionKind), T(t) {} + + static void ProfileRegion(llvm::FoldingSetNodeID &ID, + QualType T, const MemRegion *sReg); + +public: + QualType getValueType(ASTContext& C) const { + return T; + } + + void Profile(llvm::FoldingSetNodeID &ID) const; + + static bool classof(const MemRegion* R) { + return R->getKind() == CXXObjectRegionKind; + } +}; + template<typename RegionTy> const RegionTy* MemRegion::getAs() const { if (const RegionTy* RT = dyn_cast<RegionTy>(this)) @@ -865,11 +862,6 @@ public: return getFieldRegion(FR->getDecl(), superRegion); } - /// getObjCObjectRegion - Retrieve or create the memory region associated with - /// the instance of a specified Objective-C class. - const ObjCObjectRegion* getObjCObjectRegion(const ObjCInterfaceDecl* ID, - const MemRegion* superRegion); - /// getObjCIvarRegion - Retrieve or create the memory region associated with /// a specified Objective-c instance variable. 'superRegion' corresponds /// to the containing region (which typically represents the Objective-C @@ -877,6 +869,8 @@ public: const ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl* ivd, const MemRegion* superRegion); + const CXXObjectRegion *getCXXObjectRegion(QualType T); + const FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD); const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, CanQualType locTy, diff --git a/include/clang/Analysis/PathSensitive/SVals.h b/include/clang/Analysis/PathSensitive/SVals.h index 8b5cf40..9206817 100644 --- a/include/clang/Analysis/PathSensitive/SVals.h +++ b/include/clang/Analysis/PathSensitive/SVals.h @@ -58,7 +58,7 @@ protected: public: SVal() : Data(0), Kind(0) {} - ~SVal() {}; + ~SVal() {} /// BufferTy - A temporary buffer to hold a set of SVals. typedef llvm::SmallVector<SVal,5> BufferTy; @@ -244,7 +244,8 @@ public: } static inline bool IsLocType(QualType T) { - return T->isAnyPointerType() || T->isBlockPointerType(); + return T->isAnyPointerType() || T->isBlockPointerType() || + T->isReferenceType(); } }; diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h index 648710f..52d73da 100644 --- a/include/clang/Analysis/PathSensitive/Store.h +++ b/include/clang/Analysis/PathSensitive/Store.h @@ -103,6 +103,9 @@ public: virtual SVal getLValueElement(QualType elementType, SVal offset, SVal Base)=0; + // T - the object type. + Loc getThisObject(QualType T); + // FIXME: Make out-of-line. virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state, const MemRegion *region) { @@ -201,7 +204,7 @@ public: class Visitor { public: - virtual ~Visitor() {}; + virtual ~Visitor() {} virtual bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) = 0; }; diff --git a/include/clang/Analysis/PathSensitive/ValueManager.h b/include/clang/Analysis/PathSensitive/ValueManager.h index ef4e069..9cec3c4 100644 --- a/include/clang/Analysis/PathSensitive/ValueManager.h +++ b/include/clang/Analysis/PathSensitive/ValueManager.h @@ -97,13 +97,6 @@ public: DefinedOrUnknownSVal getRegionValueSymbolVal(const MemRegion *R, QualType T = QualType()); - DefinedOrUnknownSVal getRegionValueSymbolValOrUnknown(const MemRegion *R, - QualType T) { - if (SymMgr.canSymbolicate(T)) - return getRegionValueSymbolVal(R, T); - return UnknownVal(); - } - DefinedOrUnknownSVal getConjuredSymbolVal(const void *SymbolTag, const Expr *E, unsigned Count); DefinedOrUnknownSVal getConjuredSymbolVal(const void *SymbolTag, diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index 5abe1ab..332f9d3 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -108,9 +108,13 @@ public: return const_cast<CFGBlock*>(reinterpret_cast<const CFGBlock*>(getData1())); } - Stmt* getFirstStmt() const { + CFGElement getFirstElement() const { const CFGBlock* B = getBlock(); - return B->empty() ? NULL : B->front(); + return B->empty() ? CFGElement() : B->front(); + } + + Stmt *getFirstStmt() const { + return getFirstElement().getStmt(); } static bool classof(const ProgramPoint* Location) { @@ -129,7 +133,7 @@ public: Stmt* getLastStmt() const { const CFGBlock* B = getBlock(); - return B->empty() ? NULL : B->back(); + return B->empty() ? CFGElement() : B->back(); } Stmt* getTerminator() const { diff --git a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h index afc6361..d627b88 100644 --- a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h +++ b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h @@ -20,6 +20,7 @@ #include "clang/Analysis/Visitors/CFGRecStmtVisitor.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclCXX.h" #define DISPATCH_CASE(CASE,CLASS) \ case Decl::CASE: \ @@ -55,6 +56,7 @@ public: void VisitDecl(Decl* D) { switch (D->getKind()) { DISPATCH_CASE(Function,FunctionDecl) + DISPATCH_CASE(CXXMethod,CXXMethodDecl) DISPATCH_CASE(Var,VarDecl) DISPATCH_CASE(ParmVar,ParmVarDecl) // FIXME: (same) DISPATCH_CASE(ImplicitParam,ImplicitParamDecl) @@ -69,6 +71,7 @@ public: DEFAULT_DISPATCH(VarDecl) DEFAULT_DISPATCH(FunctionDecl) + DEFAULT_DISPATCH(CXXMethodDecl) DEFAULT_DISPATCH_VARDECL(ParmVarDecl) DEFAULT_DISPATCH(ImplicitParamDecl) DEFAULT_DISPATCH(EnumConstantDecl) diff --git a/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h index 83700a3..75a4ac6 100644 --- a/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h +++ b/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h @@ -25,6 +25,25 @@ public: void VisitStmt(Stmt* S) { static_cast< ImplClass* >(this)->VisitChildren(S); } + + void VisitConditionVariableInit(Stmt *S) { + assert(S == this->getCurrentBlkStmt()); + VarDecl *CondVar = 0; + switch (S->getStmtClass()) { +#define CONDVAR_CASE(CLASS) \ +case Stmt::CLASS ## Class:\ +CondVar = cast<CLASS>(S)->getConditionVariable();\ +break; + CONDVAR_CASE(IfStmt) + CONDVAR_CASE(ForStmt) + CONDVAR_CASE(SwitchStmt) + CONDVAR_CASE(WhileStmt) +#undef CONDVAR_CASE + default: + assert(false && "Infeasible"); + } + static_cast<ImplClass*>(this)->Visit(CondVar->getInit()); + } // Defining operator() allows the visitor to be used as a C++ style functor. void operator()(Stmt* S) { static_cast<ImplClass*>(this)->BlockStmt_Visit(S);} diff --git a/include/clang/Analysis/Visitors/CFGStmtVisitor.h b/include/clang/Analysis/Visitors/CFGStmtVisitor.h index 426b9cc..8a85ec1 100644 --- a/include/clang/Analysis/Visitors/CFGStmtVisitor.h +++ b/include/clang/Analysis/Visitors/CFGStmtVisitor.h @@ -54,6 +54,13 @@ public: else return RetTy(); } + + /// VisitConditionVariableInit - Handle the initialization of condition + /// variables at branches. Valid statements include IfStmt, ForStmt, + /// WhileStmt, and SwitchStmt. + RetTy VisitConditionVariableInit(Stmt *S) { + return RetTy(); + } /// BlockVisit_XXX - Visitor methods for visiting the "root" statements in /// CFGBlocks. Root statements are the statements that appear explicitly in @@ -65,6 +72,11 @@ public: NullifyStmt cleanup(CurrentBlkStmt); switch (S->getStmtClass()) { + case Stmt::IfStmtClass: + case Stmt::ForStmtClass: + case Stmt::WhileStmtClass: + case Stmt::SwitchStmtClass: + return static_cast<ImplClass*>(this)->VisitConditionVariableInit(S); DISPATCH_CASE(StmtExpr) DISPATCH_CASE(ConditionalOperator) diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index e700cde..14f7356 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -76,9 +76,9 @@ #endif // Standard libc/libm functions: -BUILTIN(__builtin_atan2 , "ddd" , "nc") -BUILTIN(__builtin_atan2f, "fff" , "nc") -BUILTIN(__builtin_atan2l, "LdLdLd", "nc") +BUILTIN(__builtin_atan2 , "ddd" , "Fnc") +BUILTIN(__builtin_atan2f, "fff" , "Fnc") +BUILTIN(__builtin_atan2l, "LdLdLd", "Fnc") BUILTIN(__builtin_abs , "ii" , "ncF") BUILTIN(__builtin_copysign, "ddd", "ncF") BUILTIN(__builtin_copysignf, "fff", "ncF") @@ -86,36 +86,36 @@ BUILTIN(__builtin_copysignl, "LdLdLd", "ncF") BUILTIN(__builtin_fabs , "dd" , "ncF") BUILTIN(__builtin_fabsf, "ff" , "ncF") BUILTIN(__builtin_fabsl, "LdLd", "ncF") -BUILTIN(__builtin_fmod , "ddd" , "nc") -BUILTIN(__builtin_fmodf, "fff" , "nc") -BUILTIN(__builtin_fmodl, "LdLdLd", "nc") -BUILTIN(__builtin_frexp , "ddi*" , "nc") -BUILTIN(__builtin_frexpf, "ffi*" , "nc") -BUILTIN(__builtin_frexpl, "LdLdi*", "nc") +BUILTIN(__builtin_fmod , "ddd" , "Fnc") +BUILTIN(__builtin_fmodf, "fff" , "Fnc") +BUILTIN(__builtin_fmodl, "LdLdLd", "Fnc") +BUILTIN(__builtin_frexp , "ddi*" , "Fnc") +BUILTIN(__builtin_frexpf, "ffi*" , "Fnc") +BUILTIN(__builtin_frexpl, "LdLdi*", "Fnc") BUILTIN(__builtin_huge_val, "d", "nc") BUILTIN(__builtin_huge_valf, "f", "nc") BUILTIN(__builtin_huge_vall, "Ld", "nc") BUILTIN(__builtin_inf , "d" , "nc") BUILTIN(__builtin_inff , "f" , "nc") BUILTIN(__builtin_infl , "Ld" , "nc") -BUILTIN(__builtin_ldexp , "ddi" , "nc") -BUILTIN(__builtin_ldexpf, "ffi" , "nc") -BUILTIN(__builtin_ldexpl, "LdLdi", "nc") -BUILTIN(__builtin_modf , "ddd*" , "nc") -BUILTIN(__builtin_modff, "fff*" , "nc") -BUILTIN(__builtin_modfl, "LdLdLd*", "nc") +BUILTIN(__builtin_ldexp , "ddi" , "Fnc") +BUILTIN(__builtin_ldexpf, "ffi" , "Fnc") +BUILTIN(__builtin_ldexpl, "LdLdi", "Fnc") +BUILTIN(__builtin_modf , "ddd*" , "Fnc") +BUILTIN(__builtin_modff, "fff*" , "Fnc") +BUILTIN(__builtin_modfl, "LdLdLd*", "Fnc") BUILTIN(__builtin_nan, "dcC*" , "ncF") BUILTIN(__builtin_nanf, "fcC*" , "ncF") BUILTIN(__builtin_nanl, "LdcC*", "ncF") BUILTIN(__builtin_nans, "dcC*" , "ncF") BUILTIN(__builtin_nansf, "fcC*" , "ncF") BUILTIN(__builtin_nansl, "LdcC*", "ncF") -BUILTIN(__builtin_powi , "ddi" , "nc") -BUILTIN(__builtin_powif, "ffi" , "nc") -BUILTIN(__builtin_powil, "LdLdi", "nc") -BUILTIN(__builtin_pow , "ddd" , "nc") -BUILTIN(__builtin_powf, "fff" , "nc") -BUILTIN(__builtin_powl, "LdLdLd", "nc") +BUILTIN(__builtin_powi , "ddi" , "Fnc") +BUILTIN(__builtin_powif, "ffi" , "Fnc") +BUILTIN(__builtin_powil, "LdLdi", "Fnc") +BUILTIN(__builtin_pow , "ddd" , "Fnc") +BUILTIN(__builtin_powf, "fff" , "Fnc") +BUILTIN(__builtin_powl, "LdLdLd", "Fnc") // Standard unary libc/libm functions with double/float/long double variants: BUILTIN(__builtin_acos , "dd" , "Fnc") @@ -142,6 +142,9 @@ BUILTIN(__builtin_expl, "LdLd", "Fnc") BUILTIN(__builtin_floor , "dd" , "Fnc") BUILTIN(__builtin_floorf, "ff" , "Fnc") BUILTIN(__builtin_floorl, "LdLd", "Fnc") +BUILTIN(__builtin_hypot , "ddd" , "Fnc") +BUILTIN(__builtin_hypotf, "fff" , "Fnc") +BUILTIN(__builtin_hypotl, "LdLdLd", "Fnc") BUILTIN(__builtin_log , "dd" , "Fnc") BUILTIN(__builtin_log10 , "dd" , "Fnc") BUILTIN(__builtin_log10f, "ff" , "Fnc") @@ -475,6 +478,7 @@ BUILTIN(__sync_fetch_and_umax, "UiUi*Ui", "n") // C99 library functions // C99 stdlib.h +LIBBUILTIN(abort, "v", "fr", "stdlib.h") LIBBUILTIN(calloc, "v*zz", "f", "stdlib.h") LIBBUILTIN(exit, "vi", "fr", "stdlib.h") LIBBUILTIN(_Exit, "vi", "fr", "stdlib.h") diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index b2523f2..a2ccea7 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -45,7 +45,7 @@ namespace clang { DIAG_START_PARSE = DIAG_START_LEX + 300, DIAG_START_AST = DIAG_START_PARSE + 300, DIAG_START_SEMA = DIAG_START_AST + 100, - DIAG_START_ANALYSIS = DIAG_START_SEMA + 1100, + DIAG_START_ANALYSIS = DIAG_START_SEMA + 1500, DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100 }; @@ -76,7 +76,10 @@ namespace clang { /// Map this diagnostic to "warning", but make it immune to -Werror. This /// happens when you specify -Wno-error=foo. - MAP_WARNING_NO_WERROR = 5 + MAP_WARNING_NO_WERROR = 5, + /// Map this diagnostic to "error", but make it immune to -Wfatal-errors. + /// This happens for -Wno-fatal-errors=foo. + MAP_ERROR_NO_WFATAL = 6 }; } @@ -178,6 +181,7 @@ private: unsigned char AllExtensionsSilenced; // Used by __extension__ bool IgnoreAllWarnings; // Ignore all warnings: -w bool WarningsAsErrors; // Treat warnings like errors: + bool ErrorsAsFatal; // Treat errors like fatal errors. bool SuppressSystemWarnings; // Suppress warnings in system headers. bool SuppressAllDiagnostics; // Suppress all diagnostics. ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors? @@ -260,6 +264,11 @@ public: void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; } bool getWarningsAsErrors() const { return WarningsAsErrors; } + /// setErrorsAsFatal - When set to true, any error reported is made a + /// fatal error. + void setErrorsAsFatal(bool Val) { ErrorsAsFatal = Val; } + bool getErrorsAsFatal() const { return ErrorsAsFatal; } + /// setSuppressSystemWarnings - When set to true mask warnings that /// come from system headers. void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; } diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index f319cf2..7e14a32 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -56,6 +56,7 @@ def note_invalid_subexpr_in_ice : Note< def err_target_unknown_triple : Error< "unknown target triple '%0', please use -triple or -arch">; +def err_target_unknown_cpu : Error<"unknown target CPU '%0'">; def err_target_unknown_abi : Error<"unknown target ABI '%0'">; def err_target_invalid_feature : Error<"invalid target feature '%0'">; diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 252900d..66a841a 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -219,4 +219,7 @@ def err_not_a_pch_file : Error< def warn_unknown_warning_option : Warning< "unknown warning option '%0'">, InGroup<DiagGroup<"unknown-warning-option"> >; +def warn_unknown_warning_specifier : Warning< + "unknown %0 warning specifier: '%1'">, + InGroup<DiagGroup<"unknown-warning-option"> >; } diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 761478a..03aad86 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -171,8 +171,9 @@ def Most : DiagGroup<"most", [ def : DiagGroup<"all", [Most, Parentheses]>; // Aliases. -def : DiagGroup<"", [Extra]>; // -W = -Wextra -def : DiagGroup<"endif-labels", [ExtraTokens]>; // endif-labels = endif-tokens +def : DiagGroup<"", [Extra]>; // -W = -Wextra +def : DiagGroup<"endif-labels", [ExtraTokens]>; // -Wendif-labels=-Wendif-tokens +def : DiagGroup<"comments", [Comment]>; // -Wcomments = -Wcomment // A warning group for warnings that we want to have on by default in clang, // but which aren't on by default in GCC. diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index bf188cf..98a74a5 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -229,6 +229,8 @@ def warn_parens_disambiguated_as_function_decl : Warning< "parentheses were disambiguated as a function declarator">; def err_expected_member_or_base_name : Error< "expected class member or base class name">; +def err_expected_lbrace_after_base_specifiers : Error< + "expected '{' after base class list">; def ext_ellipsis_exception_spec : Extension< "exception specification of '...' is a Microsoft extension">; def err_expected_catch : Error<"expected catch">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index a890323..155633b 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -26,9 +26,13 @@ def ext_null_pointer_expr_not_ice : Extension< -// Semantic analysis of string and character constant literals. +// Semantic analysis of constant literals. def ext_predef_outside_function : Warning< "predefined identifier is only valid inside function">; +def err_float_overflow : Error< + "magnitude of floating-point constant too large for type %0; maximum is %1">; +def err_float_underflow : Error< + "magnitude of floating-point constant too small for type %0; minimum is %1">; // C99 Designated Initializers def err_array_designator_negative : Error< @@ -182,11 +186,12 @@ def warn_unusual_main_decl : Warning<"'main' should not be declared " def err_unusual_main_decl : Error<"'main' is not allowed to be declared " "%select{static|inline|static or inline}0">; def err_main_returns_nonint : Error<"'main' must return 'int'">; -def err_main_surplus_args : Error<"%0 is too many arguments for 'main': " +def err_main_surplus_args : Error<"too many parameters (%0) for 'main': " "must be 0, 2, or 3">; -def warn_main_one_arg : Warning<"one-argument 'main' is usually a mistake">; -def err_main_arg_wrong : Error<"%select{first|second|third}0 argument of " - "'main' should be of type %1">; +def warn_main_one_arg : Warning<"only one parameter on 'main' declaration">; +def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 " + "parameter of 'main' (%select{argument count|argument array|environment|" + "platform-specific data}0) must be of type %1">; /// parser diagnostics def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">; @@ -305,6 +310,8 @@ def note_property_declare : Note< "property declared here">; def error_synthesize_category_decl : Error< "@synthesize not allowed in a category's implementation">; +def error_reference_property : Error< + "property of reference type is not supported">; def error_missing_property_interface : Error< "property implementation in a category with no category declaration">; def error_bad_category_property_decl : Error< @@ -349,8 +356,6 @@ def err_enum_friend : Error< "enum types cannot be friends">; def err_friend_is_member : Error< "friends cannot be members of the declaring class">; -def ext_friend_inner_class : Extension< - "C++ 98 does not allow inner classes as friends">; def err_unelaborated_friend_type : Error< "must specify '%select{struct|union|class|enum}0' to befriend %1">; def err_qualified_friend_not_found : Error< @@ -492,6 +497,9 @@ def err_covariant_return_ambiguous_derived_to_base_conv : Error< def err_covariant_return_not_derived : Error< "return type of virtual function %0 is not covariant with the return type of " "the function it overrides (%1 is not derived from %2)">; +def err_covariant_return_incomplete : Error< + "return type of virtual function %0 is not covariant with the return type of " + "the function it overrides (%1 is incomplete)">; def err_covariant_return_type_different_qualifications : Error< "return type of virtual function %0 is not covariant with the return type of " "the function it overrides (%1 has different qualifiers than %2)">; @@ -525,15 +533,19 @@ def err_destructor_name : Error< "expected the class name after '~' to name the enclosing class">; // C++ initialization +def err_init_conversion_failed : Error< + "cannot initialize %select{a variable|a parameter|return object|an " + "exception object|a value|a base class|a member subobject|an array element}0" + " of type %1 with an %select{rvalue|lvalue}2 of type %3">; + def err_lvalue_to_rvalue_ref : Error<"rvalue reference cannot bind to lvalue">; def err_invalid_initialization : Error< "invalid initialization of reference of type %0 from expression of type %1">; def err_lvalue_to_rvalue_ambig_ref : Error<"rvalue reference cannot bind to lvalue " "due to multiple conversion functions">; -// FIXME: passing in an English string as %1! def err_not_reference_to_const_init : Error< "non-const lvalue reference to type %0 cannot be initialized " - "with a %1 of type %2">; + "with a %select{value|temporary}1 of type %2">; def err_lvalue_reference_bind_to_temporary : Error< "non-const lvalue reference to type %0 cannot bind to a temporary of type " "%1">; @@ -551,9 +563,8 @@ def err_init_list_bad_dest_type : Error< "%select{|non-aggregate }0type %1 cannot be initialized with an initializer " "list">; -// FIXME: passing in an English string as %1! def err_reference_init_drops_quals : Error< - "initialization of reference to type %0 with a %1 of type %2 drops " + "initialization of reference to type %0 with a %select{value|temporary}1 of type %2 drops " "qualifiers">; def err_reference_bind_to_bitfield : Error< "%select{non-const|volatile}0 reference cannot bind to bit-field %1">; @@ -572,9 +583,20 @@ def note_uninit_reference_member : Note< def warn_field_is_uninit : Warning<"field is uninitialized when used here">, InGroup<DiagGroup<"uninitialized">>; +def err_temp_copy_no_viable : Error< + "no viable copy constructor %select{copying variable|copying parameter|" + "returning object|throwing object}0 of type %1">; +def err_temp_copy_ambiguous : Error< + "ambiguous copy constructor call when %select{copying variable|copying " + "parameter|returning object|throwing object}0 of type %1">; +def err_temp_copy_deleted : Error< + "%select{copying variable|copying parameter|returning object|throwing " + "object}0 of type %1 invokes deleted copy constructor">; + // C++0x decltype def err_cannot_determine_declared_type_of_overloaded_function : Error< - "can't determine the declared type of an overloaded function">; + "cannot determine the %select{type|declared type}0 of an overloaded " + "function">; // C++0x auto def err_auto_variable_cannot_appear_in_own_initializer : Error< @@ -641,8 +663,6 @@ def err_unsupported_vector_size : Error< "unsupported type %0 for vector_size attribute, please use on typedef">; def err_ext_vector_component_exceeds_length : Error< "vector component access exceeds type %0">; -def err_ext_vector_component_requires_even : Error< - "vector component access invalid for odd-sized type %0">; def err_ext_vector_component_name_illegal : Error< "illegal vector component name '%0'">; def err_attribute_address_space_not_int : Error< @@ -670,6 +690,8 @@ def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning< def warn_attribute_ignored : Warning<"%0 attribute ignored">; def warn_attribute_precede_definition : Warning< "attribute declaration must precede definition">; +def warn_attribute_void_function : Warning< + "attribute %0 cannot be applied to functions without return value">; def warn_attribute_weak_on_field : Warning< "__weak attribute cannot be specified on a field declaration">; def warn_attribute_weak_on_local : Warning< @@ -994,6 +1016,8 @@ def err_template_arg_unnamed_type : Error< "template argument uses unnamed type">; def note_template_unnamed_type_here : Note< "unnamed type used in template argument was declared here">; +def err_template_arg_overload_type : Error< + "template argument is the type of an unresolved overloaded function">; def err_template_arg_not_class_template : Error< "template argument does not refer to a class template or template " "template parameter">; @@ -1283,7 +1307,9 @@ def err_unexpected_typedef : Error< def err_unexpected_namespace : Error< "unexpected namespace name %0: expected expression">; def err_undeclared_var_use : Error<"use of undeclared identifier %0">; -def err_undeclared_use : Error<"use of undeclared '%0'">; +def note_dependent_var_use : Note<"must qualify identifier to find this " + "declaration in dependent base class">; +def err_undeclared_use : Error<"use of undeclared %0">; def warn_deprecated : Warning<"%0 is deprecated">, InGroup<DiagGroup<"deprecated-declarations">>; def warn_unavailable : Warning<"%0 is unavailable">, @@ -1365,6 +1391,8 @@ def warn_typecheck_function_qualifiers : Warning< "qualifier on function type %0 has unspecified behavior">; def err_typecheck_invalid_restrict_not_pointer : Error< "restrict requires a pointer or reference (%0 is invalid)">; +def err_typecheck_invalid_restrict_not_pointer_noarg : Error< + "restrict requires a pointer or reference">; def err_typecheck_invalid_restrict_invalid_pointee : Error< "pointer to function type %0 may not be 'restrict' qualified">; def ext_typecheck_zero_array_size : Extension< @@ -1497,11 +1525,8 @@ def ext_sizeof_function_type : Extension< "invalid application of 'sizeof' to a function type">, InGroup<PointerArith>; def ext_sizeof_void_type : Extension< "invalid application of '%0' to a void type">, InGroup<PointerArith>; -// FIXME: merge with %select -def err_sizeof_incomplete_type : Error< - "invalid application of 'sizeof' to an incomplete type %0">; -def err_alignof_incomplete_type : Error< - "invalid application of '__alignof' to an incomplete type %0">; +def err_sizeof_alignof_incomplete_type : Error< + "invalid application of '%select{sizeof|__alignof}0' to an incomplete type %1">; def err_sizeof_alignof_bitfield : Error< "invalid application of '%select{sizeof|__alignof}0' to bit-field">; def err_offsetof_incomplete_type : Error< @@ -1586,9 +1611,8 @@ def err_out_of_line_declaration : Error< def note_member_def_close_match : Note<"member declaration nearly matches">; def err_typecheck_ivar_variable_size : Error< "instance variables must have a constant size">; -// FIXME: Improve with %select def err_typecheck_illegal_increment_decrement : Error< - "cannot modify value of type %0">; + "cannot %select{decrement|increment}1 value of type %0">; def err_typecheck_arithmetic_incomplete_type : Error< "arithmetic on pointer to incomplete type %0">; def err_typecheck_pointer_arith_function_type : Error< @@ -1609,7 +1633,7 @@ def err_typecheck_incomplete_array_needs_initializer : Error< "definition of variable with array type needs an explicit size " "or an initializer">; def err_array_init_not_init_list : Error< - "array initializater must be an initializer " + "array initializer must be an initializer " "list%select{| or string literal}0">; def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">; @@ -1699,6 +1723,8 @@ def err_unexpected_interface : Error< def err_ref_non_value : Error<"%0 does not refer to a value">; def err_property_not_found : Error< "property %0 not found on object of type %1">; +def err_duplicate_property : Error< + "property has a previous declaration">; def ext_gnu_void_ptr : Extension< "use of GNU void* extension">, InGroup<PointerArith>; def ext_gnu_ptr_func_arith : Extension< @@ -1712,6 +1738,8 @@ def ext_integer_complement_complex : Extension< "ISO C does not support '~' for complex conjugation of %0">; def error_nosetter_property_assignment : Error< "setter method is needed to assign to object using property" " assignment syntax">; +def error_no_subobject_property_setting : Error< + "cannot assign to a sub-structure of an ivar using property" " assignment syntax">; def ext_freestanding_complex : Extension< "complex numbers are an extension in a freestanding C99 implementation">; @@ -1810,6 +1838,7 @@ def err_bad_dynamic_cast_not_polymorphic : Error<"%0 is not polymorphic">; // Other C++ expressions def err_need_header_before_typeid : Error< "you need to include <typeinfo> before using the 'typeid' operator">; +def err_incomplete_typeid : Error<"'typeid' of incomplete type %0">; def err_static_illegal_in_new : Error< "the 'static' modifier for the array size is not legal in new expressions">; def err_array_new_needs_size : Error< @@ -1824,8 +1853,8 @@ def err_new_paren_array_nonconst : Error< "when type is in parentheses, array cannot have dynamic size">; def err_array_size_not_integral : Error< "array size expression must have integral or enumerated type, not %0">; -def err_new_uninitialized_const : Error< - "must provide an initializer if the allocated object is 'const'">; +def err_default_init_const : Error< + "default initialization of an object of const type %0">; def err_delete_operand : Error<"cannot delete expression of type %0">; def err_ambiguous_delete_operand : Error<"ambiguous conversion of delete " "expression of type %0 to a pointer">; @@ -1928,9 +1957,11 @@ def warn_value_always_zero : Warning< "%0 is always %select{zero|false|NULL}1 in this context">; // assignment related diagnostics (also for argument passing, returning, etc). -// FIXME: %2 is an english string here. +// In most of these diagnostics the %2 is a value from the +// Sema::AssignmentAction enumeration def err_typecheck_convert_incompatible : Error< - "incompatible type %2 %1, expected %0">; + "incompatible type %select{assigning|passing|returning|converting|initializing|sending|casting}2" + " %1, expected %0">; def err_typecheck_convert_ambiguous : Error< "ambiguity in initializing value of type %0 with initializer of type %1">; def err_cannot_initialize_decl_noname : Error< @@ -1939,31 +1970,43 @@ def err_cannot_initialize_decl_noname : Error< def err_cannot_initialize_decl : Error< "cannot initialize %0 with an %select{rvalue|lvalue}1 of type %2">; def warn_incompatible_qualified_id : Warning< - "incompatible type %2 %1, expected %0">; + "incompatible type %select{assigning|passing|returning|converting|initializing|sending|casting}2" + " %1, expected %0">; def ext_typecheck_convert_pointer_int : ExtWarn< - "incompatible pointer to integer conversion %2 %1, expected %0">; + "incompatible pointer to integer conversion " + "%select{assigning|passing|returning|converting|initializing|sending|casting}2 %1, expected %0">; def ext_typecheck_convert_int_pointer : ExtWarn< - "incompatible integer to pointer conversion %2 %1, expected %0">; + "incompatible integer to pointer conversion " + "%select{assigning|passing|returning|converting|initializing|sending|casting}2 %1, expected %0">; def ext_typecheck_convert_pointer_void_func : Extension< - "%2 %1 converts between void* and function pointer, expected %0">; + "%select{assigning|passing|returning|converting|initializing|sending|casting}2" + " %1 converts between void* and function pointer, expected %0">; def ext_typecheck_convert_incompatible_pointer_sign : ExtWarn< - "pointer types point to integer types with different sign %2 %1, expected %0">, + "pointer types point to integer types with different sign " + "%select{assigning|passing|returning|converting|initializing|sending|casting}2 %1, expected %0">, InGroup<DiagGroup<"pointer-sign">>; def ext_typecheck_convert_incompatible_pointer : ExtWarn< - "incompatible pointer types %2 %1, expected %0">; + "incompatible pointer types " + "%select{assigning|passing|returning|converting|initializing|sending|casting}2 %1, expected %0">; def ext_typecheck_convert_discards_qualifiers : ExtWarn< - "%2 %1 discards qualifiers, expected %0">; + "%select{assigning|passing|returning|converting|initializing|sending|casting}2" + " %1 discards qualifiers, expected %0">; def ext_nested_pointer_qualifier_mismatch : ExtWarn< - "%2, %0 and %1 have different qualifiers in nested pointer types">; + "%select{assigning|passing|returning|converting|initializing|sending|casting}2," + " %0 and %1 have different qualifiers in nested pointer types">; def warn_incompatible_vectors : Warning< - "incompatible vector types %2 %1, expected %0">, + "incompatible vector types %select{assigning|passing|returning|converting|initializing|sending|casting}2" + " %1, expected %0">, InGroup<VectorConversions>, DefaultIgnore; def err_int_to_block_pointer : Error< - "invalid conversion %2 integer %1, expected block pointer %0">; + "invalid conversion " + "%select{assigning|passing|returning|converting|initializing|sending|casting}2" + " integer %1, expected block pointer %0">; def err_typecheck_comparison_of_distinct_blocks : Error< "comparison of distinct block types (%0 and %1)">; def err_typecheck_convert_incompatible_block_pointer : Error< - "incompatible block pointer types %2 %1, expected %0">; + "incompatible block pointer types " + "%select{assigning|passing|returning|converting|initializing|sending|casting}2 %1, expected %0">; def err_typecheck_array_not_modifiable_lvalue : Error< "array type %0 is not assignable">; @@ -2506,4 +2549,27 @@ def warn_attribute_method_def : Warning< def ext_typecheck_base_super : Warning< "method parameter type %0 does not match " "super class method parameter type %1">, InGroup<SuperSubClassMismatch>, DefaultIgnore; + +// Spell-checking diagnostics +def err_unknown_typename_suggest : Error< + "unknown type name %0; did you mean %1?">; +def err_unknown_nested_typename_suggest : Error< + "no type named %0 in %1; did you mean %2?">; +def err_no_member_suggest : Error<"no member named %0 in %1; did you mean %2?">; +def err_undeclared_use_suggest : Error< + "use of undeclared %0; did you mean %1?">; +def err_undeclared_var_use_suggest : Error< + "use of undeclared identifier %0; did you mean %1?">; +def err_no_template_suggest : Error<"no template named %0; did you mean %1?">; +def err_no_member_template_suggest : Error< + "no template named %0 in %1; did you mean %2?">; +def err_mem_init_not_member_or_class_suggest : Error< + "initializer %0 does not name a non-static data member or base " + "class; did you mean the %select{base class|member}1 %2?">; +def err_field_designator_unknown_suggest : Error< + "field designator %0 does not refer to any field in type %1; did you mean " + "%2?">; + } + + diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index e17279e..2b6092d 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -89,7 +89,10 @@ public: unsigned ShortWChar : 1; // Force wchar_t to be unsigned short int. unsigned OpenCL : 1; // OpenCL C99 language extensions. - + + unsigned AssumeSaneOperatorNew : 1; // Whether to add __attribute__((malloc)) + // to the declaration of C++'s new + // operators unsigned ElideConstructors : 1; // Whether C++ copy constructors should be // elided if possible. unsigned CatchUndefined :1; // Generate code to check for undefined ops. @@ -141,6 +144,8 @@ public: EmitAllDecls = 0; MathErrno = 1; + AssumeSaneOperatorNew = 1; + // FIXME: The default should be 1. AccessControl = 0; ElideConstructors = 1; diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 49eaafe..0d95e6a 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -61,8 +61,11 @@ protected: public: /// CreateTargetInfo - Construct a target for the given options. - static TargetInfo* CreateTargetInfo(Diagnostic &Diags, - const TargetOptions &Opts); + /// + /// \param Opts - The options to use to initialize the target. The target may + /// modify the options to canonicalize the target feature information to match + /// what the backend expects. + static TargetInfo* CreateTargetInfo(Diagnostic &Diags, TargetOptions &Opts); virtual ~TargetInfo(); @@ -360,6 +363,15 @@ public: return ""; } + /// setCPU - Target the specific CPU. + /// + /// \return - False on error (invalid CPU name). + // + // FIXME: Remove this. + virtual bool setCPU(const std::string &Name) { + return true; + } + /// setABI - Use the specific ABI. /// /// \return - False on error (invalid ABI name). @@ -380,7 +392,10 @@ public: /// HandleTargetOptions - Perform initialization based on the user configured /// set of features (e.g., +sse4). The list is guaranteed to have at most one /// entry per feature. - virtual void HandleTargetFeatures(const std::vector<std::string> &Features) { + /// + /// The target may modify the features list, to change which options are + /// passed onwards to the backend. + virtual void HandleTargetFeatures(std::vector<std::string> &Features) { } // getRegParmMax - Returns maximal number of args passed in registers. diff --git a/include/clang/CodeGen/CodeGenOptions.h b/include/clang/CodeGen/CodeGenOptions.h index c8fb37b..8682715 100644 --- a/include/clang/CodeGen/CodeGenOptions.h +++ b/include/clang/CodeGen/CodeGenOptions.h @@ -58,6 +58,10 @@ public: /// Enable additional debugging information. std::string DebugPass; + /// The string to embed in the debug information for the compile unit, if + /// non-empty. + std::string DwarfDebugFlags; + /// The ABI to use for passing floating point arguments. std::string FloatABI; diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index a9566f3..6a0d816 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -20,8 +20,8 @@ include "OptParser.td" def target_abi : Separate<"-target-abi">, HelpText<"Target a particular ABI type">; -def mcpu : Separate<"-mcpu">, - HelpText<"Target a specific cpu type ('-mcpu help' for details)">; +def target_cpu : Separate<"-target-cpu">, + HelpText<"Target a specific cpu type">; def target_feature : Separate<"-target-feature">, HelpText<"Target specific attributes">; def triple : Separate<"-triple">, @@ -104,6 +104,8 @@ 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 dwarf_debug_flags : Separate<"-dwarf-debug-flags">, + HelpText<"The string to embed in the Dwarf debug flags record.">; def g : Flag<"-g">, HelpText<"Generate source level debug information">; def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">, HelpText<"Generate runtime checks for undefined behavior.">; @@ -282,8 +284,6 @@ 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">; } @@ -304,8 +304,12 @@ def faltivec : Flag<"-faltivec">, HelpText<"Enable AltiVec vector initializer syntax">; def faccess_control : Flag<"-faccess-control">, HelpText<"Enable C++ access control">; +def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">, + HelpText<"Don't assume that C++'s global operator new can't alias any pointer">; def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, HelpText<"Allow '$' in identifiers">; +def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, + HelpText<"Disallow '$' in identifiers">; def femit_all_decls : Flag<"-femit-all-decls">, HelpText<"Emit all declarations, even if unused">; def fblocks : Flag<"-fblocks">, diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 3592fc9..247e1f5 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -17,23 +17,27 @@ include "OptParser.td" ///////// // Groups -def I_Group : OptionGroup<"<I group>">; -def M_Group : OptionGroup<"<M group>">; +// Meta-group which defines +def CompileOnly_Group : OptionGroup<"<CompileOnly group>">; + +def I_Group : OptionGroup<"<I group>">, Group<CompileOnly_Group>; +def M_Group : OptionGroup<"<M group>">, Group<CompileOnly_Group>; def T_Group : OptionGroup<"<T group>">; -def O_Group : OptionGroup<"<O group>">; -def W_Group : OptionGroup<"<W group>">; +def O_Group : OptionGroup<"<O group>">, Group<CompileOnly_Group>; +def W_Group : OptionGroup<"<W group>">, Group<CompileOnly_Group>; def X_Group : OptionGroup<"<X group>">; def a_Group : OptionGroup<"<a group>">; def d_Group : OptionGroup<"<d group>">; -def f_Group : OptionGroup<"<f group>">; +def f_Group : OptionGroup<"<f group>">, Group<CompileOnly_Group>; def g_Group : OptionGroup<"<g group>">; -def i_Group : OptionGroup<"<i group>">; +def i_Group : OptionGroup<"<i group>">, Group<CompileOnly_Group>; def clang_i_Group : OptionGroup<"<clang i group>">, Group<i_Group>; -def m_Group : OptionGroup<"<m group>">; -def m_x86_Features_Group : OptionGroup<"<m x86 features group>">; +def m_Group : OptionGroup<"<m group>">, Group<CompileOnly_Group>; +def m_x86_Features_Group : OptionGroup<"<m x86 features group>">, Group<m_Group>; def u_Group : OptionGroup<"<u group>">; -def pedantic_Group : OptionGroup<"<pedantic group>">; +def pedantic_Group : OptionGroup<"<pedantic group>">, + Group<CompileOnly_Group>; // Temporary groups for clang options which we know we don't support, // but don't want to verbosely warn the user about. @@ -116,7 +120,7 @@ def A : JoinedOrSeparate<"-A">; def B : JoinedOrSeparate<"-B">, Flags<[Unsupported]>; def CC : Flag<"-CC">; def C : Flag<"-C">; -def D : JoinedOrSeparate<"-D">; +def D : JoinedOrSeparate<"-D">, Group<CompileOnly_Group>; def E : Flag<"-E">, Flags<[DriverOption]>, HelpText<"Only run the preprocessor">; def F : JoinedOrSeparate<"-F">; @@ -152,7 +156,7 @@ def Tbss : JoinedOrSeparate<"-Tbss">, Group<T_Group>; def Tdata : JoinedOrSeparate<"-Tdata">, Group<T_Group>; def Ttext : JoinedOrSeparate<"-Ttext">, Group<T_Group>; def T : JoinedOrSeparate<"-T">, Group<T_Group>; -def U : JoinedOrSeparate<"-U">; +def U : JoinedOrSeparate<"-U">, Group<CompileOnly_Group>; def V : JoinedOrSeparate<"-V">, Flags<[DriverOption, Unsupported]>; def Wa_COMMA : CommaJoined<"-Wa,">, HelpText<"Pass the comma separated arguments in <arg> to the assembler">, @@ -226,6 +230,7 @@ def fPIC : Flag<"-fPIC">, Group<f_Group>; def fPIE : Flag<"-fPIE">, Group<f_Group>; def fapple_kext : Flag<"-fapple-kext">, Group<f_Group>; def fasm_blocks : Flag<"-fasm-blocks">, Group<clang_ignored_f_Group>; +def fassume_sane_operator_new : Flag<"-fassume-sane-operator-new">, Group<f_Group>; def fastcp : Flag<"-fastcp">, Group<f_Group>; def fastf : Flag<"-fastf">, Group<f_Group>; def fast : Flag<"-fast">, Group<f_Group>; @@ -277,6 +282,7 @@ def fmudflap : Flag<"-fmudflap">, Group<f_Group>; def fnested_functions : Flag<"-fnested-functions">, Group<f_Group>; def fnext_runtime : Flag<"-fnext-runtime">, Group<f_Group>; def fno_asynchronous_unwind_tables : Flag<"-fno-asynchronous-unwind-tables">, Group<f_Group>; +def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">, Group<f_Group>; def fno_blocks : Flag<"-fno-blocks">, Group<f_Group>; def fno_builtin_strcat : Flag<"-fno-builtin-strcat">, Group<f_Group>; def fno_builtin_strcpy : Flag<"-fno-builtin-strcpy">, Group<f_Group>; @@ -389,6 +395,7 @@ def mcpu_EQ : Joined<"-mcpu=">, Group<m_Group>, Flags<[DriverOption]>; def mdynamic_no_pic : Joined<"-mdynamic-no-pic">, Group<m_Group>, Flags<[NoArgumentUnused]>; def mfix_and_continue : Flag<"-mfix-and-continue">, Group<clang_ignored_m_Group>; def mfloat_abi_EQ : Joined<"-mfloat-abi=">, Group<m_Group>; +def mfpu_EQ : Joined<"-mfpu=">, Group<m_Group>; def mhard_float : Flag<"-mhard-float">, Group<m_Group>; def miphoneos_version_min_EQ : Joined<"-miphoneos-version-min=">, Group<m_Group>; def mkernel : Flag<"-mkernel">, Group<m_Group>; diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index df651a6..b3c2d05 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -19,6 +19,7 @@ namespace clang { namespace driver { class Compilation; class DerivedArgList; + class Driver; class HostInfo; class InputArgList; class JobAction; @@ -49,7 +50,7 @@ public: // Accessors - const HostInfo &getHost() const { return Host; } + const Driver &getDriver() const; const llvm::Triple &getTriple() const { return Triple; } std::string getArchName() const { return Triple.getArchName(); } @@ -113,6 +114,10 @@ public: /// for this tool chain, or 0 if this tool chain does not force a /// particular PIC mode. virtual const char *GetForcedPicModel() const = 0; + + /// UseDwarfDebugFlags - Embed the compile options to clang into the Dwarf + /// compile unit information. + virtual bool UseDwarfDebugFlags() const { return false; } }; } // end namespace driver diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h index 20bf83e..978b0d2 100644 --- a/include/clang/Frontend/ASTConsumers.h +++ b/include/clang/Frontend/ASTConsumers.h @@ -101,12 +101,6 @@ ASTConsumer *CreatePCHGenerator(const Preprocessor &PP, llvm::raw_ostream *OS, const char *isysroot = 0); -// Block rewriter: rewrites code using the Apple blocks extension to pure -// C code. Output is always sent to stdout. -ASTConsumer *CreateBlockRewriter(const std::string &InFile, - Diagnostic &Diags, - const LangOptions &LangOpts); - // Inheritance viewer: for C++ code, creates a graph of the inheritance // tree for the given class and displays it with "dotty". ASTConsumer *CreateInheritanceViewer(const std::string& clsname); diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h index e755fe1..33bb8aa 100644 --- a/include/clang/Frontend/FrontendActions.h +++ b/include/clang/Frontend/FrontendActions.h @@ -110,12 +110,6 @@ protected: llvm::StringRef InFile); }; -class RewriteBlocksAction : public ASTFrontendAction { -protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - llvm::StringRef InFile); -}; - class SyntaxOnlyAction : public ASTFrontendAction { protected: virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index 36fea7f..735a86a 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -41,7 +41,6 @@ namespace frontend { PluginAction, ///< Run a plugin action, \see ActionName. PrintDeclContext, ///< Print DeclContext and their Decls. PrintPreprocessedInput, ///< -E mode. - RewriteBlocks, ///< ObjC->C Rewriter for Blocks. RewriteMacros, ///< Expand macros but not #includes. RewriteObjC, ///< ObjC->C Rewriter. RewriteTest, ///< Rewriter playground diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index c8c49c8..536bd41 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -357,8 +357,6 @@ namespace clang { enum TypeCode { /// \brief An ExtQualType record. TYPE_EXT_QUAL = 1, - /// \brief A FixedWidthIntType record. - TYPE_FIXED_WIDTH_INT = 2, /// \brief A ComplexType record. TYPE_COMPLEX = 3, /// \brief A PointerType record. diff --git a/include/clang/Frontend/TypeXML.def b/include/clang/Frontend/TypeXML.def index 35f5deb..dd5018a 100644 --- a/include/clang/Frontend/TypeXML.def +++ b/include/clang/Frontend/TypeXML.def @@ -103,12 +103,6 @@ NODE_XML(BuiltinType, "FundamentalType") END_ENUM_XML END_NODE_XML -NODE_XML(FixedWidthIntType, "FixedWidthIntType") - ID_ATTRIBUTE_XML - ATTRIBUTE_XML(getWidth(), "width") // unsigned - ATTRIBUTE_XML(isSigned(), "is_signed") // boolean -END_NODE_XML - NODE_XML(PointerType, "PointerType") ID_ATTRIBUTE_XML TYPE_ATTRIBUTE_XML(getPointeeType()) diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index fc65b1f..0f36df4 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -255,8 +255,8 @@ public: // string processing, because we know we need to read until we find the // closing '"' character. // - // The second interface is the combination of PeekCharAndSize with - // ConsumeChar. PeekCharAndSize reads a phase 1/2 translated character, + // The second interface is the combination of getCharAndSize with + // ConsumeChar. getCharAndSize reads a phase 1/2 translated character, // returning it and its size. If the lexer decides that this character is // part of the current token, it calls ConsumeChar on it. This two stage // approach allows us to emit diagnostics for characters (e.g. warnings about @@ -287,7 +287,7 @@ public: } private: - /// ConsumeChar - When a character (identified by PeekCharAndSize) is consumed + /// ConsumeChar - When a character (identified by getCharAndSize) is consumed /// and added to a given token, check to see if there are diagnostics that /// need to be emitted or flags that need to be set on the token. If so, do /// it. diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index c4ab5ae..2334d72 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -16,15 +16,10 @@ #define CLANG_LITERALSUPPORT_H #include <string> +#include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallString.h" #include "llvm/System/DataTypes.h" -namespace llvm { - class APInt; - class APFloat; - struct fltSemantics; -} - namespace clang { class Diagnostic; @@ -82,8 +77,7 @@ public: /// The optional bool isExact (passed-by-reference) has its value /// set to true if the returned APFloat can represent the number in the /// literal exactly, and false otherwise. - llvm::APFloat GetFloatValue(const llvm::fltSemantics &Format, - bool* isExact = NULL); + llvm::APFloat::opStatus GetFloatValue(llvm::APFloat &Result); private: diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index b7540f9..4cbc21a 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -131,7 +131,7 @@ public: }; template<typename T> - FullExprArg FullExpr(T &Arg) { + FullExprArg MakeFullExpr(T &Arg) { return FullExprArg(ActOnFinishFullExpr(move(Arg))); } @@ -662,6 +662,12 @@ public: /// struct, or union). virtual void ActOnTagStartDefinition(Scope *S, DeclPtrTy TagDecl) { } + /// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a + /// C++ record definition's base-specifiers clause and are starting its + /// member declarations. + virtual void ActOnStartCXXMemberDeclarations(Scope *S, DeclPtrTy TagDecl, + SourceLocation LBraceLoc) { } + /// ActOnTagFinishDefinition - Invoked once we have finished parsing /// the definition of a tag (enumeration, class, struct, or union). virtual void ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagDecl, @@ -1351,6 +1357,14 @@ public: virtual void ActOnReenterTemplateScope(Scope *S, DeclPtrTy Template) { } + /// ActOnStartDelayedMemberDeclarations - We have completed parsing + /// a C++ class, and we are about to start parsing any parts of + /// member declarations that could not be parsed earlier. Enter + /// the appropriate record scope. + virtual void ActOnStartDelayedMemberDeclarations(Scope *S, + DeclPtrTy Record) { + } + /// ActOnStartDelayedCXXMethodDeclaration - We have completed /// parsing a top-level (non-nested) C++ class, and we are now /// parsing those parts of the given Method declaration that could @@ -1381,6 +1395,14 @@ public: DeclPtrTy Method) { } + /// ActOnFinishDelayedMemberDeclarations - We have finished parsing + /// a C++ class, and we are about to start parsing any parts of + /// member declarations that could not be parsed earlier. Enter the + /// appropriate record scope. + virtual void ActOnFinishDelayedMemberDeclarations(Scope *S, + DeclPtrTy Record) { + } + /// ActOnStaticAssertDeclaration - Parse a C++0x static_assert declaration. virtual DeclPtrTy ActOnStaticAssertDeclaration(SourceLocation AssertLoc, ExprArg AssertExpr, @@ -1734,7 +1756,7 @@ public: ASTTemplateArgsPtr TemplateArgs, SourceLocation RAngleLoc) { return TypeResult(); - }; + } /// \brief Note that a template ID was used with a tag. /// diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index b766890..7c99e3e 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -995,7 +995,7 @@ struct DeclaratorChunk { /// stack, not objects that are allocated in large quantities on the heap. class Declarator { public: - enum TheContext { + enum TheContext { FileContext, // File scope declaration. PrototypeContext, // Within a function prototype. KNRTypeListContext, // K&R type definition list for formals. diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index e47de50..2214797 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1243,10 +1243,7 @@ private: CreatedScope = true; P.EnterScope(0); // Not a decl scope. - if (P.Actions.ActOnCXXEnterDeclaratorScope(P.CurScope, SS)) - SS.setScopeRep(0); - - if (!SS.isInvalid()) + if (!P.Actions.ActOnCXXEnterDeclaratorScope(P.CurScope, SS)) EnteredScope = true; } diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index 84c179f..aec10f3 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -61,6 +61,9 @@ public: /// \brief A piece of text that describes something about the result but /// should not be inserted into the buffer. CK_Informative, + /// \brief A piece of text that describes the type of an entity or, for + /// functions and methods, the return type. + CK_ResultType, /// \brief A piece of text that describes the parameter that corresponds /// to the code-completion location within a function call, message send, /// macro invocation, etc. @@ -120,6 +123,9 @@ public: /// \brief Create a new informative chunk. static Chunk CreateInformative(llvm::StringRef Informative); + /// \brief Create a new result type chunk. + static Chunk CreateResultType(llvm::StringRef ResultType); + /// \brief Create a new current-parameter chunk. static Chunk CreateCurrentParameter(llvm::StringRef CurrentParameter); @@ -186,6 +192,12 @@ public: Chunks.push_back(Chunk::CreateInformative(Text)); } + /// \brief Add a new result-type chunk. + /// The text will be copied. + void AddResultTypeChunk(llvm::StringRef ResultType) { + Chunks.push_back(Chunk::CreateResultType(ResultType)); + } + /// \brief Add a new current-parameter chunk. /// The text will be copied. void AddCurrentParameterChunk(llvm::StringRef CurrentParameter) { |