diff options
Diffstat (limited to 'include/clang')
77 files changed, 2954 insertions, 856 deletions
diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h index 9d4bff8..5effa90 100644 --- a/include/clang/AST/APValue.h +++ b/include/clang/AST/APValue.h @@ -122,13 +122,17 @@ public: return const_cast<APValue*>(this)->getFloat(); } - APValue &getVectorElt(unsigned i) const { + APValue &getVectorElt(unsigned i) { assert(isVector() && "Invalid accessor"); return ((Vec*)(char*)Data)->Elts[i]; } + const APValue &getVectorElt(unsigned i) const { + assert(isVector() && "Invalid accessor"); + return ((const Vec*)(const char*)Data)->Elts[i]; + } unsigned getVectorLength() const { assert(isVector() && "Invalid accessor"); - return ((Vec*)(void *)Data)->NumElts; + return ((const Vec*)(const void *)Data)->NumElts; } APSInt &getComplexIntReal() { diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index c41857e..f8a8f17 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -25,6 +25,7 @@ #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "clang/AST/CanonicalType.h" +#include "clang/AST/UsuallyTinyPtrVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/OwningPtr.h" @@ -34,6 +35,7 @@ namespace llvm { struct fltSemantics; + class raw_ostream; } namespace clang { @@ -70,28 +72,6 @@ namespace clang { namespace Builtin { class Context; } -/// \brief A vector of C++ member functions that is optimized for -/// storing a single method. -class CXXMethodVector { - /// \brief Storage for the vector. - /// - /// When the low bit is zero, this is a const CXXMethodDecl *. When the - /// low bit is one, this is a std::vector<const CXXMethodDecl *> *. - mutable uintptr_t Storage; - - typedef std::vector<const CXXMethodDecl *> vector_type; - -public: - CXXMethodVector() : Storage(0) { } - - typedef const CXXMethodDecl **iterator; - iterator begin() const; - iterator end() const; - - void push_back(const CXXMethodDecl *Method); - void Destroy(); -}; - /// ASTContext - This class holds long-lived AST nodes (such as types and /// decls) that can be referred to throughout the semantic analysis of a file. class ASTContext { @@ -164,6 +144,8 @@ class ASTContext { QualType ObjCConstantStringType; RecordDecl *CFConstantStringTypeDecl; + RecordDecl *NSConstantStringTypeDecl; + RecordDecl *ObjCFastEnumerationStateTypeDecl; /// \brief The type for the C FILE type. @@ -250,6 +232,7 @@ class ASTContext { /// Since most C++ member functions aren't virtual and therefore /// don't override anything, we store the overridden functions in /// this map on the side rather than within the CXXMethodDecl structure. + typedef UsuallyTinyPtrVector<const CXXMethodDecl> CXXMethodVector; llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector> OverriddenMethods; TranslationUnitDecl *TUDecl; @@ -617,11 +600,13 @@ public: QualType getTemplateSpecializationType(TemplateName T, const TemplateArgument *Args, unsigned NumArgs, - QualType Canon = QualType()); + QualType Canon = QualType(), + bool IsCurrentInstantiation = false); QualType getTemplateSpecializationType(TemplateName T, const TemplateArgumentListInfo &Args, - QualType Canon = QualType()); + QualType Canon = QualType(), + bool IsCurrentInstantiation = false); TypeSourceInfo * getTemplateSpecializationTypeInfo(TemplateName T, SourceLocation TLoc, @@ -688,6 +673,19 @@ public: // constant CFStrings. QualType getCFConstantStringType(); + // getNSConstantStringType - Return the C structure type used to represent + // constant NSStrings. + QualType getNSConstantStringType(); + /// Get the structure type used to representation NSStrings, or NULL + /// if it hasn't yet been built. + QualType getRawNSConstantStringType() { + if (NSConstantStringTypeDecl) + return getTagDeclType(NSConstantStringTypeDecl); + return QualType(); + } + void setNSConstantStringType(QualType T); + + /// Get the structure type used to representation CFStrings, or NULL /// if it hasn't yet been built. QualType getRawCFConstantStringType() { @@ -937,6 +935,8 @@ public: /// layout of the specified Objective-C interface. const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D); + void DumpRecordLayout(const RecordDecl *RD, llvm::raw_ostream &OS); + /// getASTObjCImplementationLayout - Get or compute information about /// the layout of the specified Objective-C implementation. This may /// differ from the interface if synthesized ivars are present. diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h new file mode 100644 index 0000000..217dfad --- /dev/null +++ b/include/clang/AST/ASTVector.h @@ -0,0 +1,397 @@ +//===- ASTVector.h - Vector that uses ASTContext for allocation --*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides ASTVector, a vector ADT whose contents are +// allocated using the allocator associated with an ASTContext.. +// +//===----------------------------------------------------------------------===// + +// FIXME: Most of this is copy-and-paste from BumpVector.h and SmallVector.h. +// We can refactor this core logic into something common. + +#ifndef LLVM_CLANG_AST_VECTOR +#define LLVM_CLANG_AST_VECTOR + +#include "llvm/Support/type_traits.h" +#include "llvm/Support/Allocator.h" +#include "llvm/ADT/PointerIntPair.h" +#include <algorithm> +#include <memory> +#include <cstring> + +#ifdef _MSC_VER +namespace std { +#if _MSC_VER <= 1310 + // Work around flawed VC++ implementation of std::uninitialized_copy. Define + // additional overloads so that elements with pointer types are recognized as + // scalars and not objects, causing bizarre type conversion errors. + template<class T1, class T2> + inline _Scalar_ptr_iterator_tag _Ptr_cat(T1 **, T2 **) { + _Scalar_ptr_iterator_tag _Cat; + return _Cat; + } + + template<class T1, class T2> + inline _Scalar_ptr_iterator_tag _Ptr_cat(T1* const *, T2 **) { + _Scalar_ptr_iterator_tag _Cat; + return _Cat; + } +#else + // FIXME: It is not clear if the problem is fixed in VS 2005. What is clear + // is that the above hack won't work if it wasn't fixed. +#endif +} +#endif + +namespace clang { + +template<typename T> +class ASTVector { + T *Begin, *End, *Capacity; + + void setEnd(T *P) { this->End = P; } + +public: + // Default ctor - Initialize to empty. + explicit ASTVector(ASTContext &C, unsigned N = 0) + : Begin(NULL), End(NULL), Capacity(NULL) { + reserve(C, N); + } + + ~ASTVector() { + if (llvm::is_class<T>::value) { + // Destroy the constructed elements in the vector. + destroy_range(Begin, End); + } + } + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef T* iterator; + typedef const T* const_iterator; + + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + + // forward iterator creation methods. + iterator begin() { return Begin; } + const_iterator begin() const { return Begin; } + iterator end() { return End; } + const_iterator end() const { return End; } + + // reverse iterator creation methods. + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin());} + + bool empty() const { return Begin == End; } + size_type size() const { return End-Begin; } + + reference operator[](unsigned idx) { + assert(Begin + idx < End); + return Begin[idx]; + } + const_reference operator[](unsigned idx) const { + assert(Begin + idx < End); + return Begin[idx]; + } + + reference front() { + return begin()[0]; + } + const_reference front() const { + return begin()[0]; + } + + reference back() { + return end()[-1]; + } + const_reference back() const { + return end()[-1]; + } + + void pop_back() { + --End; + End->~T(); + } + + T pop_back_val() { + T Result = back(); + pop_back(); + return Result; + } + + void clear() { + if (llvm::is_class<T>::value) { + destroy_range(Begin, End); + } + End = Begin; + } + + /// data - Return a pointer to the vector's buffer, even if empty(). + pointer data() { + return pointer(Begin); + } + + /// data - Return a pointer to the vector's buffer, even if empty(). + const_pointer data() const { + return const_pointer(Begin); + } + + void push_back(const_reference Elt, ASTContext &C) { + if (End < Capacity) { + Retry: + new (End) T(Elt); + ++End; + return; + } + grow(C); + goto Retry; + } + + void reserve(ASTContext &C, unsigned N) { + if (unsigned(Capacity-Begin) < N) + grow(C, N); + } + + /// capacity - Return the total number of elements in the currently allocated + /// buffer. + size_t capacity() const { return Capacity - Begin; } + + /// append - Add the specified range to the end of the SmallVector. + /// + template<typename in_iter> + void append(ASTContext &C, in_iter in_start, in_iter in_end) { + size_type NumInputs = std::distance(in_start, in_end); + + if (NumInputs == 0) + return; + + // Grow allocated space if needed. + if (NumInputs > size_type(this->capacity_ptr()-this->end())) + this->grow(C, this->size()+NumInputs); + + // Copy the new elements over. + // TODO: NEED To compile time dispatch on whether in_iter is a random access + // iterator to use the fast uninitialized_copy. + std::uninitialized_copy(in_start, in_end, this->end()); + this->setEnd(this->end() + NumInputs); + } + + /// append - Add the specified range to the end of the SmallVector. + /// + void append(ASTContext &C, size_type NumInputs, const T &Elt) { + // Grow allocated space if needed. + if (NumInputs > size_type(this->capacity_ptr()-this->end())) + this->grow(C, this->size()+NumInputs); + + // Copy the new elements over. + std::uninitialized_fill_n(this->end(), NumInputs, Elt); + this->setEnd(this->end() + NumInputs); + } + + /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory + /// starting with "Dest", constructing elements into it as needed. + template<typename It1, typename It2> + static void uninitialized_copy(It1 I, It1 E, It2 Dest) { + std::uninitialized_copy(I, E, Dest); + } + + iterator insert(ASTContext &C, iterator I, const T &Elt) { + if (I == this->end()) { // Important special case for empty vector. + push_back(Elt); + return this->end()-1; + } + + if (this->EndX < this->CapacityX) { + Retry: + new (this->end()) T(this->back()); + this->setEnd(this->end()+1); + // Push everything else over. + std::copy_backward(I, this->end()-1, this->end()); + *I = Elt; + return I; + } + size_t EltNo = I-this->begin(); + this->grow(C); + I = this->begin()+EltNo; + goto Retry; + } + + iterator insert(ASTContext &C, iterator I, size_type NumToInsert, + const T &Elt) { + if (I == this->end()) { // Important special case for empty vector. + append(C, NumToInsert, Elt); + return this->end()-1; + } + + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + size_t InsertElt = I - this->begin(); + + // Ensure there is enough space. + reserve(C, static_cast<unsigned>(this->size() + NumToInsert)); + + // Uninvalidate the iterator. + I = this->begin()+InsertElt; + + // If there are more elements between the insertion point and the end of the + // range than there are being inserted, we can use a simple approach to + // insertion. Since we already reserved space, we know that this won't + // reallocate the vector. + if (size_t(this->end()-I) >= NumToInsert) { + T *OldEnd = this->end(); + append(C, this->end()-NumToInsert, this->end()); + + // Copy the existing elements that get replaced. + std::copy_backward(I, OldEnd-NumToInsert, OldEnd); + + std::fill_n(I, NumToInsert, Elt); + return I; + } + + // Otherwise, we're inserting more elements than exist already, and we're + // not inserting at the end. + + // Copy over the elements that we're about to overwrite. + T *OldEnd = this->end(); + this->setEnd(this->end() + NumToInsert); + size_t NumOverwritten = OldEnd-I; + this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); + + // Replace the overwritten part. + std::fill_n(I, NumOverwritten, Elt); + + // Insert the non-overwritten middle part. + std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt); + return I; + } + + template<typename ItTy> + iterator insert(ASTContext &C, iterator I, ItTy From, ItTy To) { + if (I == this->end()) { // Important special case for empty vector. + append(C, From, To); + return this->end()-1; + } + + size_t NumToInsert = std::distance(From, To); + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + size_t InsertElt = I - this->begin(); + + // Ensure there is enough space. + reserve(C, static_cast<unsigned>(this->size() + NumToInsert)); + + // Uninvalidate the iterator. + I = this->begin()+InsertElt; + + // If there are more elements between the insertion point and the end of the + // range than there are being inserted, we can use a simple approach to + // insertion. Since we already reserved space, we know that this won't + // reallocate the vector. + if (size_t(this->end()-I) >= NumToInsert) { + T *OldEnd = this->end(); + append(C, this->end()-NumToInsert, this->end()); + + // Copy the existing elements that get replaced. + std::copy_backward(I, OldEnd-NumToInsert, OldEnd); + + std::copy(From, To, I); + return I; + } + + // Otherwise, we're inserting more elements than exist already, and we're + // not inserting at the end. + + // Copy over the elements that we're about to overwrite. + T *OldEnd = this->end(); + this->setEnd(this->end() + NumToInsert); + size_t NumOverwritten = OldEnd-I; + this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); + + // Replace the overwritten part. + for (; NumOverwritten > 0; --NumOverwritten) { + *I = *From; + ++I; ++From; + } + + // Insert the non-overwritten middle part. + this->uninitialized_copy(From, To, OldEnd); + return I; + } + + void resize(ASTContext &C, unsigned N, const T &NV) { + if (N < this->size()) { + this->destroy_range(this->begin()+N, this->end()); + this->setEnd(this->begin()+N); + } else if (N > this->size()) { + if (this->capacity() < N) + this->grow(C, N); + construct_range(this->end(), this->begin()+N, NV); + this->setEnd(this->begin()+N); + } + } + +private: + /// grow - double the size of the allocated memory, guaranteeing space for at + /// least one more element or MinSize if specified. + void grow(ASTContext &C, size_type MinSize = 1); + + void construct_range(T *S, T *E, const T &Elt) { + for (; S != E; ++S) + new (S) T(Elt); + } + + void destroy_range(T *S, T *E) { + while (S != E) { + --E; + E->~T(); + } + } + +protected: + iterator capacity_ptr() { return (iterator)this->Capacity; } +}; + +// Define this out-of-line to dissuade the C++ compiler from inlining it. +template <typename T> +void ASTVector<T>::grow(ASTContext &C, size_t MinSize) { + size_t CurCapacity = Capacity-Begin; + size_t CurSize = size(); + size_t NewCapacity = 2*CurCapacity; + if (NewCapacity < MinSize) + NewCapacity = MinSize; + + // Allocate the memory from the ASTContext. + T *NewElts = new (C) T[NewCapacity]; + + // Copy the elements over. + if (llvm::is_class<T>::value) { + std::uninitialized_copy(Begin, End, NewElts); + // Destroy the original elements. + destroy_range(Begin, End); + } + else { + // Use memcpy for PODs (std::uninitialized_copy optimizes to memmove). + memcpy(NewElts, Begin, CurSize * sizeof(T)); + } + + C.Deallocate(Begin); + Begin = NewElts; + End = NewElts+CurSize; + Capacity = Begin+NewCapacity; +} + +} // end: clang namespace +#endif diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index b2a87f6..93dcad7 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -263,6 +263,7 @@ public: LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isMemberFunctionPointerType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isClassType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureOrClassType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnionType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexIntegerType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isNullPtrType) diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 2cdb983..834c9a0 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -31,7 +31,9 @@ class StringLiteral; class TemplateArgumentList; class MemberSpecializationInfo; class FunctionTemplateSpecializationInfo; +class DependentFunctionTemplateSpecializationInfo; class TypeLoc; +class UnresolvedSetImpl; /// \brief A container of type source information. /// @@ -196,6 +198,10 @@ public: return DC->isRecord(); } + /// \brief Given that this declaration is a C++ class member, + /// determine whether it's an instance member of its class. + bool isCXXInstanceMember() const; + /// \brief Determine what kind of linkage this entity has. Linkage getLinkage() const; @@ -211,6 +217,12 @@ public: static bool classofKind(Kind K) { return K >= NamedFirst && K <= NamedLast; } }; +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const NamedDecl *ND) { + ND->getDeclName().printName(OS); + return OS; +} + /// NamespaceDecl - Represent a C++ namespace. class NamespaceDecl : public NamedDecl, public DeclContext { SourceLocation LBracLoc, RBracLoc; @@ -478,6 +490,7 @@ protected: private: // FIXME: This can be packed into the bitfields in Decl. unsigned SClass : 3; + unsigned SClassAsWritten : 3; bool ThreadSpecified : 1; bool HasCXXDirectInit : 1; @@ -485,14 +498,20 @@ private: /// condition, e.g., if (int x = foo()) { ... }. bool DeclaredInCondition : 1; + /// \brief Whether this variable is the exception variable in a C++ catch + /// or an Objective-C @catch statement. + bool ExceptionVar : 1; + friend class StmtIteratorBase; protected: VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - QualType T, TypeSourceInfo *TInfo, StorageClass SC) + QualType T, TypeSourceInfo *TInfo, StorageClass SC, + StorageClass SCAsWritten) : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(), ThreadSpecified(false), HasCXXDirectInit(false), - DeclaredInCondition(false) { + DeclaredInCondition(false), ExceptionVar(false) { SClass = SC; + SClassAsWritten = SCAsWritten; } typedef Redeclarable<VarDecl> redeclarable_base; @@ -509,7 +528,8 @@ public: static VarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - QualType T, TypeSourceInfo *TInfo, StorageClass S); + QualType T, TypeSourceInfo *TInfo, StorageClass S, + StorageClass SCAsWritten); virtual void Destroy(ASTContext& C); virtual ~VarDecl(); @@ -517,7 +537,11 @@ public: virtual SourceRange getSourceRange() const; StorageClass getStorageClass() const { return (StorageClass)SClass; } + StorageClass getStorageClassAsWritten() const { + return (StorageClass) SClassAsWritten; + } void setStorageClass(StorageClass SC) { SClass = SC; } + void setStorageClassAsWritten(StorageClass SC) { SClassAsWritten = SC; } void setThreadSpecified(bool T) { ThreadSpecified = T; } bool isThreadSpecified() const { @@ -536,6 +560,12 @@ public: return getStorageClass() <= Register; } + /// isStaticLocal - Returns true if a variable with function scope is a + /// static local variable. + bool isStaticLocal() const { + return getStorageClass() == Static && !isFileVarDecl(); + } + /// hasExternStorage - Returns true if a variable has extern or /// __private_extern__ storage. bool hasExternalStorage() const { @@ -815,6 +845,13 @@ public: DeclaredInCondition = InCondition; } + /// \brief Determine whether this variable is the exception variable in a + /// C++ catch statememt or an Objective-C @catch statement. + bool isExceptionVariable() const { + return ExceptionVar; + } + void setExceptionVariable(bool EV) { ExceptionVar = EV; } + /// \brief If this variable is an instantiated static data member of a /// class template specialization, returns the templated static data member /// from which it was instantiated. @@ -844,7 +881,7 @@ class ImplicitParamDecl : public VarDecl { protected: ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType Tw) - : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, VarDecl::None) {} + : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, VarDecl::None, VarDecl::None) {} public: static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, @@ -866,9 +903,9 @@ class ParmVarDecl : public VarDecl { protected: ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S, Expr *DefArg) - : VarDecl(DK, DC, L, Id, T, TInfo, S), - objcDeclQualifier(OBJC_TQ_None), HasInheritedDefaultArg(false) { + StorageClass S, StorageClass SCAsWritten, Expr *DefArg) + : VarDecl(DK, DC, L, Id, T, TInfo, S, SCAsWritten), + objcDeclQualifier(OBJC_TQ_None), HasInheritedDefaultArg(false) { setDefaultArg(DefArg); } @@ -876,7 +913,8 @@ public: static ParmVarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - StorageClass S, Expr *DefArg); + StorageClass S, StorageClass SCAsWritten, + Expr *DefArg); ObjCDeclQualifier getObjCDeclQualifier() const { return ObjCDeclQualifier(objcDeclQualifier); @@ -1002,6 +1040,7 @@ private: // FIXME: This can be packed into the bitfields in Decl. // NOTE: VC++ treats enums as signed, avoid using the StorageClass enum unsigned SClass : 2; + unsigned SClassAsWritten : 2; bool IsInline : 1; bool IsVirtualAsWritten : 1; bool IsPure : 1; @@ -1033,19 +1072,20 @@ private: /// FunctionTemplateSpecializationInfo, which contains information about /// the template being specialized and the template arguments involved in /// that specialization. - llvm::PointerUnion3<FunctionTemplateDecl *, + llvm::PointerUnion4<FunctionTemplateDecl *, MemberSpecializationInfo *, - FunctionTemplateSpecializationInfo *> + FunctionTemplateSpecializationInfo *, + DependentFunctionTemplateSpecializationInfo *> TemplateOrSpecialization; protected: FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, - StorageClass S, bool isInline) + StorageClass S, StorageClass SCAsWritten, bool isInline) : DeclaratorDecl(DK, DC, L, N, T, TInfo), DeclContext(DK), ParamInfo(0), Body(), - SClass(S), IsInline(isInline), + SClass(S), SClassAsWritten(SCAsWritten), IsInline(isInline), IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), IsCopyAssignment(false), @@ -1070,7 +1110,9 @@ public: static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, - StorageClass S = None, bool isInline = false, + StorageClass S = None, + StorageClass SCAsWritten = None, + bool isInline = false, bool hasWrittenPrototype = true); virtual void getNameForDiagnostic(std::string &S, @@ -1107,6 +1149,9 @@ public: void setBody(Stmt *B); void setLazyBody(uint64_t Offset) { Body = Offset; } + /// Whether this function is variadic. + bool isVariadic() const; + /// Whether this function is marked as virtual explicitly. bool isVirtualAsWritten() const { return IsVirtualAsWritten; } void setVirtualAsWritten(bool V) { IsVirtualAsWritten = V; } @@ -1225,6 +1270,11 @@ public: StorageClass getStorageClass() const { return StorageClass(SClass); } void setStorageClass(StorageClass SC) { SClass = SC; } + StorageClass getStorageClassAsWritten() const { + return StorageClass(SClassAsWritten); + } + void setStorageClassAsWritten(StorageClass SC) { SClassAsWritten = SC; } + /// \brief Determine whether the "inline" keyword was specified for this /// function. bool isInlineSpecified() const { return IsInline; } @@ -1361,6 +1411,18 @@ public: void *InsertPos, TemplateSpecializationKind TSK = TSK_ImplicitInstantiation); + /// \brief Specifies that this function declaration is actually a + /// dependent function template specialization. + void setDependentTemplateSpecialization(ASTContext &Context, + const UnresolvedSetImpl &Templates, + const TemplateArgumentListInfo &TemplateArgs); + + DependentFunctionTemplateSpecializationInfo * + getDependentSpecializationInfo() const { + return TemplateOrSpecialization. + dyn_cast<DependentFunctionTemplateSpecializationInfo*>(); + } + /// \brief Determine what kind of template instantiation this function /// represents. TemplateSpecializationKind getTemplateSpecializationKind() const; @@ -1961,7 +2023,7 @@ public: /// class BlockDecl : public Decl, public DeclContext { // FIXME: This can be packed into the bitfields in Decl. - bool isVariadic : 1; + bool IsVariadic : 1; /// ParamInfo - new[]'d array of pointers to ParmVarDecls for the formal /// parameters of this function. This is null if a prototype or if there are /// no formals. @@ -1973,7 +2035,7 @@ class BlockDecl : public Decl, public DeclContext { protected: BlockDecl(DeclContext *DC, SourceLocation CaretLoc) : Decl(Block, DC, CaretLoc), DeclContext(Block), - isVariadic(false), ParamInfo(0), NumParams(0), Body(0) {} + IsVariadic(false), ParamInfo(0), NumParams(0), Body(0) {} virtual ~BlockDecl(); virtual void Destroy(ASTContext& C); @@ -1983,8 +2045,8 @@ public: SourceLocation getCaretLocation() const { return getLocation(); } - bool IsVariadic() const { return isVariadic; } - void setIsVariadic(bool value) { isVariadic = value; } + bool isVariadic() const { return IsVariadic; } + void setIsVariadic(bool value) { IsVariadic = value; } CompoundStmt *getCompoundBody() const { return (CompoundStmt*) Body; } Stmt *getBody() const { return (Stmt*) Body; } diff --git a/include/clang/AST/DeclAccessPair.h b/include/clang/AST/DeclAccessPair.h new file mode 100644 index 0000000..7ecd8f8 --- /dev/null +++ b/include/clang/AST/DeclAccessPair.h @@ -0,0 +1,72 @@ +//===--- DeclAccessPair.h - A decl bundled with its path access -*- 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 DeclAccessPair class, which provides an +// efficient representation of a pair of a NamedDecl* and an +// AccessSpecifier. Generally the access specifier gives the +// natural access of a declaration when named in a class, as +// defined in C++ [class.access.base]p1. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECLACCESSPAIR_H +#define LLVM_CLANG_AST_DECLACCESSPAIR_H + +#include "clang/Basic/Specifiers.h" + +namespace clang { + +class NamedDecl; + +/// A POD class for pairing a NamedDecl* with an access specifier. +/// Can be put into unions. +class DeclAccessPair { + NamedDecl *Ptr; // we'd use llvm::PointerUnion, but it isn't trivial + + enum { Mask = 0x3 }; + +public: + static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS) { + DeclAccessPair p; + p.set(D, AS); + return p; + } + + NamedDecl *getDecl() const { + return (NamedDecl*) (~Mask & (uintptr_t) Ptr); + } + AccessSpecifier getAccess() const { + return AccessSpecifier(Mask & (uintptr_t) Ptr); + } + + void setDecl(NamedDecl *D) { + set(D, getAccess()); + } + void setAccess(AccessSpecifier AS) { + set(getDecl(), AS); + } + void set(NamedDecl *D, AccessSpecifier AS) { + Ptr = reinterpret_cast<NamedDecl*>(uintptr_t(AS) | + reinterpret_cast<uintptr_t>(D)); + } + + operator NamedDecl*() const { return getDecl(); } + NamedDecl *operator->() const { return getDecl(); } +}; +} + +// Take a moment to tell SmallVector that DeclAccessPair is POD. +namespace llvm { +template<typename> struct isPodLike; +template<> struct isPodLike<clang::DeclAccessPair> { + static const bool value = true; +}; +} + +#endif diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index d5913e2..a9b948e 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -76,26 +76,68 @@ public: #include "clang/AST/DeclNodes.def" }; - /// IdentifierNamespace - According to C99 6.2.3, there are four - /// namespaces, labels, tags, members and ordinary - /// identifiers. These are meant as bitmasks, so that searches in - /// C++ can look into the "tag" namespace during ordinary lookup. We - /// use additional namespaces for Objective-C entities. We also put - /// C++ friend declarations (of previously-undeclared entities) in - /// shadow namespaces, and 'using' declarations (as opposed to their - /// implicit shadow declarations) can be found in their own - /// namespace. + /// IdentifierNamespace - The different namespaces in which + /// declarations may appear. According to C99 6.2.3, there are + /// four namespaces, labels, tags, members and ordinary + /// identifiers. C++ describes lookup completely differently: + /// certain lookups merely "ignore" certain kinds of declarations, + /// usually based on whether the declaration is of a type, etc. + /// + /// These are meant as bitmasks, so that searches in + /// C++ can look into the "tag" namespace during ordinary lookup. + /// + /// Decl currently provides 16 bits of IDNS bits. enum IdentifierNamespace { - IDNS_Label = 0x1, - IDNS_Tag = 0x2, - IDNS_Member = 0x4, - IDNS_Ordinary = 0x8, - IDNS_ObjCProtocol = 0x10, - IDNS_ObjCImplementation = 0x20, - IDNS_ObjCCategoryName = 0x40, - IDNS_OrdinaryFriend = 0x80, - IDNS_TagFriend = 0x100, - IDNS_Using = 0x200 + /// Labels, declared with 'x:' and referenced with 'goto x'. + IDNS_Label = 0x0001, + + /// Tags, declared with 'struct foo;' and referenced with + /// 'struct foo'. All tags are also types. This is what + /// elaborated-type-specifiers look for in C. + IDNS_Tag = 0x0002, + + /// Types, declared with 'struct foo', typedefs, etc. + /// This is what elaborated-type-specifiers look for in C++, + /// but note that it's ill-formed to find a non-tag. + IDNS_Type = 0x0004, + + /// Members, declared with object declarations within tag + /// definitions. In C, these can only be found by "qualified" + /// lookup in member expressions. In C++, they're found by + /// normal lookup. + IDNS_Member = 0x0008, + + /// Namespaces, declared with 'namespace foo {}'. + /// Lookup for nested-name-specifiers find these. + IDNS_Namespace = 0x0010, + + /// Ordinary names. In C, everything that's not a label, tag, + /// or member ends up here. + IDNS_Ordinary = 0x0020, + + /// Objective C @protocol. + IDNS_ObjCProtocol = 0x0040, + + /// This declaration is a friend function. A friend function + /// declaration is always in this namespace but may also be in + /// IDNS_Ordinary if it was previously declared. + IDNS_OrdinaryFriend = 0x0080, + + /// This declaration is a friend class. A friend class + /// declaration is always in this namespace but may also be in + /// IDNS_Tag|IDNS_Type if it was previously declared. + IDNS_TagFriend = 0x0100, + + /// This declaration is a using declaration. A using declaration + /// *introduces* a number of other declarations into the current + /// scope, and those declarations use the IDNS of their targets, + /// but the actual using declarations go in this namespace. + IDNS_Using = 0x0200, + + /// This declaration is a C++ operator declared in a non-class + /// context. All such operators are also in IDNS_Ordinary. + /// C++ lexical operator lookup looks for these. + IDNS_NonMemberOperator = 0x0400 }; /// ObjCDeclQualifier - Qualifier used on types in method declarations @@ -313,6 +355,13 @@ public: } static unsigned getIdentifierNamespaceForKind(Kind DK); + bool hasTagIdentifierNamespace() const { + return isTagIdentifierNamespace(getIdentifierNamespace()); + } + static bool isTagIdentifierNamespace(unsigned NS) { + // TagDecls have Tag and Type set and may also have TagFriend. + return (NS & ~IDNS_TagFriend) == (IDNS_Tag | IDNS_Type); + } /// getLexicalDeclContext - The declaration context where this Decl was /// lexically declared (LexicalDC). May be different from @@ -455,14 +504,14 @@ public: assert((OldNS & (IDNS_Tag | IDNS_Ordinary | IDNS_TagFriend | IDNS_OrdinaryFriend)) && "namespace includes neither ordinary nor tag"); - assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary | + assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary | IDNS_Type | IDNS_TagFriend | IDNS_OrdinaryFriend)) && "namespace includes other than ordinary or tag"); IdentifierNamespace = 0; if (OldNS & (IDNS_Tag | IDNS_TagFriend)) { IdentifierNamespace |= IDNS_TagFriend; - if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag; + if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag | IDNS_Type; } if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend)) { @@ -489,6 +538,14 @@ public: FOK_Declared : FOK_Undeclared); } + /// Specifies that this declaration is a C++ overloaded non-member. + void setNonMemberOperator() { + assert(getKind() == Function || getKind() == FunctionTemplate); + assert((IdentifierNamespace & IDNS_Ordinary) && + "visible non-member operators should be in ordinary namespace"); + IdentifierNamespace |= IDNS_NonMemberOperator; + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *) { return true; } static bool classofKind(Kind K) { return true; } diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 23769af..aa649c8 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -471,6 +471,11 @@ public: friend_iterator friend_end() const; void pushFriendDecl(FriendDecl *FD); + /// Determines whether this record has any friends. + bool hasFriends() const { + return data().FirstFriend != 0; + } + /// hasConstCopyConstructor - Determines whether this class has a /// copy constructor that accepts a const-qualified argument. bool hasConstCopyConstructor(ASTContext &Context) const; @@ -931,15 +936,16 @@ class CXXMethodDecl : public FunctionDecl { protected: CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, - bool isStatic, bool isInline) + bool isStatic, StorageClass SCAsWritten, bool isInline) : FunctionDecl(DK, RD, L, N, T, TInfo, (isStatic ? Static : None), - isInline) {} + SCAsWritten, isInline) {} public: static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, bool isStatic = false, + StorageClass SCAsWritten = FunctionDecl::None, bool isInline = false); bool isStatic() const { return getStorageClass() == Static; } @@ -960,6 +966,10 @@ public: /// delete or delete[] operator with a particular signature. bool isUsualDeallocationFunction() const; + /// \brief Determine whether this is a copy-assignment operator, regardless + /// of whether it was declared implicitly or explicitly. + bool isCopyAssignmentOperator() const; + const CXXMethodDecl *getCanonicalDecl() const { return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl()); } @@ -1052,6 +1062,10 @@ class CXXBaseOrMemberInitializer { /// and AnonUnionMember holds field decl for au_i1. FieldDecl *AnonUnionMember; + /// IsVirtual - If the initializer is a base initializer, this keeps track + /// of whether the base is virtual or not. + bool IsVirtual; + /// LParenLoc - Location of the left paren of the ctor-initializer. SourceLocation LParenLoc; @@ -1062,7 +1076,7 @@ public: /// CXXBaseOrMemberInitializer - Creates a new base-class initializer. explicit CXXBaseOrMemberInitializer(ASTContext &Context, - TypeSourceInfo *TInfo, + TypeSourceInfo *TInfo, bool IsVirtual, SourceLocation L, Expr *Init, SourceLocation R); @@ -1095,7 +1109,14 @@ public: /// Otherwise, returns NULL. const Type *getBaseClass() const; Type *getBaseClass(); - + + /// Returns whether the base is virtual or not. + bool isBaseVirtual() const { + assert(isBaseInitializer() && "Must call this on base initializer!"); + + return IsVirtual; + } + /// \brief Returns the declarator information for a base class initializer. TypeSourceInfo *getBaseClassInfo() const { return BaseOrMember.dyn_cast<TypeSourceInfo *>(); @@ -1171,7 +1192,8 @@ class CXXConstructorDecl : public CXXMethodDecl { DeclarationName N, QualType T, TypeSourceInfo *TInfo, bool isExplicitSpecified, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXConstructor, RD, L, N, T, TInfo, false, isInline), + : CXXMethodDecl(CXXConstructor, RD, L, N, T, TInfo, false, + FunctionDecl::None, isInline), IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false), BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) { setImplicit(isImplicitlyDeclared); @@ -1199,7 +1221,7 @@ public: /// defined. If false, then this constructor was defined by the /// user. This operation can only be invoked if the constructor has /// already been defined. - bool isImplicitlyDefined(ASTContext &C) const { + bool isImplicitlyDefined() const { assert(isThisDeclarationADefinition() && "Can only get the implicit-definition flag once the " "constructor has been defined"); @@ -1314,7 +1336,8 @@ class CXXDestructorDecl : public CXXMethodDecl { CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXDestructor, RD, L, N, T, /*TInfo=*/0, false, isInline), + : CXXMethodDecl(CXXDestructor, RD, L, N, T, /*TInfo=*/0, false, + FunctionDecl::None, isInline), ImplicitlyDefined(false), OperatorDelete(0) { setImplicit(isImplicitlyDeclared); } @@ -1370,7 +1393,8 @@ class CXXConversionDecl : public CXXMethodDecl { CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, bool isInline, bool isExplicitSpecified) - : CXXMethodDecl(CXXConversion, RD, L, N, T, TInfo, false, isInline), + : CXXMethodDecl(CXXConversion, RD, L, N, T, TInfo, false, + FunctionDecl::None, isInline), IsExplicitSpecified(isExplicitSpecified) { } public: diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h index 16cb491..2a4b12a 100644 --- a/include/clang/AST/DeclContextInternals.h +++ b/include/clang/AST/DeclContextInternals.h @@ -230,7 +230,7 @@ public: // Tag declarations always go at the end of the list so that an // iterator which points at the first tag will start a span of // decls that only contains tags. - if (D->getIdentifierNamespace() == Decl::IDNS_Tag) + if (D->hasTagIdentifierNamespace()) Vec.push_back(reinterpret_cast<uintptr_t>(D)); // Resolved using declarations go at the front of the list so that @@ -251,7 +251,7 @@ public: // tag declarations. But we can be clever about tag declarations // because there can only ever be one in a scope. } else if (reinterpret_cast<NamedDecl *>(Vec.back()) - ->getIdentifierNamespace() == Decl::IDNS_Tag) { + ->hasTagIdentifierNamespace()) { uintptr_t TagD = Vec.back(); Vec.back() = reinterpret_cast<uintptr_t>(D); Vec.push_back(TagD); diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index 99ef738..a20625d 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -48,10 +48,6 @@ private: // Location of the 'friend' specifier. SourceLocation FriendLoc; - // FIXME: Hack to keep track of whether this was a friend function - // template specialization. - bool WasSpecialization; - friend class CXXRecordDecl::friend_iterator; friend class CXXRecordDecl; @@ -60,8 +56,7 @@ private: : Decl(Decl::Friend, DC, L), Friend(Friend), NextFriend(0), - FriendLoc(FriendL), - WasSpecialization(false) { + FriendLoc(FriendL) { } public: @@ -88,9 +83,6 @@ 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 classofKind(D->getKind()); } static bool classof(const FriendDecl *D) { return true; } diff --git a/include/clang/AST/DeclNodes.def b/include/clang/AST/DeclNodes.def index 082299c..5b03ff8 100644 --- a/include/clang/AST/DeclNodes.def +++ b/include/clang/AST/DeclNodes.def @@ -105,14 +105,14 @@ ABSTRACT_DECL(Named, Decl) DECL(ImplicitParam, VarDecl) DECL(ParmVar, VarDecl) DECL(NonTypeTemplateParm, VarDecl) - DECL(Template, NamedDecl) + ABSTRACT_DECL(Template, NamedDecl) DECL(FunctionTemplate, TemplateDecl) DECL(ClassTemplate, TemplateDecl) DECL(TemplateTemplateParm, TemplateDecl) DECL(Using, NamedDecl) DECL(UsingShadow, NamedDecl) DECL(ObjCMethod, NamedDecl) - DECL(ObjCContainer, NamedDecl) + ABSTRACT_DECL(ObjCContainer, NamedDecl) DECL(ObjCCategory, ObjCContainerDecl) DECL(ObjCProtocol, ObjCContainerDecl) DECL(ObjCInterface, ObjCContainerDecl) @@ -143,7 +143,7 @@ LAST_DECL_CONTEXT(Block) // Declaration ranges DECL_RANGE(Named, Namespace, ObjCCompatibleAlias) -DECL_RANGE(ObjCContainer, ObjCContainer, ObjCImplementation) +DECL_RANGE(ObjCContainer, ObjCCategory, ObjCImplementation) DECL_RANGE(Field, Field, ObjCAtDefsField) DECL_RANGE(Type, Typedef, TemplateTypeParm) DECL_RANGE(Tag, Enum, ClassTemplatePartialSpecialization) @@ -151,7 +151,7 @@ DECL_RANGE(Record, Record, ClassTemplatePartialSpecialization) DECL_RANGE(Value, EnumConstant, NonTypeTemplateParm) DECL_RANGE(Declarator, Function, NonTypeTemplateParm) DECL_RANGE(Function, Function, CXXConversion) -DECL_RANGE(Template, Template, TemplateTemplateParm) +DECL_RANGE(Template, FunctionTemplate, TemplateTemplateParm) DECL_RANGE(ObjCImpl, ObjCCategoryImpl, ObjCImplementation) LAST_DECL_RANGE(Var, Var, NonTypeTemplateParm) diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 9b2b609..e34ec9f 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -29,6 +29,7 @@ class ObjCProtocolDecl; class ObjCCategoryDecl; class ObjCPropertyDecl; class ObjCPropertyImplDecl; +class CXXBaseOrMemberInitializer; class ObjCListBase { void operator=(const ObjCListBase &); // DO NOT IMPLEMENT @@ -136,6 +137,9 @@ private: /// in, inout, etc. unsigned objcDeclQualifier : 6; + // Number of args separated by ':' in a method declaration. + unsigned NumSelectorArgs; + // Result type of this method. QualType MethodDeclType; @@ -167,13 +171,15 @@ private: bool isInstance = true, bool isVariadic = false, bool isSynthesized = false, - ImplementationControl impControl = None) + ImplementationControl impControl = None, + unsigned numSelectorArgs = 0) : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), DeclContext(ObjCMethod), IsInstance(isInstance), IsVariadic(isVariadic), IsSynthesized(isSynthesized), DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None), - MethodDeclType(T), ResultTInfo(ResultTInfo), + NumSelectorArgs(numSelectorArgs), MethodDeclType(T), + ResultTInfo(ResultTInfo), EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {} virtual ~ObjCMethodDecl() {} @@ -197,7 +203,8 @@ public: bool isInstance = true, bool isVariadic = false, bool isSynthesized = false, - ImplementationControl impControl = None); + ImplementationControl impControl = None, + unsigned numSelectorArgs = 0); virtual ObjCMethodDecl *getCanonicalDecl(); const ObjCMethodDecl *getCanonicalDecl() const { @@ -209,6 +216,11 @@ public: } void setObjCDeclQualifier(ObjCDeclQualifier QV) { objcDeclQualifier = QV; } + unsigned getNumSelectorArgs() const { return NumSelectorArgs; } + void setNumSelectorArgs(unsigned numSelectorArgs) { + NumSelectorArgs = numSelectorArgs; + } + // Location information, modeled after the Stmt API. SourceLocation getLocStart() const { return getLocation(); } SourceLocation getLocEnd() const { return EndLoc; } @@ -235,9 +247,16 @@ public: typedef ObjCList<ParmVarDecl>::iterator param_iterator; param_iterator param_begin() const { return ParamInfo.begin(); } param_iterator param_end() const { return ParamInfo.end(); } + // This method returns and of the parameters which are part of the selector + // name mangling requirements. + param_iterator sel_param_end() const { + return ParamInfo.begin() + NumSelectorArgs; + } - void setMethodParams(ASTContext &C, ParmVarDecl *const *List, unsigned Num) { + void setMethodParams(ASTContext &C, ParmVarDecl *const *List, unsigned Num, + unsigned numSelectorArgs) { ParamInfo.set(List, Num, C); + NumSelectorArgs = numSelectorArgs; } // Iterator access to parameter types. @@ -1114,6 +1133,9 @@ public: static bool classofKind(Kind K) { return K == ObjCCategoryImpl;} }; +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const ObjCCategoryImplDecl *CID); + /// ObjCImplementationDecl - Represents a class definition - this is where /// method definitions are specified. For example: /// @@ -1131,18 +1153,54 @@ public: class ObjCImplementationDecl : public ObjCImplDecl { /// Implementation Class's super class. ObjCInterfaceDecl *SuperClass; - + /// Support for ivar initialization. + /// IvarInitializers - The arguments used to initialize the ivars + CXXBaseOrMemberInitializer **IvarInitializers; + unsigned NumIvarInitializers; + ObjCImplementationDecl(DeclContext *DC, SourceLocation L, ObjCInterfaceDecl *classInterface, ObjCInterfaceDecl *superDecl) : ObjCImplDecl(ObjCImplementation, DC, L, classInterface), - SuperClass(superDecl){} + SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0) {} public: static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, ObjCInterfaceDecl *classInterface, ObjCInterfaceDecl *superDecl); - + + /// init_iterator - Iterates through the ivar initializer list. + typedef CXXBaseOrMemberInitializer **init_iterator; + + /// init_const_iterator - Iterates through the ivar initializer list. + typedef CXXBaseOrMemberInitializer * const * init_const_iterator; + + /// init_begin() - Retrieve an iterator to the first initializer. + init_iterator init_begin() { return IvarInitializers; } + /// begin() - Retrieve an iterator to the first initializer. + init_const_iterator init_begin() const { return IvarInitializers; } + + /// init_end() - Retrieve an iterator past the last initializer. + init_iterator init_end() { + return IvarInitializers + NumIvarInitializers; + } + /// end() - Retrieve an iterator past the last initializer. + init_const_iterator init_end() const { + return IvarInitializers + NumIvarInitializers; + } + /// getNumArgs - Number of ivars which must be initialized. + unsigned getNumIvarInitializers() const { + return NumIvarInitializers; + } + + void setNumIvarInitializers(unsigned numNumIvarInitializers) { + NumIvarInitializers = numNumIvarInitializers; + } + + void setIvarInitializers(ASTContext &C, + CXXBaseOrMemberInitializer ** initializers, + unsigned numInitializers); + /// getIdentifier - Get the identifier that names the class /// interface associated with this implementation. IdentifierInfo *getIdentifier() const { @@ -1199,6 +1257,9 @@ public: static bool classofKind(Kind K) { return K == ObjCImplementation; } }; +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const ObjCImplementationDecl *ID); + /// ObjCCompatibleAliasDecl - Represents alias of a class. This alias is /// declared as @compatibility_alias alias class. class ObjCCompatibleAliasDecl : public NamedDecl { diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 8d1a4ca..1ec38ba 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -376,6 +376,81 @@ public: PointOfInstantiation = POI; } }; + +/// \brief Provides information about a dependent function-template +/// specialization declaration. Since explicit function template +/// specialization and instantiation declarations can only appear in +/// namespace scope, and you can only specialize a member of a +/// fully-specialized class, the only way to get one of these is in +/// a friend declaration like the following: +/// +/// template <class T> void foo(T); +/// template <class T> class A { +/// friend void foo<>(T); +/// }; +class DependentFunctionTemplateSpecializationInfo { + union { + // Force sizeof to be a multiple of sizeof(void*) so that the + // trailing data is aligned. + void *Aligner; + + struct { + /// The number of potential template candidates. + unsigned NumTemplates; + + /// The number of template arguments. + unsigned NumArgs; + } d; + }; + + /// The locations of the left and right angle brackets. + SourceRange AngleLocs; + + FunctionTemplateDecl * const *getTemplates() const { + return reinterpret_cast<FunctionTemplateDecl*const*>(this+1); + } + + const TemplateArgumentLoc *getTemplateArgs() const { + return reinterpret_cast<const TemplateArgumentLoc*>( + &getTemplates()[getNumTemplates()]); + } + +public: + DependentFunctionTemplateSpecializationInfo( + const UnresolvedSetImpl &Templates, + const TemplateArgumentListInfo &TemplateArgs); + + /// \brief Returns the number of function templates that this might + /// be a specialization of. + unsigned getNumTemplates() const { + return d.NumTemplates; + } + + /// \brief Returns the i'th template candidate. + FunctionTemplateDecl *getTemplate(unsigned I) const { + assert(I < getNumTemplates() && "template index out of range"); + return getTemplates()[I]; + } + + /// \brief Returns the number of explicit template arguments that were given. + unsigned getNumTemplateArgs() const { + return d.NumArgs; + } + + /// \brief Returns the nth template argument. + const TemplateArgumentLoc &getTemplateArg(unsigned I) const { + assert(I < getNumTemplateArgs() && "template arg index out of range"); + return getTemplateArgs()[I]; + } + + SourceLocation getLAngleLoc() const { + return AngleLocs.getBegin(); + } + + SourceLocation getRAngleLoc() const { + return AngleLocs.getEnd(); + } +}; /// Declaration of a template function. class FunctionTemplateDecl : public TemplateDecl { @@ -652,7 +727,8 @@ class NonTypeTemplateParmDecl NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo) - : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, VarDecl::None), + : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, VarDecl::None, + VarDecl::None), TemplateParmPosition(D, P), DefaultArgument(0) { } @@ -935,6 +1011,11 @@ class ClassTemplatePartialSpecializationDecl TemplateArgumentLoc *ArgsAsWritten; unsigned NumArgsAsWritten; + /// \brief Sequence number indicating when this class template partial + /// specialization was added to the set of partial specializations for + /// its owning class template. + unsigned SequenceNumber; + /// \brief The class template partial specialization from which this /// class template partial specialization was instantiated. /// @@ -950,13 +1031,15 @@ class ClassTemplatePartialSpecializationDecl TemplateArgumentListBuilder &Builder, TemplateArgumentLoc *ArgInfos, unsigned NumArgInfos, - ClassTemplatePartialSpecializationDecl *PrevDecl) + ClassTemplatePartialSpecializationDecl *PrevDecl, + unsigned SequenceNumber) : ClassTemplateSpecializationDecl(Context, ClassTemplatePartialSpecialization, DC, L, SpecializedTemplate, Builder, PrevDecl), TemplateParams(Params), ArgsAsWritten(ArgInfos), - NumArgsAsWritten(NumArgInfos), InstantiatedFromMember(0, false) { } + NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber), + InstantiatedFromMember(0, false) { } public: static ClassTemplatePartialSpecializationDecl * @@ -966,7 +1049,8 @@ public: TemplateArgumentListBuilder &Builder, const TemplateArgumentListInfo &ArgInfos, QualType CanonInjectedType, - ClassTemplatePartialSpecializationDecl *PrevDecl); + ClassTemplatePartialSpecializationDecl *PrevDecl, + unsigned SequenceNumber); /// Get the list of template parameters TemplateParameterList *getTemplateParameters() const { @@ -983,6 +1067,10 @@ public: return NumArgsAsWritten; } + /// \brief Get the sequence number for this class template partial + /// specialization. + unsigned getSequenceNumber() const { return SequenceNumber; } + /// \brief Retrieve the member class template partial specialization from /// which this particular class template partial specialization was /// instantiated. @@ -1046,6 +1134,15 @@ public: "Only member templates can be member template specializations"); return First->InstantiatedFromMember.setInt(true); } + + /// Retrieves the injected specialization type for this partial + /// specialization. This is not the same as the type-decl-type for + /// this partial specialization, which is an InjectedClassNameType. + QualType getInjectedSpecializationType() const { + assert(getTypeForDecl() && "partial specialization has no type set!"); + return cast<InjectedClassNameType>(getTypeForDecl()) + ->getInjectedSpecializationType(); + } // FIXME: Add Profile support! @@ -1141,6 +1238,10 @@ public: return CommonPtr->PartialSpecializations; } + /// \brief Retrieve the partial specializations as an ordered list. + void getPartialSpecializations( + llvm::SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS); + /// \brief Find a class template partial specialization with the given /// type T. /// diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index 6225069..9401786 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -198,9 +198,12 @@ public: /// callee in a call expression with dependent arguments. bool isDependentName() const; - /// getName - Retrieve the human-readable string for this name. + /// getNameAsString - Retrieve the human-readable string for this name. std::string getAsString() const; + /// printName - Print the human-readable name to a stream. + void printName(llvm::raw_ostream &OS) const; + /// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in /// this declaration name, or NULL if this declaration name isn't a /// simple identifier. @@ -331,13 +334,15 @@ public: /// getCXXConstructorName - Returns the name of a C++ constructor /// for the given Type. DeclarationName getCXXConstructorName(CanQualType Ty) { - return getCXXSpecialName(DeclarationName::CXXConstructorName, Ty); + return getCXXSpecialName(DeclarationName::CXXConstructorName, + Ty.getUnqualifiedType()); } /// getCXXDestructorName - Returns the name of a C++ destructor /// for the given Type. DeclarationName getCXXDestructorName(CanQualType Ty) { - return getCXXSpecialName(DeclarationName::CXXDestructorName, Ty); + return getCXXSpecialName(DeclarationName::CXXDestructorName, + Ty.getUnqualifiedType()); } /// getCXXConversionFunctionName - Returns the name of a C++ diff --git a/include/clang/AST/DependentDiagnostic.h b/include/clang/AST/DependentDiagnostic.h index 1954a28..2bbe502 100644 --- a/include/clang/AST/DependentDiagnostic.h +++ b/include/clang/AST/DependentDiagnostic.h @@ -22,6 +22,7 @@ #include "clang/Basic/SourceLocation.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclContextInternals.h" +#include "clang/AST/Type.h" namespace clang { @@ -42,6 +43,7 @@ public: AccessSpecifier AS, NamedDecl *TargetDecl, CXXRecordDecl *NamingClass, + QualType BaseObjectType, const PartialDiagnostic &PDiag) { DependentDiagnostic *DD = Create(Context, Parent, PDiag); DD->AccessData.Loc = Loc.getRawEncoding(); @@ -49,6 +51,7 @@ public: DD->AccessData.Access = AS; DD->AccessData.TargetDecl = TargetDecl; DD->AccessData.NamingClass = NamingClass; + DD->AccessData.BaseObjectType = BaseObjectType.getAsOpaquePtr(); return DD; } @@ -81,6 +84,11 @@ public: return AccessData.NamingClass; } + QualType getAccessBaseObjectType() const { + assert(getKind() == Access); + return QualType::getFromOpaquePtr(AccessData.BaseObjectType); + } + const PartialDiagnostic &getDiagnostic() const { return Diag; } @@ -107,6 +115,7 @@ private: unsigned IsMember : 1; NamedDecl *TargetDecl; CXXRecordDecl *NamingClass; + void *BaseObjectType; } AccessData; }; }; diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index a687ee5..2946e46 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -17,6 +17,9 @@ #include "clang/AST/APValue.h" #include "clang/AST/Stmt.h" #include "clang/AST/Type.h" +#include "clang/AST/DeclAccessPair.h" +#include "clang/AST/ASTVector.h" +#include "clang/AST/UsuallyTinyPtrVector.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallVector.h" @@ -32,11 +35,15 @@ namespace clang { class NamedDecl; class ValueDecl; class BlockDecl; + class CXXBaseSpecifier; class CXXOperatorCallExpr; class CXXMemberCallExpr; class TemplateArgumentLoc; class TemplateArgumentListInfo; +/// \brief A simple array of base specifiers. +typedef UsuallyTinyPtrVector<const CXXBaseSpecifier> CXXBaseSpecifierArray; + /// Expr - This represents one expression. Note that Expr's are subclasses of /// Stmt. This allows an expression to be transparently used any place a Stmt /// is required. @@ -197,6 +204,12 @@ public: /// \brief Returns whether this expression refers to a vector element. bool refersToVectorElement() const; + /// isKnownToHaveBooleanValue - Return true if this is an integer expression + /// that is known to return 0 or 1. This happens for _Bool/bool expressions + /// but also int expressions which are produced by things like comparisons in + /// C. + bool isKnownToHaveBooleanValue() const; + /// isIntegerConstantExpr - Return true if this expression is a valid integer /// constant expression, and, if so, return its value in Result. If not a /// valid i-c-e, return false and fill in Loc (if specified) with the location @@ -210,7 +223,7 @@ public: } /// isConstantInitializer - Returns true if this expression is a constant /// initializer, which can be emitted at compile-time. - bool isConstantInitializer(ASTContext &Ctx) const; + bool isConstantInitializer(ASTContext &Ctx) const; /// EvalResult is a struct with detailed info about an evaluated expression. struct EvalResult { @@ -302,7 +315,7 @@ public: /// its subexpression. If that subexpression is also a ParenExpr, /// then this method recursively returns its subexpression, and so forth. /// Otherwise, the method returns the current Expr. - Expr* IgnoreParens(); + Expr *IgnoreParens(); /// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr /// or CastExprs, returning their operand. @@ -331,7 +344,7 @@ public: /// temporary object. const Expr *getTemporaryObject() const; - const Expr* IgnoreParens() const { + const Expr *IgnoreParens() const { return const_cast<Expr*>(this)->IgnoreParens(); } const Expr *IgnoreParenCasts() const { @@ -901,7 +914,7 @@ public: /// /// __builtin_offsetof(type, a.b[10]) is represented as a unary operator whose /// subexpression is a compound literal with the various MemberExpr and -/// ArraySubscriptExpr's applied to it. +/// ArraySubscriptExpr's applied to it. (This is only used in C) /// class UnaryOperator : public Expr { public: @@ -990,6 +1003,205 @@ public: virtual child_iterator child_end(); }; +/// OffsetOfExpr - [C99 7.17] - This represents an expression of the form +/// offsetof(record-type, member-designator). For example, given: +/// @code +/// struct S { +/// float f; +/// double d; +/// }; +/// struct T { +/// int i; +/// struct S s[10]; +/// }; +/// @endcode +/// we can represent and evaluate the expression @c offsetof(struct T, s[2].d). + +class OffsetOfExpr : public Expr { +public: + // __builtin_offsetof(type, identifier(.identifier|[expr])*) + class OffsetOfNode { + public: + /// \brief The kind of offsetof node we have. + enum Kind { + /// \brief An index into an array. + Array = 0x00, + /// \brief A field. + Field = 0x01, + /// \brief A field in a dependent type, known only by its name. + Identifier = 0x02, + /// \brief An implicit indirection through a C++ base class, when the + /// field found is in a base class. + Base = 0x03 + }; + + private: + enum { MaskBits = 2, Mask = 0x03 }; + + /// \brief The source range that covers this part of the designator. + SourceRange Range; + + /// \brief The data describing the designator, which comes in three + /// different forms, depending on the lower two bits. + /// - An unsigned index into the array of Expr*'s stored after this node + /// in memory, for [constant-expression] designators. + /// - A FieldDecl*, for references to a known field. + /// - An IdentifierInfo*, for references to a field with a given name + /// when the class type is dependent. + /// - A CXXBaseSpecifier*, for references that look at a field in a + /// base class. + uintptr_t Data; + + public: + /// \brief Create an offsetof node that refers to an array element. + OffsetOfNode(SourceLocation LBracketLoc, unsigned Index, + SourceLocation RBracketLoc) + : Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) { } + + /// \brief Create an offsetof node that refers to a field. + OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field, + SourceLocation NameLoc) + : Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc), + Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) { } + + /// \brief Create an offsetof node that refers to an identifier. + OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name, + SourceLocation NameLoc) + : Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc), + Data(reinterpret_cast<uintptr_t>(Name) | Identifier) { } + + /// \brief Create an offsetof node that refers into a C++ base class. + explicit OffsetOfNode(const CXXBaseSpecifier *Base) + : Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {} + + /// \brief Determine what kind of offsetof node this is. + Kind getKind() const { + return static_cast<Kind>(Data & Mask); + } + + /// \brief For an array element node, returns the index into the array + /// of expressions. + unsigned getArrayExprIndex() const { + assert(getKind() == Array); + return Data >> 2; + } + + /// \brief For a field offsetof node, returns the field. + FieldDecl *getField() const { + assert(getKind() == Field); + return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask); + } + + /// \brief For a field or identifier offsetof node, returns the name of + /// the field. + IdentifierInfo *getFieldName() const; + + /// \brief For a base class node, returns the base specifier. + CXXBaseSpecifier *getBase() const { + assert(getKind() == Base); + return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask); + } + + /// \brief Retrieve the source range that covers this offsetof node. + /// + /// For an array element node, the source range contains the locations of + /// the square brackets. For a field or identifier node, the source range + /// contains the location of the period (if there is one) and the + /// identifier. + SourceRange getRange() const { return Range; } + }; + +private: + + SourceLocation OperatorLoc, RParenLoc; + // Base type; + TypeSourceInfo *TSInfo; + // Number of sub-components (i.e. instances of OffsetOfNode). + unsigned NumComps; + // Number of sub-expressions (i.e. array subscript expressions). + unsigned NumExprs; + + OffsetOfExpr(ASTContext &C, QualType type, + SourceLocation OperatorLoc, TypeSourceInfo *tsi, + OffsetOfNode* compsPtr, unsigned numComps, + Expr** exprsPtr, unsigned numExprs, + SourceLocation RParenLoc); + + explicit OffsetOfExpr(unsigned numComps, unsigned numExprs) + : Expr(OffsetOfExprClass, EmptyShell()), + TSInfo(0), NumComps(numComps), NumExprs(numExprs) {} + +public: + + static OffsetOfExpr *Create(ASTContext &C, QualType type, + SourceLocation OperatorLoc, TypeSourceInfo *tsi, + OffsetOfNode* compsPtr, unsigned numComps, + Expr** exprsPtr, unsigned numExprs, + SourceLocation RParenLoc); + + static OffsetOfExpr *CreateEmpty(ASTContext &C, + unsigned NumComps, unsigned NumExprs); + + /// getOperatorLoc - Return the location of the operator. + SourceLocation getOperatorLoc() const { return OperatorLoc; } + void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } + + /// \brief Return the location of the right parentheses. + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation R) { RParenLoc = R; } + + TypeSourceInfo *getTypeSourceInfo() const { + return TSInfo; + } + void setTypeSourceInfo(TypeSourceInfo *tsi) { + TSInfo = tsi; + } + + const OffsetOfNode &getComponent(unsigned Idx) { + assert(Idx < NumComps && "Subscript out of range"); + return reinterpret_cast<OffsetOfNode *> (this + 1)[Idx]; + } + + void setComponent(unsigned Idx, OffsetOfNode ON) { + assert(Idx < NumComps && "Subscript out of range"); + reinterpret_cast<OffsetOfNode *> (this + 1)[Idx] = ON; + } + + unsigned getNumComponents() const { + return NumComps; + } + + Expr* getIndexExpr(unsigned Idx) { + assert(Idx < NumExprs && "Subscript out of range"); + return reinterpret_cast<Expr **>( + reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx]; + } + + void setIndexExpr(unsigned Idx, Expr* E) { + assert(Idx < NumComps && "Subscript out of range"); + reinterpret_cast<Expr **>( + reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx] = E; + } + + unsigned getNumExpressions() const { + return NumExprs; + } + + virtual SourceRange getSourceRange() const { + return SourceRange(OperatorLoc, RParenLoc); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OffsetOfExprClass; + } + + static bool classof(const OffsetOfExpr *) { return true; } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); +}; + /// SizeOfAlignOfExpr - [C99 6.5.3.4] - This is for sizeof/alignof, both of /// types and expressions. class SizeOfAlignOfExpr : public Expr { @@ -1274,7 +1486,7 @@ public: class MemberExpr : public Expr { /// Extra data stored in some member expressions. struct MemberNameQualifier : public NameQualifier { - NamedDecl *FoundDecl; + DeclAccessPair FoundDecl; }; /// Base - the expression for the base pointer or structure references. In @@ -1349,7 +1561,7 @@ public: static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow, NestedNameSpecifier *qual, SourceRange qualrange, - ValueDecl *memberdecl, NamedDecl *founddecl, + ValueDecl *memberdecl, DeclAccessPair founddecl, SourceLocation l, const TemplateArgumentListInfo *targs, QualType ty); @@ -1365,9 +1577,10 @@ public: void setMemberDecl(ValueDecl *D) { MemberDecl = D; } /// \brief Retrieves the declaration found by lookup. - NamedDecl *getFoundDecl() const { + DeclAccessPair getFoundDecl() const { if (!HasQualifierOrFoundDecl) - return getMemberDecl(); + return DeclAccessPair::make(getMemberDecl(), + getMemberDecl()->getAccess()); return getMemberQualifier()->FoundDecl; } @@ -1636,8 +1849,53 @@ public: private: CastKind Kind; Stmt *Op; + + /// BasePath - For derived-to-base and base-to-derived casts, the base array + /// contains the inheritance path. + CXXBaseSpecifierArray BasePath; + + void CheckBasePath() const { +#ifndef NDEBUG + switch (getCastKind()) { + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: + case CK_DerivedToBaseMemberPointer: + case CK_BaseToDerived: + case CK_BaseToDerivedMemberPointer: + assert(!BasePath.empty() && "Cast kind should have a base path!"); + break; + + // These should not have an inheritance path. + case CK_Unknown: + case CK_BitCast: + case CK_NoOp: + case CK_Dynamic: + case CK_ToUnion: + case CK_ArrayToPointerDecay: + case CK_FunctionToPointerDecay: + case CK_NullToMemberPointer: + case CK_UserDefinedConversion: + case CK_ConstructorConversion: + case CK_IntegralToPointer: + case CK_PointerToIntegral: + case CK_ToVoid: + case CK_VectorSplat: + case CK_IntegralCast: + case CK_IntegralToFloating: + case CK_FloatingToIntegral: + case CK_FloatingCast: + case CK_MemberPointerToBoolean: + case CK_AnyPointerToObjCPointerCast: + case CK_AnyPointerToBlockPointerCast: + assert(BasePath.empty() && "Cast kind should not have a base path!"); + break; + } +#endif + } + protected: - CastExpr(StmtClass SC, QualType ty, const CastKind kind, Expr *op) : + CastExpr(StmtClass SC, QualType ty, const CastKind kind, Expr *op, + CXXBaseSpecifierArray BasePath) : Expr(SC, ty, // Cast expressions are type-dependent if the type is // dependent (C++ [temp.dep.expr]p3). @@ -1645,12 +1903,16 @@ protected: // Cast expressions are value-dependent if the type is // dependent or if the subexpression is value-dependent. ty->isDependentType() || (op && op->isValueDependent())), - Kind(kind), Op(op) {} + Kind(kind), Op(op), BasePath(BasePath) { + CheckBasePath(); + } /// \brief Construct an empty cast. CastExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) { } + virtual void DoDestroy(ASTContext &C); + public: CastKind getCastKind() const { return Kind; } void setCastKind(CastKind K) { Kind = K; } @@ -1667,10 +1929,12 @@ public: const Expr *getSubExprAsWritten() const { return const_cast<CastExpr *>(this)->getSubExprAsWritten(); } - + + const CXXBaseSpecifierArray& getBasePath() const { return BasePath; } + static bool classof(const Stmt *T) { StmtClass SC = T->getStmtClass(); - if (SC >= CXXNamedCastExprClass && SC <= CXXFunctionalCastExprClass) + if (SC >= CXXStaticCastExprClass && SC <= CXXFunctionalCastExprClass) return true; if (SC >= ImplicitCastExprClass && SC <= CStyleCastExprClass) @@ -1706,14 +1970,15 @@ class ImplicitCastExpr : public CastExpr { bool LvalueCast; public: - ImplicitCastExpr(QualType ty, CastKind kind, Expr *op, bool Lvalue) : - CastExpr(ImplicitCastExprClass, ty, kind, op), LvalueCast(Lvalue) { } + ImplicitCastExpr(QualType ty, CastKind kind, Expr *op, + CXXBaseSpecifierArray BasePath, bool Lvalue) + : CastExpr(ImplicitCastExprClass, ty, kind, op, BasePath), + LvalueCast(Lvalue) { } /// \brief Construct an empty implicit cast. explicit ImplicitCastExpr(EmptyShell Shell) : CastExpr(ImplicitCastExprClass, Shell) { } - virtual SourceRange getSourceRange() const { return getSubExpr()->getSourceRange(); } @@ -1753,8 +2018,9 @@ class ExplicitCastExpr : public CastExpr { protected: ExplicitCastExpr(StmtClass SC, QualType exprTy, CastKind kind, - Expr *op, TypeSourceInfo *writtenTy) - : CastExpr(SC, exprTy, kind, op), TInfo(writtenTy) {} + Expr *op, CXXBaseSpecifierArray BasePath, + TypeSourceInfo *writtenTy) + : CastExpr(SC, exprTy, kind, op, BasePath), TInfo(writtenTy) {} /// \brief Construct an empty explicit cast. ExplicitCastExpr(StmtClass SC, EmptyShell Shell) @@ -1774,7 +2040,7 @@ public: StmtClass SC = T->getStmtClass(); if (SC >= CStyleCastExprClass && SC <= CStyleCastExprClass) return true; - if (SC >= CXXNamedCastExprClass && SC <= CXXFunctionalCastExprClass) + if (SC >= CXXStaticCastExprClass && SC <= CXXFunctionalCastExprClass) return true; return false; @@ -1790,10 +2056,10 @@ class CStyleCastExpr : public ExplicitCastExpr { SourceLocation RPLoc; // the location of the right paren public: CStyleCastExpr(QualType exprTy, CastKind kind, Expr *op, - TypeSourceInfo *writtenTy, - SourceLocation l, SourceLocation r) : - ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, writtenTy), - LPLoc(l), RPLoc(r) {} + CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, + SourceLocation l, SourceLocation r) + : ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, BasePath, + writtenTy), LPLoc(l), RPLoc(r) {} /// \brief Construct an empty C-style explicit cast. explicit CStyleCastExpr(EmptyShell Shell) @@ -2362,7 +2628,7 @@ public: virtual child_iterator child_end(); }; -/// VAArgExpr, used for the builtin function __builtin_va_start. +/// VAArgExpr, used for the builtin function __builtin_va_arg. class VAArgExpr : public Expr { Stmt *Val; SourceLocation BuiltinLoc, RParenLoc; @@ -2373,7 +2639,7 @@ public: BuiltinLoc(BLoc), RParenLoc(RPLoc) { } - /// \brief Create an empty __builtin_va_start expression. + /// \brief Create an empty __builtin_va_arg expression. explicit VAArgExpr(EmptyShell Empty) : Expr(VAArgExprClass, Empty) { } const Expr *getSubExpr() const { return cast<Expr>(Val); } @@ -2438,7 +2704,8 @@ public: /// serves as its syntactic form. class InitListExpr : public Expr { // FIXME: Eliminate this vector in favor of ASTContext allocation - std::vector<Stmt *> InitExprs; + typedef ASTVector<Stmt *> InitExprsTy; + InitExprsTy InitExprs; SourceLocation LBraceLoc, RBraceLoc; /// Contains the initializer list that describes the syntactic form @@ -2454,11 +2721,13 @@ class InitListExpr : public Expr { bool HadArrayRangeDesignator; public: - InitListExpr(SourceLocation lbraceloc, Expr **initexprs, unsigned numinits, + InitListExpr(ASTContext &C, SourceLocation lbraceloc, + Expr **initexprs, unsigned numinits, SourceLocation rbraceloc); /// \brief Build an empty initializer list. - explicit InitListExpr(EmptyShell Empty) : Expr(InitListExprClass, Empty) { } + explicit InitListExpr(ASTContext &C, EmptyShell Empty) + : Expr(InitListExprClass, Empty), InitExprs(C) { } unsigned getNumInits() const { return InitExprs.size(); } @@ -2478,7 +2747,7 @@ public: } /// \brief Reserve space for some number of initializers. - void reserveInits(unsigned NumInits); + void reserveInits(ASTContext &C, unsigned NumInits); /// @brief Specify the number of initializers /// @@ -2495,7 +2764,7 @@ public: /// When @p Init is out of range for this initializer list, the /// initializer list will be extended with NULL expressions to /// accomodate the new entry. - Expr *updateInit(unsigned Init, Expr *expr); + Expr *updateInit(ASTContext &C, unsigned Init, Expr *expr); /// \brief If this initializes a union, specifies which field in the /// union to initialize. @@ -2541,8 +2810,8 @@ public: virtual child_iterator child_begin(); virtual child_iterator child_end(); - typedef std::vector<Stmt *>::iterator iterator; - typedef std::vector<Stmt *>::reverse_iterator reverse_iterator; + typedef InitExprsTy::iterator iterator; + typedef InitExprsTy::reverse_iterator reverse_iterator; iterator begin() { return InitExprs.begin(); } iterator end() { return InitExprs.end(); } diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 6e2e832..f9ca78a 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -118,8 +118,9 @@ private: protected: CXXNamedCastExpr(StmtClass SC, QualType ty, CastKind kind, Expr *op, - TypeSourceInfo *writtenTy, SourceLocation l) - : ExplicitCastExpr(SC, ty, kind, op, writtenTy), Loc(l) {} + CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, + SourceLocation l) + : ExplicitCastExpr(SC, ty, kind, op, BasePath, writtenTy), Loc(l) {} explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell) : ExplicitCastExpr(SC, Shell) { } @@ -137,7 +138,6 @@ public: } static bool classof(const Stmt *T) { switch (T->getStmtClass()) { - case CXXNamedCastExprClass: case CXXStaticCastExprClass: case CXXDynamicCastExprClass: case CXXReinterpretCastExprClass: @@ -156,9 +156,10 @@ public: /// @c static_cast<int>(1.0). class CXXStaticCastExpr : public CXXNamedCastExpr { public: - CXXStaticCastExpr(QualType ty, CastKind kind, Expr *op, - TypeSourceInfo *writtenTy, SourceLocation l) - : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, writtenTy, l) {} + CXXStaticCastExpr(QualType ty, CastKind kind, Expr *op, + CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, + SourceLocation l) + : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, BasePath, writtenTy, l) {} explicit CXXStaticCastExpr(EmptyShell Empty) : CXXNamedCastExpr(CXXStaticCastExprClass, Empty) { } @@ -177,9 +178,11 @@ public: /// @c dynamic_cast<Derived*>(BasePtr). class CXXDynamicCastExpr : public CXXNamedCastExpr { public: - CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op, - TypeSourceInfo *writtenTy, SourceLocation l) - : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, writtenTy, l) {} + CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op, + CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, + SourceLocation l) + : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, BasePath, + writtenTy, l) {} explicit CXXDynamicCastExpr(EmptyShell Empty) : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty) { } @@ -199,8 +202,9 @@ public: class CXXReinterpretCastExpr : public CXXNamedCastExpr { public: CXXReinterpretCastExpr(QualType ty, CastKind kind, Expr *op, + CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, SourceLocation l) - : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, + : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, BasePath, writtenTy, l) {} explicit CXXReinterpretCastExpr(EmptyShell Empty) @@ -221,7 +225,8 @@ class CXXConstCastExpr : public CXXNamedCastExpr { public: CXXConstCastExpr(QualType ty, Expr *op, TypeSourceInfo *writtenTy, SourceLocation l) - : CXXNamedCastExpr(CXXConstCastExprClass, ty, CK_NoOp, op, writtenTy, l) {} + : CXXNamedCastExpr(CXXConstCastExprClass, ty, CK_NoOp, op, + CXXBaseSpecifierArray(), writtenTy, l) {} explicit CXXConstCastExpr(EmptyShell Empty) : CXXNamedCastExpr(CXXConstCastExprClass, Empty) { } @@ -293,37 +298,41 @@ public: /// This represents code like @c typeid(int) or @c typeid(*objPtr) class CXXTypeidExpr : public Expr { private: - bool isTypeOp : 1; - union { - void *Ty; - Stmt *Ex; - } Operand; + llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand; SourceRange Range; public: - CXXTypeidExpr(bool isTypeOp, void *op, QualType Ty, const SourceRange r) : - Expr(CXXTypeidExprClass, Ty, + CXXTypeidExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R) + : Expr(CXXTypeidExprClass, Ty, + // typeid is never type-dependent (C++ [temp.dep.expr]p4) + false, + // typeid is value-dependent if the type or expression are dependent + Operand->getType()->isDependentType()), + Operand(Operand), Range(R) { } + + CXXTypeidExpr(QualType Ty, Expr *Operand, SourceRange R) + : Expr(CXXTypeidExprClass, Ty, // typeid is never type-dependent (C++ [temp.dep.expr]p4) false, // typeid is value-dependent if the type or expression are dependent - (isTypeOp ? QualType::getFromOpaquePtr(op)->isDependentType() - : static_cast<Expr*>(op)->isValueDependent())), - isTypeOp(isTypeOp), Range(r) { - if (isTypeOp) - Operand.Ty = op; - else - // op was an Expr*, so cast it back to that to be safe - Operand.Ex = static_cast<Expr*>(op); - } + Operand->isTypeDependent() || Operand->isValueDependent()), + Operand(Operand), Range(R) { } + + bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } + + /// \brief Retrieves the type operand of this typeid() expression after + /// various required adjustments (removing reference types, cv-qualifiers). + QualType getTypeOperand() const; - bool isTypeOperand() const { return isTypeOp; } - QualType getTypeOperand() const { + /// \brief Retrieve source information for the type operand. + TypeSourceInfo *getTypeOperandSourceInfo() const { assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); - return QualType::getFromOpaquePtr(Operand.Ty); + return Operand.get<TypeSourceInfo *>(); } + Expr* getExprOperand() const { assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)"); - return static_cast<Expr*>(Operand.Ex); + return static_cast<Expr*>(Operand.get<Stmt *>()); } virtual SourceRange getSourceRange() const { @@ -621,12 +630,20 @@ public: /// CXXConstructExpr - Represents a call to a C++ constructor. class CXXConstructExpr : public Expr { +public: + enum ConstructionKind { + CK_Complete, + CK_NonVirtualBase, + CK_VirtualBase + }; + +private: CXXConstructorDecl *Constructor; SourceLocation Loc; bool Elidable : 1; bool ZeroInitialization : 1; - bool BaseInitialization : 1; + unsigned ConstructKind : 2; Stmt **Args; unsigned NumArgs; @@ -636,7 +653,7 @@ protected: CXXConstructorDecl *d, bool elidable, Expr **args, unsigned numargs, bool ZeroInitialization = false, - bool BaseInitialization = false); + ConstructionKind ConstructKind = CK_Complete); ~CXXConstructExpr() { } virtual void DoDestroy(ASTContext &C); @@ -651,7 +668,7 @@ public: CXXConstructorDecl *D, bool Elidable, Expr **Args, unsigned NumArgs, bool ZeroInitialization = false, - bool BaseInitialization = false); + ConstructionKind ConstructKind = CK_Complete); CXXConstructorDecl* getConstructor() const { return Constructor; } @@ -673,8 +690,12 @@ public: /// \brief Determines whether this constructor is actually constructing /// a base class (rather than a complete object). - bool isBaseInitialization() const { return BaseInitialization; } - void setBaseInitialization(bool BI) { BaseInitialization = BI; } + ConstructionKind getConstructionKind() const { + return (ConstructionKind)ConstructKind; + } + void setConstructionKind(ConstructionKind CK) { + ConstructKind = CK; + } typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; @@ -725,9 +746,10 @@ class CXXFunctionalCastExpr : public ExplicitCastExpr { public: CXXFunctionalCastExpr(QualType ty, TypeSourceInfo *writtenTy, SourceLocation tyBeginLoc, CastKind kind, - Expr *castExpr, SourceLocation rParenLoc) + Expr *castExpr, CXXBaseSpecifierArray BasePath, + SourceLocation rParenLoc) : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, kind, castExpr, - writtenTy), + BasePath, writtenTy), TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} explicit CXXFunctionalCastExpr(EmptyShell Shell) @@ -774,7 +796,8 @@ public: CXXTemporaryObjectExpr(ASTContext &C, CXXConstructorDecl *Cons, QualType writtenTy, SourceLocation tyBeginLoc, Expr **Args,unsigned NumArgs, - SourceLocation rParenLoc); + SourceLocation rParenLoc, + bool ZeroInitialization = false); ~CXXTemporaryObjectExpr() { } @@ -1290,6 +1313,9 @@ public: Results.append(Begin, End); } + /// Gets the naming class of this lookup, if any. + CXXRecordDecl *getNamingClass() const; + typedef UnresolvedSetImpl::iterator decls_iterator; decls_iterator decls_begin() const { return Results.begin(); } decls_iterator decls_end() const { return Results.end(); } diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index 6f43973..8a09f4e 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -59,13 +59,14 @@ public: /// and behavior as StringLiteral except that the string initializer is obtained /// from ASTContext with the encoding type as an argument. class ObjCEncodeExpr : public Expr { - QualType EncType; + TypeSourceInfo *EncodedType; SourceLocation AtLoc, RParenLoc; public: - ObjCEncodeExpr(QualType T, QualType ET, + ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType, SourceLocation at, SourceLocation rp) - : Expr(ObjCEncodeExprClass, T, ET->isDependentType(), - ET->isDependentType()), EncType(ET), AtLoc(at), RParenLoc(rp) {} + : Expr(ObjCEncodeExprClass, T, EncodedType->getType()->isDependentType(), + EncodedType->getType()->isDependentType()), + EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) {} explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){} @@ -75,9 +76,12 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - QualType getEncodedType() const { return EncType; } - void setEncodedType(QualType T) { EncType = T; } + QualType getEncodedType() const { return EncodedType->getType(); } + TypeSourceInfo *getEncodedTypeSourceInfo() const { return EncodedType; } + void setEncodedTypeSourceInfo(TypeSourceInfo *EncType) { + EncodedType = EncType; + } virtual SourceRange getSourceRange() const { return SourceRange(AtLoc, RParenLoc); @@ -177,11 +181,12 @@ class ObjCIvarRefExpr : public Expr { public: ObjCIvarRefExpr(ObjCIvarDecl *d, - QualType t, SourceLocation l, Expr *base=0, + QualType t, SourceLocation l, Expr *base, bool arrow = false, bool freeIvar = false) : - Expr(ObjCIvarRefExprClass, t, false, false), D(d), - Loc(l), Base(base), IsArrow(arrow), - IsFreeIvar(freeIvar) {} + Expr(ObjCIvarRefExprClass, t, /*TypeDependent=*/false, + base->isValueDependent()), D(d), + Loc(l), Base(base), IsArrow(arrow), + IsFreeIvar(freeIvar) {} explicit ObjCIvarRefExpr(EmptyShell Empty) : Expr(ObjCIvarRefExprClass, Empty) {} @@ -228,8 +233,9 @@ private: public: ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, SourceLocation l, Expr *base) - : Expr(ObjCPropertyRefExprClass, t, false, false), AsProperty(PD), - IdLoc(l), Base(base) { + : Expr(ObjCPropertyRefExprClass, t, /*TypeDependent=*/false, + base->isValueDependent()), + AsProperty(PD), IdLoc(l), Base(base) { } explicit ObjCPropertyRefExpr(EmptyShell Empty) @@ -293,7 +299,8 @@ public: QualType t, ObjCMethodDecl *setter, SourceLocation l, Expr *base) - : Expr(ObjCImplicitSetterGetterRefExprClass, t, false, false), + : Expr(ObjCImplicitSetterGetterRefExprClass, t, /*TypeDependent=*/false, + base->isValueDependent()), Setter(setter), Getter(getter), MemberLoc(l), Base(base), InterfaceDecl(0), ClassLoc(SourceLocation()) { } @@ -339,152 +346,376 @@ public: virtual child_iterator child_end(); }; +/// \brief An expression that sends a message to the given Objective-C +/// object or class. +/// +/// The following contains two message send expressions: +/// +/// \code +/// [[NSString alloc] initWithString:@"Hello"] +/// \endcode +/// +/// The innermost message send invokes the "alloc" class method on the +/// NSString class, while the outermost message send invokes the +/// "initWithString" instance method on the object returned from +/// NSString's "alloc". In all, an Objective-C message send can take +/// on four different (although related) forms: +/// +/// 1. Send to an object instance. +/// 2. Send to a class. +/// 3. Send to the superclass instance of the current class. +/// 4. Send to the superclass of the current class. +/// +/// All four kinds of message sends are modeled by the ObjCMessageExpr +/// class, and can be distinguished via \c getReceiverKind(). Example: +/// class ObjCMessageExpr : public Expr { - // SubExprs - The receiver and arguments of the message expression. - Stmt **SubExprs; + /// \brief The number of arguments in the message send, not + /// including the receiver. + unsigned NumArgs : 16; + + /// \brief The kind of message send this is, which is one of the + /// ReceiverKind values. + /// + /// We pad this out to a byte to avoid excessive masking and shifting. + unsigned Kind : 8; + + /// \brief Whether we have an actual method prototype in \c + /// SelectorOrMethod. + /// + /// When non-zero, we have a method declaration; otherwise, we just + /// have a selector. + unsigned HasMethod : 8; + + /// \brief When the message expression is a send to 'super', this is + /// the location of the 'super' keyword. + SourceLocation SuperLoc; + + /// \brief Stores either the selector that this message is sending + /// to (when \c HasMethod is zero) or an \c ObjCMethodDecl pointer + /// referring to the method that we type-checked against. + uintptr_t SelectorOrMethod; + + /// \brief The source locations of the open and close square + /// brackets ('[' and ']', respectively). + SourceLocation LBracLoc, RBracLoc; + + ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs) + : Expr(ObjCMessageExprClass, Empty), NumArgs(NumArgs), Kind(0), + HasMethod(0), SelectorOrMethod(0) { } + + ObjCMessageExpr(QualType T, + SourceLocation LBracLoc, + SourceLocation SuperLoc, + bool IsInstanceSuper, + QualType SuperType, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + ObjCMessageExpr(QualType T, + SourceLocation LBracLoc, + TypeSourceInfo *Receiver, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + ObjCMessageExpr(QualType T, + SourceLocation LBracLoc, + Expr *Receiver, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + + /// \brief Retrieve the pointer value of the message receiver. + void *getReceiverPointer() const { + return *const_cast<void **>( + reinterpret_cast<const void * const*>(this + 1)); + } - // NumArgs - The number of arguments (not including the receiver) to the - // message expression. - unsigned NumArgs; + /// \brief Set the pointer value of the message receiver. + void setReceiverPointer(void *Value) { + *reinterpret_cast<void **>(this + 1) = Value; + } - /// \brief The location of the class name in a class message. - SourceLocation ClassNameLoc; +public: + /// \brief The kind of receiver this message is sending to. + enum ReceiverKind { + /// \brief The receiver is a class. + Class = 0, + /// \brief The receiver is an object instance. + Instance, + /// \brief The receiver is a superclass. + SuperClass, + /// \brief The receiver is the instance of the superclass object. + SuperInstance + }; - // A unigue name for this message. - Selector SelName; + /// \brief Create a message send to super. + /// + /// \param Context The ASTContext in which this expression will be created. + /// + /// \param T The result type of this message. + /// + /// \param LBrac The location of the open square bracket '['. + /// + /// \param SuperLoc The location of the "super" keyword. + /// + /// \param IsInstanceSuper Whether this is an instance "super" + /// message (otherwise, it's a class "super" message). + /// + /// \param Sel The selector used to determine which method gets called. + /// + /// \param Method The Objective-C method against which this message + /// send was type-checked. May be NULL. + /// + /// \param Args The message send arguments. + /// + /// \param NumArgs The number of arguments. + /// + /// \param RBracLoc The location of the closing square bracket ']'. + static ObjCMessageExpr *Create(ASTContext &Context, QualType T, + SourceLocation LBracLoc, + SourceLocation SuperLoc, + bool IsInstanceSuper, + QualType SuperType, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + + /// \brief Create a class message send. + /// + /// \param Context The ASTContext in which this expression will be created. + /// + /// \param T The result type of this message. + /// + /// \param LBrac The location of the open square bracket '['. + /// + /// \param Receiver The type of the receiver, including + /// source-location information. + /// + /// \param Sel The selector used to determine which method gets called. + /// + /// \param Method The Objective-C method against which this message + /// send was type-checked. May be NULL. + /// + /// \param Args The message send arguments. + /// + /// \param NumArgs The number of arguments. + /// + /// \param RBracLoc The location of the closing square bracket ']'. + static ObjCMessageExpr *Create(ASTContext &Context, QualType T, + SourceLocation LBracLoc, + TypeSourceInfo *Receiver, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + + /// \brief Create an instance message send. + /// + /// \param Context The ASTContext in which this expression will be created. + /// + /// \param T The result type of this message. + /// + /// \param LBrac The location of the open square bracket '['. + /// + /// \param Receiver The expression used to produce the object that + /// will receive this message. + /// + /// \param Sel The selector used to determine which method gets called. + /// + /// \param Method The Objective-C method against which this message + /// send was type-checked. May be NULL. + /// + /// \param Args The message send arguments. + /// + /// \param NumArgs The number of arguments. + /// + /// \param RBracLoc The location of the closing square bracket ']'. + static ObjCMessageExpr *Create(ASTContext &Context, QualType T, + SourceLocation LBracLoc, + Expr *Receiver, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + + /// \brief Create an empty Objective-C message expression, to be + /// filled in by subsequent calls. + /// + /// \param Context The context in which the message send will be created. + /// + /// \param NumArgs The number of message arguments, not including + /// the receiver. + static ObjCMessageExpr *CreateEmpty(ASTContext &Context, unsigned NumArgs); + + /// \brief Determine the kind of receiver that this message is being + /// sent to. + ReceiverKind getReceiverKind() const { return (ReceiverKind)Kind; } + + /// \brief Determine whether this is an instance message to either a + /// computed object or to super. + bool isInstanceMessage() const { + return getReceiverKind() == Instance || getReceiverKind() == SuperInstance; + } - // A method prototype for this message (optional). - // FIXME: Since method decls contain the selector, and most messages have a - // prototype, consider devising a scheme for unifying SelName/MethodProto. - ObjCMethodDecl *MethodProto; + /// \brief Determine whether this is an class message to either a + /// specified class or to super. + bool isClassMessage() const { + return getReceiverKind() == Class || getReceiverKind() == SuperClass; + } - SourceLocation LBracloc, RBracloc; + /// \brief Returns the receiver of an instance message. + /// + /// \brief Returns the object expression for an instance message, or + /// NULL for a message that is not an instance message. + Expr *getInstanceReceiver() { + if (getReceiverKind() == Instance) + return static_cast<Expr *>(getReceiverPointer()); - // Constants for indexing into SubExprs. - enum { RECEIVER=0, ARGS_START=1 }; + return 0; + } + const Expr *getInstanceReceiver() const { + return const_cast<ObjCMessageExpr*>(this)->getInstanceReceiver(); + } - // Bit-swizzling flags. - enum { IsInstMeth=0, IsClsMethDeclUnknown, IsClsMethDeclKnown, Flags=0x3 }; - unsigned getFlag() const { return (uintptr_t) SubExprs[RECEIVER] & Flags; } + /// \brief Turn this message send into an instance message that + /// computes the receiver object with the given expression. + void setInstanceReceiver(Expr *rec) { + Kind = Instance; + setReceiverPointer(rec); + } + + /// \brief Returns the type of a class message send, or NULL if the + /// message is not a class message. + QualType getClassReceiver() const { + if (TypeSourceInfo *TSInfo = getClassReceiverTypeInfo()) + return TSInfo->getType(); + + return QualType(); + } -public: - /// This constructor is used to represent class messages where the - /// ObjCInterfaceDecl* of the receiver is not known. - ObjCMessageExpr(ASTContext &C, IdentifierInfo *clsName, - SourceLocation clsNameLoc, Selector selInfo, - QualType retType, ObjCMethodDecl *methDecl, - SourceLocation LBrac, SourceLocation RBrac, - Expr **ArgExprs, unsigned NumArgs); - - /// This constructor is used to represent class messages where the - /// ObjCInterfaceDecl* of the receiver is known. - // FIXME: clsName should be typed to ObjCInterfaceType - ObjCMessageExpr(ASTContext &C, ObjCInterfaceDecl *cls, - SourceLocation clsNameLoc, Selector selInfo, - QualType retType, ObjCMethodDecl *methDecl, - SourceLocation LBrac, SourceLocation RBrac, - Expr **ArgExprs, unsigned NumArgs); - - // constructor for instance messages. - ObjCMessageExpr(ASTContext &C, Expr *receiver, Selector selInfo, - QualType retType, ObjCMethodDecl *methDecl, - SourceLocation LBrac, SourceLocation RBrac, - Expr **ArgExprs, unsigned NumArgs); - - explicit ObjCMessageExpr(EmptyShell Empty) - : Expr(ObjCMessageExprClass, Empty), SubExprs(0), NumArgs(0) {} - - virtual void DoDestroy(ASTContext &C); - - /// getReceiver - Returns the receiver of the message expression. - /// This can be NULL if the message is for class methods. For - /// class methods, use getClassName. - /// FIXME: need to handle/detect 'super' usage within a class method. - Expr *getReceiver() { - uintptr_t x = (uintptr_t) SubExprs[RECEIVER]; - return (x & Flags) == IsInstMeth ? (Expr*) x : 0; - } - const Expr *getReceiver() const { - return const_cast<ObjCMessageExpr*>(this)->getReceiver(); - } - // FIXME: need setters for different receiver types. - void setReceiver(Expr *rec) { SubExprs[RECEIVER] = rec; } - Selector getSelector() const { return SelName; } - void setSelector(Selector S) { SelName = S; } + /// \brief Returns a type-source information of a class message + /// send, or NULL if the message is not a class message. + TypeSourceInfo *getClassReceiverTypeInfo() const { + if (getReceiverKind() == Class) + return reinterpret_cast<TypeSourceInfo *>(getReceiverPointer()); + return 0; + } + + void setClassReceiver(TypeSourceInfo *TSInfo) { + Kind = Class; + setReceiverPointer(TSInfo); + } - const ObjCMethodDecl *getMethodDecl() const { return MethodProto; } - ObjCMethodDecl *getMethodDecl() { return MethodProto; } - void setMethodDecl(ObjCMethodDecl *MD) { MethodProto = MD; } + /// \brief Retrieve the location of the 'super' keyword for a class + /// or instance message to 'super', otherwise an invalid source location. + SourceLocation getSuperLoc() const { + if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass) + return SuperLoc; - /// \brief Describes the class receiver of a message send. - struct ClassInfo { - /// \brief The interface declaration for the class that is - /// receiving the message. May be NULL. - ObjCInterfaceDecl *Decl; + return SourceLocation(); + } - /// \brief The name of the class that is receiving the - /// message. This will never be NULL. - IdentifierInfo *Name; + /// \brief Retrieve the Objective-C interface to which this message + /// is being directed, if known. + /// + /// This routine cross-cuts all of the different kinds of message + /// sends to determine what the underlying (statically known) type + /// of the receiver will be; use \c getReceiverKind() to determine + /// whether the message is a class or an instance method, whether it + /// is a send to super or not, etc. + /// + /// \returns The Objective-C interface if known, otherwise NULL. + ObjCInterfaceDecl *getReceiverInterface() const; + + /// \brief Retrieve the type referred to by 'super'. + /// + /// The returned type will either be an ObjCInterfaceType (for an + /// class message to super) or an ObjCObjectPointerType that refers + /// to a class (for an instance message to super); + QualType getSuperType() const { + if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass) + return QualType::getFromOpaquePtr(getReceiverPointer()); + + return QualType(); + } - /// \brief The source location of the class name. - SourceLocation Loc; + void setSuper(SourceLocation Loc, QualType T, bool IsInstanceSuper) { + Kind = IsInstanceSuper? SuperInstance : SuperClass; + SuperLoc = Loc; + setReceiverPointer(T.getAsOpaquePtr()); + } - ClassInfo() : Decl(0), Name(0), Loc() { } + Selector getSelector() const; - ClassInfo(ObjCInterfaceDecl *Decl, IdentifierInfo *Name, SourceLocation Loc) - : Decl(Decl), Name(Name), Loc(Loc) { } - }; + void setSelector(Selector S) { + HasMethod = false; + SelectorOrMethod = reinterpret_cast<uintptr_t>(S.getAsOpaquePtr()); + } - /// getClassInfo - For class methods, this returns both the ObjCInterfaceDecl* - /// and IdentifierInfo* of the invoked class. Both can be NULL if this - /// is an instance message, and the ObjCInterfaceDecl* can be NULL if none - /// was available when this ObjCMessageExpr object was constructed. - ClassInfo getClassInfo() const; - void setClassInfo(const ClassInfo &C); + const ObjCMethodDecl *getMethodDecl() const { + if (HasMethod) + return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod); - /// getClassName - For class methods, this returns the invoked class, - /// and returns NULL otherwise. For instance methods, use getReceiver. - IdentifierInfo *getClassName() const { - return getClassInfo().Name; + return 0; } - /// getNumArgs - Return the number of actual arguments to this call. + ObjCMethodDecl *getMethodDecl() { + if (HasMethod) + return reinterpret_cast<ObjCMethodDecl *>(SelectorOrMethod); + + return 0; + } + + void setMethodDecl(ObjCMethodDecl *MD) { + HasMethod = true; + SelectorOrMethod = reinterpret_cast<uintptr_t>(MD); + } + + /// \brief Return the number of actual arguments in this message, + /// not counting the receiver. unsigned getNumArgs() const { return NumArgs; } - void setNumArgs(unsigned nArgs) { - NumArgs = nArgs; - // FIXME: should always allocate SubExprs via the ASTContext's - // allocator. - if (!SubExprs) - SubExprs = new Stmt* [NumArgs + 1]; + + /// \brief Retrieve the arguments to this message, not including the + /// receiver. + Stmt **getArgs() { + return reinterpret_cast<Stmt **>(this + 1) + 1; + } + const Stmt * const *getArgs() const { + return reinterpret_cast<const Stmt * const *>(this + 1) + 1; } /// getArg - Return the specified argument. Expr *getArg(unsigned Arg) { assert(Arg < NumArgs && "Arg access out of range!"); - return cast<Expr>(SubExprs[Arg+ARGS_START]); + return cast<Expr>(getArgs()[Arg]); } const Expr *getArg(unsigned Arg) const { assert(Arg < NumArgs && "Arg access out of range!"); - return cast<Expr>(SubExprs[Arg+ARGS_START]); + return cast<Expr>(getArgs()[Arg]); } /// setArg - Set the specified argument. void setArg(unsigned Arg, Expr *ArgExpr) { assert(Arg < NumArgs && "Arg access out of range!"); - SubExprs[Arg+ARGS_START] = ArgExpr; + getArgs()[Arg] = ArgExpr; } - SourceLocation getLeftLoc() const { return LBracloc; } - SourceLocation getRightLoc() const { return RBracloc; } + SourceLocation getLeftLoc() const { return LBracLoc; } + SourceLocation getRightLoc() const { return RBracLoc; } - void setLeftLoc(SourceLocation L) { LBracloc = L; } - void setRightLoc(SourceLocation L) { RBracloc = L; } + void setLeftLoc(SourceLocation L) { LBracLoc = L; } + void setRightLoc(SourceLocation L) { RBracLoc = L; } void setSourceRange(SourceRange R) { - LBracloc = R.getBegin(); - RBracloc = R.getEnd(); + LBracLoc = R.getBegin(); + RBracLoc = R.getEnd(); } virtual SourceRange getSourceRange() const { - return SourceRange(LBracloc, RBracloc); + return SourceRange(LBracLoc, RBracLoc); } static bool classof(const Stmt *T) { @@ -499,14 +730,17 @@ public: typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; - arg_iterator arg_begin() { return &SubExprs[ARGS_START]; } - arg_iterator arg_end() { return &SubExprs[ARGS_START] + NumArgs; } - const_arg_iterator arg_begin() const { return &SubExprs[ARGS_START]; } - const_arg_iterator arg_end() const { return &SubExprs[ARGS_START] + NumArgs; } + arg_iterator arg_begin() { return getArgs(); } + arg_iterator arg_end() { return getArgs() + NumArgs; } + const_arg_iterator arg_begin() const { return getArgs(); } + const_arg_iterator arg_end() const { return getArgs() + NumArgs; } }; /// ObjCSuperExpr - Represents the "super" expression in Objective-C, /// which refers to the object on which the current method is executing. +/// +/// FIXME: This class is intended for removal, once its remaining +/// clients have been altered to represent "super" internally. class ObjCSuperExpr : public Expr { SourceLocation Loc; public: @@ -542,7 +776,8 @@ class ObjCIsaExpr : public Expr { bool IsArrow; public: ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, QualType ty) - : Expr(ObjCIsaExprClass, ty, false, false), + : Expr(ObjCIsaExprClass, ty, /*TypeDependent=*/false, + base->isValueDependent()), Base(base), IsaMemberLoc(l), IsArrow(isarrow) {} /// \brief Build an empty expression. diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index b8d80bc..79e4451 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -66,6 +66,13 @@ public: /// building a new declaration. virtual Decl *GetDecl(uint32_t ID) = 0; + /// \brief Resolve a selector ID into a selector. + virtual Selector GetSelector(uint32_t ID) = 0; + + /// \brief Returns the number of selectors known to the external AST + /// source. + virtual uint32_t GetNumKnownSelectors() = 0; + /// \brief Resolve the offset of a statement in the decl stream into a /// statement. /// diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 4668489..0b68a40 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -70,13 +70,13 @@ namespace clang { }; class ConstExprIterator { - Stmt* const * I; + const Stmt * const *I; public: - ConstExprIterator(Stmt* const* i) : I(i) {} + ConstExprIterator(const Stmt * const *i) : I(i) {} ConstExprIterator() : I(0) {} ConstExprIterator& operator++() { ++I; return *this; } - ConstExprIterator operator+(size_t i) { return I+i; } - ConstExprIterator operator-(size_t i) { return I-i; } + ConstExprIterator operator+(size_t i) const { return I+i; } + ConstExprIterator operator-(size_t i) const { return I-i; } const Expr * operator[](size_t idx) const; signed operator-(const ConstExprIterator& R) const { return I - R.I; } const Expr * operator*() const; diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def index ec6149e..3a23e49 100644 --- a/include/clang/AST/StmtNodes.def +++ b/include/clang/AST/StmtNodes.def @@ -78,6 +78,7 @@ EXPR(StringLiteral , Expr) EXPR(CharacterLiteral , Expr) EXPR(ParenExpr , Expr) EXPR(UnaryOperator , Expr) +EXPR(OffsetOfExpr , Expr) EXPR(SizeOfAlignOfExpr , Expr) EXPR(ArraySubscriptExpr , Expr) EXPR(CallExpr , Expr) @@ -107,7 +108,7 @@ EXPR(GNUNullExpr , Expr) // C++ Expressions. EXPR(CXXOperatorCallExpr , CallExpr) EXPR(CXXMemberCallExpr , CallExpr) -EXPR(CXXNamedCastExpr , ExplicitCastExpr) +ABSTRACT_EXPR(CXXNamedCastExpr , ExplicitCastExpr) EXPR(CXXStaticCastExpr , CXXNamedCastExpr) EXPR(CXXDynamicCastExpr , CXXNamedCastExpr) EXPR(CXXReinterpretCastExpr , CXXNamedCastExpr) diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h index 3fd8f16..269aa4c 100644 --- a/include/clang/AST/StmtObjC.h +++ b/include/clang/AST/StmtObjC.h @@ -71,38 +71,31 @@ public: /// ObjCAtCatchStmt - This represents objective-c's @catch statement. class ObjCAtCatchStmt : public Stmt { private: - enum { BODY, NEXT_CATCH, END_EXPR }; - ParmVarDecl *ExceptionDecl; - Stmt *SubExprs[END_EXPR]; + VarDecl *ExceptionDecl; + Stmt *Body; SourceLocation AtCatchLoc, RParenLoc; public: ObjCAtCatchStmt(SourceLocation atCatchLoc, SourceLocation rparenloc, - ParmVarDecl *catchVarDecl, - Stmt *atCatchStmt, Stmt *atCatchList); + VarDecl *catchVarDecl, + Stmt *atCatchStmt) + : Stmt(ObjCAtCatchStmtClass), ExceptionDecl(catchVarDecl), + Body(atCatchStmt), AtCatchLoc(atCatchLoc), RParenLoc(rparenloc) { } explicit ObjCAtCatchStmt(EmptyShell Empty) : Stmt(ObjCAtCatchStmtClass, Empty) { } - const Stmt *getCatchBody() const { return SubExprs[BODY]; } - Stmt *getCatchBody() { return SubExprs[BODY]; } - void setCatchBody(Stmt *S) { SubExprs[BODY] = S; } + const Stmt *getCatchBody() const { return Body; } + Stmt *getCatchBody() { return Body; } + void setCatchBody(Stmt *S) { Body = S; } - const ObjCAtCatchStmt *getNextCatchStmt() const { - return static_cast<const ObjCAtCatchStmt*>(SubExprs[NEXT_CATCH]); - } - ObjCAtCatchStmt *getNextCatchStmt() { - return static_cast<ObjCAtCatchStmt*>(SubExprs[NEXT_CATCH]); - } - void setNextCatchStmt(Stmt *S) { SubExprs[NEXT_CATCH] = S; } - - const ParmVarDecl *getCatchParamDecl() const { + const VarDecl *getCatchParamDecl() const { return ExceptionDecl; } - ParmVarDecl *getCatchParamDecl() { + VarDecl *getCatchParamDecl() { return ExceptionDecl; } - void setCatchParamDecl(ParmVarDecl *D) { ExceptionDecl = D; } + void setCatchParamDecl(VarDecl *D) { ExceptionDecl = D; } SourceLocation getAtCatchLoc() const { return AtCatchLoc; } void setAtCatchLoc(SourceLocation Loc) { AtCatchLoc = Loc; } @@ -110,7 +103,7 @@ public: void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } virtual SourceRange getSourceRange() const { - return SourceRange(AtCatchLoc, SubExprs[BODY]->getLocEnd()); + return SourceRange(AtCatchLoc, Body->getLocEnd()); } bool hasEllipsis() const { return getCatchParamDecl() == 0; } @@ -160,50 +153,94 @@ public: /// @try ... @catch ... @finally statement. class ObjCAtTryStmt : public Stmt { private: - enum { TRY, CATCH, FINALLY, END_EXPR }; - Stmt* SubStmts[END_EXPR]; - + // The location of the SourceLocation AtTryLoc; -public: + + // The number of catch blocks in this statement. + unsigned NumCatchStmts : 16; + + // Whether this statement has a @finally statement. + bool HasFinally : 1; + + /// \brief Retrieve the statements that are stored after this @try statement. + /// + /// The order of the statements in memory follows the order in the source, + /// with the @try body first, followed by the @catch statements (if any) and, + /// finally, the @finally (if it exists). + Stmt **getStmts() { return reinterpret_cast<Stmt **> (this + 1); } + const Stmt* const *getStmts() const { + return reinterpret_cast<const Stmt * const*> (this + 1); + } + ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt, - Stmt *atCatchStmt, - Stmt *atFinallyStmt) - : Stmt(ObjCAtTryStmtClass) { - SubStmts[TRY] = atTryStmt; - SubStmts[CATCH] = atCatchStmt; - SubStmts[FINALLY] = atFinallyStmt; - AtTryLoc = atTryLoc; - } - explicit ObjCAtTryStmt(EmptyShell Empty) : - Stmt(ObjCAtTryStmtClass, Empty) { } + Stmt **CatchStmts, unsigned NumCatchStmts, + Stmt *atFinallyStmt); + + explicit ObjCAtTryStmt(EmptyShell Empty, unsigned NumCatchStmts, + bool HasFinally) + : Stmt(ObjCAtTryStmtClass, Empty), NumCatchStmts(NumCatchStmts), + HasFinally(HasFinally) { } +public: + static ObjCAtTryStmt *Create(ASTContext &Context, SourceLocation atTryLoc, + Stmt *atTryStmt, + Stmt **CatchStmts, unsigned NumCatchStmts, + Stmt *atFinallyStmt); + static ObjCAtTryStmt *CreateEmpty(ASTContext &Context, + unsigned NumCatchStmts, + bool HasFinally); + + /// \brief Retrieve the location of the @ in the @try. SourceLocation getAtTryLoc() const { return AtTryLoc; } void setAtTryLoc(SourceLocation Loc) { AtTryLoc = Loc; } - const Stmt *getTryBody() const { return SubStmts[TRY]; } - Stmt *getTryBody() { return SubStmts[TRY]; } - void setTryBody(Stmt *S) { SubStmts[TRY] = S; } - - const ObjCAtCatchStmt *getCatchStmts() const { - return dyn_cast_or_null<ObjCAtCatchStmt>(SubStmts[CATCH]); + /// \brief Retrieve the @try body. + const Stmt *getTryBody() const { return getStmts()[0]; } + Stmt *getTryBody() { return getStmts()[0]; } + void setTryBody(Stmt *S) { getStmts()[0] = S; } + + /// \brief Retrieve the number of @catch statements in this try-catch-finally + /// block. + unsigned getNumCatchStmts() const { return NumCatchStmts; } + + /// \brief Retrieve a @catch statement. + const ObjCAtCatchStmt *getCatchStmt(unsigned I) const { + assert(I < NumCatchStmts && "Out-of-bounds @catch index"); + return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]); } - ObjCAtCatchStmt *getCatchStmts() { - return dyn_cast_or_null<ObjCAtCatchStmt>(SubStmts[CATCH]); + + /// \brief Retrieve a @catch statement. + ObjCAtCatchStmt *getCatchStmt(unsigned I) { + assert(I < NumCatchStmts && "Out-of-bounds @catch index"); + return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]); } - void setCatchStmts(Stmt *S) { SubStmts[CATCH] = S; } - + + /// \brief Set a particular catch statement. + void setCatchStmt(unsigned I, ObjCAtCatchStmt *S) { + assert(I < NumCatchStmts && "Out-of-bounds @catch index"); + getStmts()[I + 1] = S; + } + + /// Retrieve the @finally statement, if any. const ObjCAtFinallyStmt *getFinallyStmt() const { - return dyn_cast_or_null<ObjCAtFinallyStmt>(SubStmts[FINALLY]); + if (!HasFinally) + return 0; + + return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]); } ObjCAtFinallyStmt *getFinallyStmt() { - return dyn_cast_or_null<ObjCAtFinallyStmt>(SubStmts[FINALLY]); + if (!HasFinally) + return 0; + + return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]); } - void setFinallyStmt(Stmt *S) { SubStmts[FINALLY] = S; } - - virtual SourceRange getSourceRange() const { - return SourceRange(AtTryLoc, SubStmts[TRY]->getLocEnd()); + void setFinallyStmt(Stmt *S) { + assert(HasFinally && "@try does not have a @finally slot!"); + getStmts()[1 + NumCatchStmts] = S; } + virtual SourceRange getSourceRange() const; + static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCAtTryStmtClass; } diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h index aafe963..f3de9fa 100644 --- a/include/clang/AST/TemplateName.h +++ b/include/clang/AST/TemplateName.h @@ -25,6 +25,7 @@ namespace llvm { namespace clang { class DependentTemplateName; +class DiagnosticBuilder; class IdentifierInfo; class NestedNameSpecifier; struct PrintingPolicy; @@ -173,6 +174,11 @@ public: } }; +/// Insertion operator for diagnostics. This allows sending TemplateName's +/// into a diagnostic with <<. +const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + TemplateName N); + /// \brief Represents a template name that was expressed as a /// qualified name. /// diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 7279365..030c74c 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -871,6 +871,7 @@ public: bool isRecordType() const; bool isClassType() const; bool isStructureType() const; + bool isStructureOrClassType() const; bool isUnionType() const; bool isComplexIntegerType() const; // GCC _Complex integer type. bool isVectorType() const; // GCC vector type. @@ -922,6 +923,11 @@ public: const ObjCInterfaceType *getAsObjCQualifiedInterfaceType() const; const CXXRecordDecl *getCXXRecordDeclForPointerType() const; + /// \brief Retrieves the CXXRecordDecl that this type refers to, either + /// because the type is a RecordType or because it is the injected-class-name + /// type of a class template or class template partial specialization. + CXXRecordDecl *getAsCXXRecordDecl() const; + // Member-template getAs<specific type>'. This scheme will eventually // replace the specific getAsXXXX methods above. // @@ -2433,8 +2439,11 @@ public: class TemplateSpecializationType : public Type, public llvm::FoldingSetNode { - // FIXME: Currently needed for profiling expressions; can we avoid this? - ASTContext &Context; + // The ASTContext is currently needed in order to profile expressions. + // FIXME: avoid this. + // + // The bool is whether this is a current instantiation. + llvm::PointerIntPair<ASTContext*, 1, bool> ContextAndCurrentInstantiation; /// \brief The name of the template being specialized. TemplateName Template; @@ -2445,6 +2454,7 @@ class TemplateSpecializationType TemplateSpecializationType(ASTContext &Context, TemplateName T, + bool IsCurrentInstantiation, const TemplateArgument *Args, unsigned NumArgs, QualType Canon); @@ -2476,6 +2486,12 @@ public: static std::string PrintTemplateArgumentList(const TemplateArgumentListInfo &, const PrintingPolicy &Policy); + /// True if this template specialization type matches a current + /// instantiation in the context in which it is found. + bool isCurrentInstantiation() const { + return ContextAndCurrentInstantiation.getInt(); + } + typedef const TemplateArgument * iterator; iterator begin() const { return getArgs(); } @@ -2496,15 +2512,20 @@ public: /// \precondition @c isArgType(Arg) const TemplateArgument &getArg(unsigned Idx) const; - bool isSugared() const { return !isDependentType(); } + bool isSugared() const { + return !isDependentType() || isCurrentInstantiation(); + } QualType desugar() const { return getCanonicalTypeInternal(); } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, Template, getArgs(), NumArgs, Context); + Profile(ID, Template, isCurrentInstantiation(), getArgs(), NumArgs, + *ContextAndCurrentInstantiation.getPointer()); } static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T, - const TemplateArgument *Args, unsigned NumArgs, + bool IsCurrentInstantiation, + const TemplateArgument *Args, + unsigned NumArgs, ASTContext &Context); static bool classof(const Type *T) { @@ -2513,40 +2534,57 @@ public: static bool classof(const TemplateSpecializationType *T) { return true; } }; -/// \brief The injected class name of a C++ class template. Used to -/// record that a type was spelled with a bare identifier rather than -/// as a template-id; the equivalent for non-templated classes is just -/// RecordType. +/// \brief The injected class name of a C++ class template or class +/// template partial specialization. Used to record that a type was +/// spelled with a bare identifier rather than as a template-id; the +/// equivalent for non-templated classes is just RecordType. /// -/// For consistency, template instantiation turns these into RecordTypes. +/// Injected class name types are always dependent. Template +/// instantiation turns these into RecordTypes. /// -/// The desugared form is always a unqualified TemplateSpecializationType. -/// The canonical form is always either a TemplateSpecializationType -/// (when dependent) or a RecordType (otherwise). +/// Injected class name types are always canonical. This works +/// because it is impossible to compare an injected class name type +/// with the corresponding non-injected template type, for the same +/// reason that it is impossible to directly compare template +/// parameters from different dependent contexts: injected class name +/// types can only occur within the scope of a particular templated +/// declaration, and within that scope every template specialization +/// will canonicalize to the injected class name (when appropriate +/// according to the rules of the language). class InjectedClassNameType : public Type { CXXRecordDecl *Decl; - QualType UnderlyingType; + /// The template specialization which this type represents. + /// For example, in + /// template <class T> class A { ... }; + /// this is A<T>, whereas in + /// template <class X, class Y> class A<B<X,Y> > { ... }; + /// this is A<B<X,Y> >. + /// + /// It is always unqualified, always a template specialization type, + /// and always dependent. + QualType InjectedType; friend class ASTContext; // ASTContext creates these. - InjectedClassNameType(CXXRecordDecl *D, QualType TST, QualType Canon) - : Type(InjectedClassName, Canon, Canon->isDependentType()), - Decl(D), UnderlyingType(TST) { + friend class TagDecl; // TagDecl mutilates the Decl + InjectedClassNameType(CXXRecordDecl *D, QualType TST) + : Type(InjectedClassName, QualType(), true), + Decl(D), InjectedType(TST) { assert(isa<TemplateSpecializationType>(TST)); assert(!TST.hasQualifiers()); - assert(TST->getCanonicalTypeInternal() == Canon); + assert(TST->isDependentType()); } public: - QualType getUnderlyingType() const { return UnderlyingType; } - const TemplateSpecializationType *getUnderlyingTST() const { - return cast<TemplateSpecializationType>(UnderlyingType.getTypePtr()); + QualType getInjectedSpecializationType() const { return InjectedType; } + const TemplateSpecializationType *getInjectedTST() const { + return cast<TemplateSpecializationType>(InjectedType.getTypePtr()); } CXXRecordDecl *getDecl() const { return Decl; } - bool isSugared() const { return true; } - QualType desugar() const { return UnderlyingType; } + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } static bool classof(const Type *T) { return T->getTypeClass() == InjectedClassName; diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 7e8b73c..c665073 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -91,7 +91,7 @@ DEPENDENT_TYPE(TemplateTypeParm, Type) NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type) NON_CANONICAL_TYPE(QualifiedName, Type) -NON_CANONICAL_TYPE(InjectedClassName, Type) +DEPENDENT_TYPE(InjectedClassName, Type) DEPENDENT_TYPE(DependentName, Type) TYPE(ObjCInterface, Type) TYPE(ObjCObjectPointer, Type) @@ -105,6 +105,8 @@ LAST_TYPE(ObjCObjectPointer) #ifdef LEAF_TYPE LEAF_TYPE(Enum) LEAF_TYPE(Builtin) +LEAF_TYPE(Record) +LEAF_TYPE(InjectedClassName) LEAF_TYPE(ObjCInterface) LEAF_TYPE(TemplateTypeParm) #undef LEAF_TYPE diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h index 553f04d..cad7e61 100644 --- a/include/clang/AST/UnresolvedSet.h +++ b/include/clang/AST/UnresolvedSet.h @@ -17,56 +17,7 @@ #include <iterator> #include "llvm/ADT/SmallVector.h" -#include "clang/Basic/Specifiers.h" - -namespace clang { - -class NamedDecl; - -/// A POD class for pairing a NamedDecl* with an access specifier. -/// Can be put into unions. -class DeclAccessPair { - NamedDecl *Ptr; // we'd use llvm::PointerUnion, but it isn't trivial - - enum { Mask = 0x3 }; - -public: - static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS) { - DeclAccessPair p; - p.set(D, AS); - return p; - } - - NamedDecl *getDecl() const { - return (NamedDecl*) (~Mask & (uintptr_t) Ptr); - } - AccessSpecifier getAccess() const { - return AccessSpecifier(Mask & (uintptr_t) Ptr); - } - - void setDecl(NamedDecl *D) { - set(D, getAccess()); - } - void setAccess(AccessSpecifier AS) { - set(getDecl(), AS); - } - void set(NamedDecl *D, AccessSpecifier AS) { - Ptr = reinterpret_cast<NamedDecl*>(uintptr_t(AS) | - reinterpret_cast<uintptr_t>(D)); - } - - operator NamedDecl*() const { return getDecl(); } - NamedDecl *operator->() const { return getDecl(); } -}; -} - -// Take a moment to tell SmallVector that this is POD. -namespace llvm { -template<typename> struct isPodLike; -template<> struct isPodLike<clang::DeclAccessPair> { - static const bool value = true; -}; -} +#include "clang/AST/DeclAccessPair.h" namespace clang { diff --git a/include/clang/AST/UsuallyTinyPtrVector.h b/include/clang/AST/UsuallyTinyPtrVector.h new file mode 100644 index 0000000..5ee40e0 --- /dev/null +++ b/include/clang/AST/UsuallyTinyPtrVector.h @@ -0,0 +1,105 @@ +//===-- UsuallyTinyPtrVector.h - Pointer vector 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 UsuallyTinyPtrVector class, which is a vector that +// optimizes the case where there is only one element. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_USUALLY_TINY_PTR_VECTOR_H +#define LLVM_CLANG_AST_USUALLY_TINY_PTR_VECTOR_H + +#include <vector> + +namespace clang { + +/// \brief A vector class template that is optimized for storing a single +/// pointer element. +template<typename T> +class UsuallyTinyPtrVector { + /// \brief Storage for the vector. + /// + /// When the low bit is zero, this is a T *. When the + /// low bit is one, this is a std::vector<T *> *. + mutable uintptr_t Storage; + + typedef std::vector<T*> vector_type; + +public: + UsuallyTinyPtrVector() : Storage(0) { } + explicit UsuallyTinyPtrVector(T *Element) + : Storage(reinterpret_cast<uintptr_t>(Element)) { } + + bool empty() const { return !Storage; } + + typedef const T **iterator; + iterator begin() const; + iterator end() const; + + void push_back(T *Method); + void Destroy(); +}; + +template<typename T> +typename UsuallyTinyPtrVector<T>::iterator +UsuallyTinyPtrVector<T>::begin() const { + if ((Storage & 0x01) == 0) + return reinterpret_cast<iterator>(&Storage); + + vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01); + return &Vec->front(); +} + + +template<typename T> +typename UsuallyTinyPtrVector<T>::iterator +UsuallyTinyPtrVector<T>::end() const { + if ((Storage & 0x01) == 0) { + if (Storage == 0) + return reinterpret_cast<iterator>(&Storage); + + return reinterpret_cast<iterator>(&Storage) + 1; + } + + vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01); + return &Vec->front() + Vec->size(); +} + +template<typename T> +void UsuallyTinyPtrVector<T>::push_back(T *Element) { + if (Storage == 0) { + // 0 -> 1 element. + Storage = reinterpret_cast<uintptr_t>(Element); + return; + } + + vector_type *Vec; + if ((Storage & 0x01) == 0) { + // 1 -> 2 elements. Allocate a new vector and push the element into that + // vector. + Vec = new vector_type; + Vec->push_back(reinterpret_cast<T *>(Storage)); + Storage = reinterpret_cast<uintptr_t>(Vec) | 0x01; + } else + Vec = reinterpret_cast<vector_type *>(Storage & ~0x01); + + // Add the new element to the vector. + Vec->push_back(Element); +} + +template<typename T> +void UsuallyTinyPtrVector<T>::Destroy() { + if (Storage & 0x01) + delete reinterpret_cast<vector_type *>(Storage & ~0x01); + + Storage = 0; +} + +} +#endif diff --git a/include/clang/Analysis/Support/Optional.h b/include/clang/Analysis/Support/Optional.h deleted file mode 100644 index a4e6d51..0000000 --- a/include/clang/Analysis/Support/Optional.h +++ /dev/null @@ -1,66 +0,0 @@ -//===-- Optional.h - Simple variant for passing optional values ---*- C++ -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides Optional, a template class modeled in the spirit of -// OCaml's 'opt' variant. The idea is to strongly type whether or not -// a value can be optional. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_ANALYSIS_OPTIONAL -#define LLVM_CLANG_ANALYSIS_OPTIONAL - -namespace clang { - -template<typename T> -class Optional { - T x; - unsigned hasVal : 1; -public: - explicit Optional() : x(), hasVal(false) {} - Optional(const T &y) : x(y), hasVal(true) {} - - static inline Optional create(const T* y) { - return y ? Optional(*y) : Optional(); - } - - Optional &operator=(const T &y) { - x = y; - hasVal = true; - return *this; - } - - const T* getPointer() const { assert(hasVal); return &x; } - const T& getValue() const { assert(hasVal); return x; } - - operator bool() const { return hasVal; } - bool hasValue() const { return hasVal; } - const T* operator->() const { return getPointer(); } - const T& operator*() const { assert(hasVal); return x; } -}; -} //end clang namespace - -namespace llvm { - -template<typename T> struct simplify_type; - -template <typename T> -struct simplify_type<const ::clang::Optional<T> > { - typedef const T* SimpleType; - static SimpleType getSimplifiedValue(const ::clang::Optional<T> &Val) { - return Val.getPointer(); - } -}; - -template <typename T> -struct simplify_type< ::clang::Optional<T> > - : public simplify_type<const ::clang::Optional<T> > {}; -} // end llvm namespace - -#endif diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 453f660..b306954 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -314,6 +314,7 @@ BUILTIN(__builtin_setjmp, "iv**", "") BUILTIN(__builtin_longjmp, "vv**i", "r") BUILTIN(__builtin_unwind_init, "v", "") BUILTIN(__builtin_eh_return_data_regno, "ii", "nc") +BUILTIN(__builtin_vsprintf, "ic*cC*a", "nFP:1:") BUILTIN(__builtin_vsnprintf, "ic*zcC*a", "nFP:2:") // GCC exception builtins @@ -335,6 +336,7 @@ BUILTIN(__builtin___strcat_chk, "c*c*cC*z", "nF") BUILTIN(__builtin___strcpy_chk, "c*c*cC*z", "nF") BUILTIN(__builtin___strncat_chk, "c*c*cC*zz", "nF") BUILTIN(__builtin___strncpy_chk, "c*c*cC*zz", "nF") +BUILTIN(__builtin___stpncpy_chk, "c*c*cC*zz", "nF") BUILTIN(__builtin___snprintf_chk, "ic*zizcC*.", "Fp:4:") BUILTIN(__builtin___sprintf_chk, "ic*izcC*.", "Fp:3:") BUILTIN(__builtin___vsnprintf_chk, "ic*zizcC*a", "FP:4:") @@ -346,12 +348,9 @@ BUILTIN(__builtin___vprintf_chk, "iicC*a", "FP:1:") BUILTIN(__builtin_expect, "LiLiLi" , "nc") BUILTIN(__builtin_prefetch, "vvC*.", "nc") -BUILTIN(__builtin_abort, "v", "Fnr") BUILTIN(__builtin_trap, "v", "nr") BUILTIN(__builtin_unreachable, "v", "nr") - BUILTIN(__builtin_shufflevector, "v." , "nc") - BUILTIN(__builtin_alloca, "v*z" , "n") // "Overloaded" Atomic operator builtins. These are overloaded to support data @@ -473,6 +472,13 @@ BUILTIN(__sync_fetch_and_max, "ii*i", "n") BUILTIN(__sync_fetch_and_umin, "UiUi*Ui", "n") BUILTIN(__sync_fetch_and_umax, "UiUi*Ui", "n") +// Random libc builtins. +BUILTIN(__builtin_abort, "v", "Fnr") +BUILTIN(__builtin_index, "c*cC*i", "Fn") +BUILTIN(__builtin_rindex, "c*cC*i", "Fn") + + + // C99 library functions // C99 stdlib.h LIBBUILTIN(abort, "v", "fr", "stdlib.h") diff --git a/include/clang/Basic/BuiltinsPPC.def b/include/clang/Basic/BuiltinsPPC.def index 817a032..287bba9 100644 --- a/include/clang/Basic/BuiltinsPPC.def +++ b/include/clang/Basic/BuiltinsPPC.def @@ -18,7 +18,97 @@ // The format of this database matches clang/Basic/Builtins.def. // This is just a placeholder, the types and attributes are wrong. -BUILTIN(__builtin_altivec_abs_v4sf , "ii" , "nc") +BUILTIN(__builtin_altivec_abs_v16qi, "V16UcV16Sc", "") +BUILTIN(__builtin_altivec_abs_v8hi, "V8UsV8Ss", "") +BUILTIN(__builtin_altivec_abs_v4si, "V4UiV4Si", "") + +BUILTIN(__builtin_altivec_abss_v16qi, "V16UcV16Sc", "") +BUILTIN(__builtin_altivec_abss_v8hi, "V8UsV8Ss", "") +BUILTIN(__builtin_altivec_abss_v4si, "V4UiV4Si", "") + +BUILTIN(__builtin_altivec_vaddcuw, "V4UiV4UiV4Ui", "") + +BUILTIN(__builtin_altivec_vaddsbs, "V16ScV16ScV16Sc", "") +BUILTIN(__builtin_altivec_vaddubs, "V16UcV16UcV16Uc", "") +BUILTIN(__builtin_altivec_vaddshs, "V8SsV8SsV8Ss", "") +BUILTIN(__builtin_altivec_vadduhs, "V8UsV8UsV8Us", "") +BUILTIN(__builtin_altivec_vaddsws, "V4SiV4SiV4Si", "") +BUILTIN(__builtin_altivec_vadduws, "V4UiV4UiV4Ui", "") + +BUILTIN(__builtin_altivec_vsubsbs, "V16ScV16ScV16Sc", "") +BUILTIN(__builtin_altivec_vsububs, "V16UcV16UcV16Uc", "") +BUILTIN(__builtin_altivec_vsubshs, "V8SsV8SsV8Ss", "") +BUILTIN(__builtin_altivec_vsubuhs, "V8UsV8UsV8Us", "") +BUILTIN(__builtin_altivec_vsubsws, "V4SiV4SiV4Si", "") +BUILTIN(__builtin_altivec_vsubuws, "V4UiV4UiV4Ui", "") + +BUILTIN(__builtin_altivec_vavgsb, "V16ScV16ScV16Sc", "") +BUILTIN(__builtin_altivec_vavgub, "V16UcV16UcV16Uc", "") +BUILTIN(__builtin_altivec_vavgsh, "V8SsV8SsV8Ss", "") +BUILTIN(__builtin_altivec_vavguh, "V8UsV8UsV8Us", "") +BUILTIN(__builtin_altivec_vavgsw, "V4SiV4SiV4Si", "") +BUILTIN(__builtin_altivec_vavguw, "V4UiV4UiV4Ui", "") + +BUILTIN(__builtin_altivec_stvx, "vV4iiv*", "") +BUILTIN(__builtin_altivec_stvxl, "vV4iiv*", "") +BUILTIN(__builtin_altivec_stvebx, "vV16civ*", "") +BUILTIN(__builtin_altivec_stvehx, "vV8siv*", "") +BUILTIN(__builtin_altivec_stvewx, "vV4iiv*", "") + +BUILTIN(__builtin_altivec_vcmpbfp, "V4iV4fV4f", "") + +BUILTIN(__builtin_altivec_vcmpgefp, "V4iV4fV4f", "") + +BUILTIN(__builtin_altivec_vcmpequb, "V16cV16cV16c", "") +BUILTIN(__builtin_altivec_vcmpequh, "V8sV8sV8s", "") +BUILTIN(__builtin_altivec_vcmpequw, "V4iV4iV4i", "") +BUILTIN(__builtin_altivec_vcmpeqfp, "V4iV4fV4f", "") + +BUILTIN(__builtin_altivec_vcmpgtsb, "V16cV16ScV16Sc", "") +BUILTIN(__builtin_altivec_vcmpgtub, "V16cV16UcV16Uc", "") +BUILTIN(__builtin_altivec_vcmpgtsh, "V8sV8SsV8Ss", "") +BUILTIN(__builtin_altivec_vcmpgtuh, "V8sV8UsV8Us", "") +BUILTIN(__builtin_altivec_vcmpgtsw, "V4iV4SiV4Si", "") +BUILTIN(__builtin_altivec_vcmpgtuw, "V4iV4UiV4Ui", "") +BUILTIN(__builtin_altivec_vcmpgtfp, "V4iV4fV4f", "") + +BUILTIN(__builtin_altivec_vmaxsb, "V16ScV16ScV16Sc", "") +BUILTIN(__builtin_altivec_vmaxub, "V16UcV16UcV16Uc", "") +BUILTIN(__builtin_altivec_vmaxsh, "V8SsV8SsV8Ss", "") +BUILTIN(__builtin_altivec_vmaxuh, "V8UsV8UsV8Us", "") +BUILTIN(__builtin_altivec_vmaxsw, "V4SiV4SiV4Si", "") +BUILTIN(__builtin_altivec_vmaxuw, "V4UiV4UiV4Ui", "") +BUILTIN(__builtin_altivec_vmaxfp, "V4fV4fV4f", "") + +BUILTIN(__builtin_altivec_mfvscr, "V8Us", "") + +BUILTIN(__builtin_altivec_vminsb, "V16ScV16ScV16Sc", "") +BUILTIN(__builtin_altivec_vminub, "V16UcV16UcV16Uc", "") +BUILTIN(__builtin_altivec_vminsh, "V8SsV8SsV8Ss", "") +BUILTIN(__builtin_altivec_vminuh, "V8UsV8UsV8Us", "") +BUILTIN(__builtin_altivec_vminsw, "V4SiV4SiV4Si", "") +BUILTIN(__builtin_altivec_vminuw, "V4UiV4UiV4Ui", "") +BUILTIN(__builtin_altivec_vminfp, "V4fV4fV4f", "") + +BUILTIN(__builtin_altivec_mtvscr, "vV4i", "") + +BUILTIN(__builtin_altivec_vcmpbfp_p, "iiV4fV4f", "") + +BUILTIN(__builtin_altivec_vcmpgefp_p, "iiV4fV4f", "") + +BUILTIN(__builtin_altivec_vcmpequb_p, "iiV16cV16c", "") +BUILTIN(__builtin_altivec_vcmpequh_p, "iiV8sV8s", "") +BUILTIN(__builtin_altivec_vcmpequw_p, "iiV4iV4i", "") +BUILTIN(__builtin_altivec_vcmpeqfp_p, "iiV4fV4f", "") + +BUILTIN(__builtin_altivec_vcmpgtsb_p, "iiV16ScV16Sc", "") +BUILTIN(__builtin_altivec_vcmpgtub_p, "iiV16UcV16Uc", "") +BUILTIN(__builtin_altivec_vcmpgtsh_p, "iiV8SsV8Ss", "") +BUILTIN(__builtin_altivec_vcmpgtuh_p, "iiV8UsV8Us", "") +BUILTIN(__builtin_altivec_vcmpgtsw_p, "iiV4SiV4Si", "") +BUILTIN(__builtin_altivec_vcmpgtuw_p, "iiV4UiV4Ui", "") +BUILTIN(__builtin_altivec_vcmpgtfp_p, "iiV4fV4f", "") + // FIXME: Obviously incomplete. #undef BUILTIN diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 5c75d37..a878dd1 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -245,7 +245,7 @@ BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "") BUILTIN(__builtin_ia32_mwait, "vUiUi", "") BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "") BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cc", "") -BUILTIN(__builtin_ia32_palignr, "V1LLiV1LLiV1LLic", "") +BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cc", "") BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "") BUILTIN(__builtin_ia32_storelv4si, "vV2i*V2LLi", "") diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 57dd696..bf94af6 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -188,6 +188,9 @@ private: bool ErrorsAsFatal; // Treat errors like fatal errors. bool SuppressSystemWarnings; // Suppress warnings in system headers. bool SuppressAllDiagnostics; // Suppress all diagnostics. + unsigned ErrorLimit; // Cap of # errors emitted, 0 -> no limit. + unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack, + // 0 -> no limit. ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors? DiagnosticClient *Client; @@ -211,9 +214,10 @@ private: /// diagnostic that they follow. Diagnostic::Level LastDiagLevel; - unsigned NumDiagnostics; // Number of diagnostics reported - unsigned NumErrors; // Number of diagnostics that are errors - + unsigned NumWarnings; // Number of warnings reported + unsigned NumErrors; // Number of errors reported + unsigned NumErrorsSuppressed; // Number of errors suppressed + /// CustomDiagInfo - Information for uniquing and looking up custom diags. diag::CustomDiagInfo *CustomDiagInfo; @@ -270,6 +274,22 @@ public: void setClient(DiagnosticClient* client) { Client = client; } + /// setErrorLimit - Specify a limit for the number of errors we should + /// emit before giving up. Zero disables the limit. + void setErrorLimit(unsigned Limit) { ErrorLimit = Limit; } + + /// \brief Specify the maximum number of template instantiation + /// notes to emit along with a given diagnostic. + void setTemplateBacktraceLimit(unsigned Limit) { + TemplateBacktraceLimit = Limit; + } + + /// \brief Retrieve the maximum number of template instantiation + /// nodes to emit along with a given diagnostic. + unsigned getTemplateBacktraceLimit() const { + return TemplateBacktraceLimit; + } + /// setIgnoreAllWarnings - When set to true, any unmapped warnings are /// ignored. If this and WarningsAsErrors are both set, then this one wins. void setIgnoreAllWarnings(bool Val) { IgnoreAllWarnings = Val; } @@ -324,8 +344,9 @@ public: void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map) { assert(Diag < diag::DIAG_UPPER_LIMIT && "Can only map builtin diagnostics"); - assert((isBuiltinWarningOrExtension(Diag) || Map == diag::MAP_FATAL) && - "Cannot map errors!"); + assert((isBuiltinWarningOrExtension(Diag) || + (Map == diag::MAP_FATAL || Map == diag::MAP_ERROR)) && + "Cannot map errors into warnings!"); setDiagnosticMappingInternal(Diag, Map, true); } @@ -338,7 +359,8 @@ public: bool hasFatalErrorOccurred() const { return FatalErrorOccurred; } unsigned getNumErrors() const { return NumErrors; } - unsigned getNumDiagnostics() const { return NumDiagnostics; } + unsigned getNumErrorsSuppressed() const { return NumErrorsSuppressed; } + unsigned getNumWarnings() const { return NumWarnings; } /// getCustomDiagID - Return an ID for a diagnostic with the specified message /// and level. If this is the first request for this diagnosic, it is @@ -383,7 +405,18 @@ public: /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic /// ID is for an extension of some sort. /// - static bool isBuiltinExtensionDiag(unsigned DiagID); + static bool isBuiltinExtensionDiag(unsigned DiagID) { + bool ignored; + return isBuiltinExtensionDiag(DiagID, ignored); + } + + /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic + /// ID is for an extension of some sort. This also returns EnabledByDefault, + /// which is set to indicate whether the diagnostic is ignored by default (in + /// which case -pedantic enables it) or treated as a warning/error by default. + /// + static bool isBuiltinExtensionDiag(unsigned DiagID, bool &EnabledByDefault); + /// getWarningOptionForDiag - Return the lowest-level warning option that /// enables the specified diagnostic. If there is no -Wfoo flag that controls @@ -473,7 +506,7 @@ private: /// getDiagnosticMappingInfo - Return the mapping info currently set for the /// specified builtin diagnostic. This returns the high bit encoding, or zero /// if the field is completely uninitialized. - unsigned getDiagnosticMappingInfo(diag::kind Diag) const { + diag::Mapping getDiagnosticMappingInfo(diag::kind Diag) const { const DiagMappings ¤tMappings = DiagMappingsStack.back(); return (diag::Mapping)((currentMappings[Diag/2] >> (Diag & 1)*4) & 15); } diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index 8e791c3..88e7dc1 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -13,6 +13,11 @@ let Component = "Common" in { +// Basic. + +def fatal_too_many_errors + : Error<"too many errors emitted, stopping now">, DefaultFatal; + def note_previous_definition : Note<"previous definition is here">; def note_previous_declaration : Note<"previous declaration is here">; def note_previous_implicit_declaration : Note< @@ -36,7 +41,7 @@ def err_expected_colon_after_setter_name : Error< "must end with ':'">; // Parse && Sema -def err_no_declarators : Error<"declaration does not declare anything">; +def ext_no_declarators : ExtWarn<"declaration does not declare anything">; def err_param_redefinition : Error<"redefinition of parameter %0">; def err_invalid_storage_class_in_func_decl : Error< "invalid storage class specifier in function declarator">; @@ -67,5 +72,6 @@ def err_target_invalid_feature : Error<"invalid target feature '%0'">; def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal; def err_file_modified : Error< "file '%0' modified since it was first processed">, DefaultFatal; - +def err_unsupported_bom : Error<"%0 byte order mark detected in '%1', but " + "encoding is not supported">, DefaultFatal; } diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index 3dbe47f..3b7272e 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -94,5 +94,7 @@ def warn_drv_conflicting_deployment_targets : Warning< def warn_drv_treating_input_as_cxx : Warning< "treating '%0' input as '%1' when in C++ mode, this behavior is deprecated">, InGroup<Deprecated>; +def warn_drv_objc_gc_unsupported : Warning< + "Objective-C garbage collection is not supported on this platform, ignoring '%0'">; } diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 2e0b4ba..b731030 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -14,7 +14,10 @@ def err_fe_error_reading : Error<"error reading '%0'">; def err_fe_error_reading_stdin : Error<"error reading stdin">; def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal; def err_fe_invalid_ast_file : Error<"invalid AST file: '%0'">, DefaultFatal; -def err_fe_invalid_ast_action : Error<"invalid action for AST input">, DefaultFatal; +def err_fe_invalid_ast_action : Error<"invalid action for AST input">, + DefaultFatal; +def err_fe_inline_asm : Error<"%0">; // Error generated by the backend. +def note_fe_inline_asm_here : Note<"generated from here">; def err_fe_invalid_code_complete_file : Error< "cannot locate code-completion file %0">, DefaultFatal; def err_fe_stdout_binary : Error<"unable to change standard output to binary">, @@ -69,12 +72,12 @@ def err_fe_pth_file_has_no_source_header : Error< def warn_fe_macro_contains_embedded_newline : Warning< "macro '%0' contains embedded newline, text after the newline is ignored.">; -def err_verify_bogus_characters : Error< - "bogus characters before '{{' in expected string">; def err_verify_missing_start : Error< - "cannot find start ('{{') of expected string">; + "cannot find start ('{{') of expected %0">; def err_verify_missing_end : Error< - "cannot find end ('}}') of expected string">; + "cannot find end ('}}') of expected %0">; +def err_verify_invalid_content : Error< + "invalid expected %0: %1">; def err_verify_inconsistent_diags : Error< "'%0' diagnostics %select{expected|seen}1 but not %select{seen|expected}1: %2">; @@ -120,12 +123,18 @@ def warn_pch_nonfragile_abi2 : Error< "PCH file was compiled with the %select{32-bit|enhanced non-fragile}0 " "Objective-C ABI but the %select{32-bit|enhanced non-fragile}1 " "Objective-C ABI is selected">; +def warn_pch_no_constant_cfstrings : Error< + "Objctive-C NSstring generation support was %select{disabled|enabled}0 " + "in PCH file but currently %select{disabled|enabled}1">; def warn_pch_extensions : Error< "extensions were %select{enabled|disabled}0 in PCH file but are " "currently %select{enabled|disabled}1">; def warn_pch_gnu_extensions : Error< "GNU extensions were %select{disabled|enabled}0 in PCH file but are " "currently %select{disabled|enabled}1">; +def warn_pch_gnu_keywords : Error< + "GNU keywords were %select{disabled|enabled}0 in PCH file but are " + "currently %select{disabled|enabled}1">; def warn_pch_microsoft_extensions : Error< "Microsoft extensions were %select{disabled|enabled}0 in PCH file but are " "currently %select{disabled|enabled}1">; diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index b0c016b..c74a48c 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -108,6 +108,7 @@ def : DiagGroup<"type-limits">; def Uninitialized : DiagGroup<"uninitialized">; def UnknownPragmas : DiagGroup<"unknown-pragmas">; def UnusedArgument : DiagGroup<"unused-argument">; +def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">; def UnusedFunction : DiagGroup<"unused-function">; def UnusedLabel : DiagGroup<"unused-label">; def UnusedParameter : DiagGroup<"unused-parameter">; @@ -138,7 +139,8 @@ def Conversion : DiagGroup<"conversion", def Unused : DiagGroup<"unused", [UnusedArgument, UnusedFunction, UnusedLabel, - UnusedParameter, UnusedValue, UnusedVariable]>; + // UnusedParameter, (matches GCC's behavior) + UnusedValue, UnusedVariable]>; // Format settings. def Format : DiagGroup<"format", [FormatExtraArgs, FormatZeroLength, NonNull]>; @@ -156,23 +158,22 @@ def Extra : DiagGroup<"extra", [ ]>; def Most : DiagGroup<"most", [ + CharSubscript, Comment, Format, Implicit, MismatchedTags, MissingBraces, MultiChar, + Reorder, ReturnType, Switch, Trigraphs, Uninitialized, UnknownPragmas, - UnusedValue, - UnusedVariable, + Unused, VectorConversions, - VolatileRegisterVar, - Reorder, - CharSubscript + VolatileRegisterVar ]>; // -Wall is -Wmost -Wparentheses diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 3e0956f..2795851 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -190,7 +190,9 @@ def err_objc_missing_end : Error<"missing @end">; def warn_objc_protocol_qualifier_missing_id : Warning< "protocol qualifiers without 'id' is archaic">; def err_objc_unknown_at : Error<"expected an Objective-C directive after '@'">; - +def err_illegal_super_cast : Error< + "cannot cast 'super' (it isn't an expression)">; + def err_objc_illegal_visibility_spec : Error< "illegal visibility specification">; def err_objc_illegal_interface_qual : Error<"illegal interface qualifier">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index b66d6cc..93ab858 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -85,6 +85,8 @@ def warn_unused_parameter : Warning<"unused parameter %0">, InGroup<UnusedParameter>, DefaultIgnore; def warn_unused_variable : Warning<"unused variable %0">, InGroup<UnusedVariable>, DefaultIgnore; +def warn_unused_exception_param : Warning<"unused exception parameter %0">, + InGroup<UnusedExceptionParameter>, DefaultIgnore; def warn_decl_in_param_list : Warning< "declaration of %0 will not be visible outside of this function">; def err_array_star_in_function_definition : Error< @@ -215,7 +217,8 @@ def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">; def err_statically_allocated_object : Error< "interface type cannot be statically allocated">; def err_object_cannot_be_passed_returned_by_value : Error< - "interface type %1 cannot be %select{returned|passed}0 by value">; + "interface type %1 cannot be %select{returned|passed}0 by value" + "; did you forget * in %1">; def warn_enum_value_overflow : Warning<"overflow in enumeration value">; def warn_pragma_pack_invalid_alignment : Warning< "expected #pragma pack parameter to be '1', '2', '4', '8', or '16'">; @@ -237,6 +240,8 @@ def err_duplicate_class_def : Error< "duplicate interface definition for class %0">; def err_undef_superclass : Error< "cannot find interface declaration for %0, superclass of %1">; +def err_no_nsconstant_string_class : Error< + "cannot find interface declaration for %0">; def err_recursive_superclass : Error< "trying to recursively use %0 as superclass of %1">; def warn_previous_alias_decl : Warning<"previously declared alias is ignored">; @@ -296,7 +301,7 @@ def warn_implements_nscopying : Warning< def warn_multiple_method_decl : Warning<"multiple methods named %0 found">; def warn_accessor_property_type_mismatch : Warning< "type of property %0 does not match type of accessor %1">; -def note_declared_at : Note<"declared at">; +def note_declared_at : Note<"declared here">; def err_setter_type_void : Error<"type of setter must be void">; def err_duplicate_method_decl : Error<"duplicate declaration of method %0">; def warn_missing_atend : Warning<"'@end' is missing in implementation context">; @@ -322,8 +327,8 @@ def warn_atomic_property_rule : Warning< "writable atomic property %0 cannot pair a synthesized setter/getter " "with a user defined setter/getter">; def err_use_continuation_class : Error< - "property declaration in continuation class of %0 is to change a 'readonly' " - "property to 'readwrite'">; + "illegal declaration of property in continuation class %0" + ": attribute must be readwrite, while its primary must be readonly">; def err_continuation_class : Error<"continuation class has no primary class">; def err_property_type : Error<"property cannot have array or function type %0">; def error_missing_property_context : Error< @@ -381,11 +386,13 @@ def err_static_assert_failed : Error<"static_assert failed \"%0\"">; def err_unexpected_friend : Error< "friends can only be classes or functions">; -def err_enum_friend : Error< - "enum types cannot be friends">; +def ext_enum_friend : ExtWarn< + "enumeration type %0 cannot be a friend">; +def ext_nonclass_type_friend : ExtWarn< + "non-class type %0 cannot be a friend">; def err_friend_is_member : Error< "friends cannot be members of the declaring class">; -def err_unelaborated_friend_type : Error< +def ext_unelaborated_friend_type : ExtWarn< "must specify '%select{struct|union|class|enum}0' to befriend %1">; def err_qualified_friend_not_found : Error< "no function named %0 with type %1 was found in the specified scope">; @@ -399,6 +406,9 @@ def err_abstract_type_in_decl : Error< "%select{return|parameter|variable|field}0 type %1 is an abstract class">; def err_allocation_of_abstract_type : Error< "allocation of an object of abstract type %0">; +def err_throw_abstract_type : Error< + "cannot throw an object of abstract type %0">; +def err_array_of_abstract_type : Error<"array of abstract class type %0">; def err_multiple_final_overriders : Error< "virtual function %q0 has more than one final overrider in %1">; @@ -448,11 +458,20 @@ def warn_missing_exception_specification : Warning< // C++ access checking def err_class_redeclared_with_different_access : Error< "%0 redeclared with '%1' access">; -def err_access : - Error<"%1 is a %select{private|protected}0 member of %3">, - NoSFINAE; -def err_access_ctor : - Error<"calling a %select{private|protected}0 constructor of class %2">, +def err_access : Error< + "%1 is a %select{private|protected}0 member of %3">, NoSFINAE; +def err_access_ctor : Error< + "calling a %select{private|protected}0 constructor of class %2">, NoSFINAE; +def err_access_base : Error< + "%select{base class|inherited virtual base class}0 %1 has %select{private|" + "protected}3 %select{constructor|copy constructor|copy assignment operator|" + "destructor}2">, NoSFINAE; +def err_access_field: Error< + "field of type %0 has %select{private|protected}2 %select{constructor|copy " + "constructor|copy assignment operator|destructor}1">, NoSFINAE; + +def err_access_ctor_field : + Error<"field of type %1 has %select{private|protected}2 constructor">, NoSFINAE; def err_access_dtor_base : Error<"base class %0 has %select{private|protected}1 destructor">, @@ -461,6 +480,9 @@ def err_access_dtor_vbase : Error<"inherited virtual base class %0 has " "%select{private|protected}1 destructor">, NoSFINAE; +def err_access_dtor_temp : + Error<"temporary of type %0 has %select{private|protected}1 destructor">, + NoSFINAE; def err_access_dtor_field : Error<"field of type %1 has %select{private|protected}2 destructor">, NoSFINAE; @@ -494,6 +516,9 @@ def note_access_constrained_by_path : Note< // C++ name lookup def err_incomplete_nested_name_spec : Error< "incomplete type %0 named in nested name specifier">; +def err_dependent_nested_name_spec : Error< + "nested name specifier for a declaration cannot depend on a template " + "parameter">; def err_nested_name_member_ref_lookup_ambiguous : Error< "lookup of %0 in member access expression is ambiguous">; def note_ambig_member_ref_object_type : Note< @@ -542,6 +567,8 @@ def err_non_virtual_pure : Error< def err_implicit_object_parameter_init : Error< "cannot initialize object parameter of type %0 with an expression " "of type %1">; +def err_qualified_member_of_unrelated : Error< + "%q0 is not a member of class %1">; def note_field_decl : Note<"member is declared here">; def note_ivar_decl : Note<"ivar is declared here">; @@ -592,6 +619,7 @@ def err_covariant_return_type_class_type_more_qualified : Error< "return type of virtual function %0 is not covariant with the return type of " "the function it overrides (class type %1 is more qualified than class " "type %2">; + // C++ constructors def err_constructor_cannot_be : Error<"constructor cannot be declared '%0'">; def err_invalid_qualified_constructor : Error< @@ -601,6 +629,11 @@ def err_constructor_return_type : Error< def err_constructor_redeclared : Error<"constructor cannot be redeclared">; def err_constructor_byvalue_arg : Error< "copy constructor must pass its first argument by reference">; +def warn_no_constructor_for_refconst : Warning< + "%select{struct|union|class|enum}0 %1 does not declare any constructor to " + "initialize its non-modifiable members">; +def note_refconst_member_not_initialized : Note< + "%select{const|reference}0 member %1 will never be initialized">; // C++ destructors def err_destructor_not_member : Error< @@ -678,18 +711,23 @@ 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|" + "no viable constructor %select{copying variable|copying parameter|" "returning object|throwing object|copying member subobject|copying array " - "element}0 of type %1">; + "element|allocating object|copying temporary|initializing base subobject|" + "initializing vector element}0 of type %1">; def err_temp_copy_ambiguous : Error< - "ambiguous copy constructor call when %select{copying variable|copying " + "ambiguous constructor call when %select{copying variable|copying " "parameter|returning object|throwing object|copying member subobject|copying " - "array element}0 of type %1">; + "array element|allocating object|copying temporary|initializing base subobject|" + "initializing vector element}0 of type %1">; def err_temp_copy_deleted : Error< "%select{copying variable|copying parameter|returning object|throwing " - "object|copying member subobject|copying array element}0 of type %1 invokes " - "deleted copy constructor">; - + "object|copying member subobject|copying array element|allocating object|" + "copying temporary|initializing base subobject|initializing vector element}0 " + "of type %1 invokes deleted constructor">; +def err_temp_copy_incomplete : Error< + "copying a temporary object of incomplete type %0">; + // C++0x decltype def err_cannot_determine_declared_type_of_overloaded_function : Error< "cannot determine the %select{type|declared type}0 of an overloaded " @@ -1116,9 +1154,13 @@ def err_member_call_without_object : Error< "call to non-static member function without an object argument">; // C++ Address of Overloaded Function +def err_addr_ovl_no_viable : Error< + "address of overloaded function %0 does not match required type %1">; def err_addr_ovl_ambiguous : Error< "address of overloaded function %0 is ambiguous">; - +def err_addr_ovl_not_func_ptrref : Error< + "address of overloaded function %0 cannot be converted to type %1">; + // C++ Template Declarations def err_template_param_shadow : Error< "declaration of %0 shadows template parameter">; @@ -1178,6 +1220,8 @@ def err_template_decl_ref : Error< "cannot refer to class template %0 without a template argument list">; // C++ Template Argument Lists +def err_template_missing_args : Error< + "use of class template %0 requires template arguments">; def err_template_arg_list_different_arity : Error< "%select{too few|too many}0 template arguments for " "%select{class template|function template|template template parameter" @@ -1231,9 +1275,6 @@ def err_template_arg_no_ref_bind : Error< def err_template_arg_ref_bind_ignores_quals : Error< "reference binding of non-type template parameter of type %0 to template " "argument of type %1 ignores qualifiers">; -def err_template_arg_unresolved_overloaded_function : Error< - "overloaded function cannot be resolved to a non-type template parameter of " - "type %0">; def err_template_arg_not_decl_ref : Error< "non-type template argument does not refer to any declaration">; def err_template_arg_not_object_or_func_form : Error< @@ -1414,7 +1455,10 @@ def note_prior_template_arg_substitution : Note< " template parameter%1 %2">; def note_template_default_arg_checking : Note< "while checking a default template argument used here">; - +def note_instantiation_contexts_suppressed : Note< + "(skipping %0 context%s0 in backtrace; use -ftemplate-backtrace-limit=0 to " + "see all)">; + def err_field_instantiates_to_function : Error< "data member instantiated with function type %0">; def err_nested_name_spec_non_tag : Error< @@ -1551,6 +1595,14 @@ def err_redefinition_different_kind : Error< "redefinition of %0 as different kind of symbol">; def err_redefinition_different_typedef : Error< "typedef redefinition with different types (%0 vs %1)">; +def err_tag_reference_non_tag : Error< + "elaborated type refers to %select{a non-tag type|a typedef|a template}0">; +def err_tag_reference_conflict : Error< + "implicit declaration introduced by elaborated type conflicts with " + "%select{a declaration|a typedef|a template}0 of the same name">; +def err_dependent_tag_decl : Error< + "%select{declaration|definition}0 of %select{struct|union|class|enum}1 " + "in a dependent scope">; def err_tag_definition_of_typedef : Error< "definition of type %0 conflicts with typedef of the same name">; def err_conflicting_types : Error<"conflicting types for %0">; @@ -1641,6 +1693,8 @@ def err_empty_scalar_initializer : Error<"scalar initializer cannot be empty">; def err_illegal_initializer : Error< "illegal initializer (only variables can be initialized)">; def err_illegal_initializer_type : Error<"illegal initializer type %0">; +def err_init_objc_class : Error< + "cannot initialize Objective-C class type %0">; def err_implicit_empty_initializer : Error< "initializer for aggregate with no elements requires explicit braces">; def err_bitfield_has_negative_width : Error< @@ -1649,9 +1703,18 @@ def err_anon_bitfield_has_negative_width : Error< "anonymous bit-field has negative width (%0)">; def err_bitfield_has_zero_width : Error<"named bit-field %0 has zero width">; def err_bitfield_width_exceeds_type_size : Error< - "size of bit-field %0 exceeds size of its type (%1 bits)">; + "size of bit-field %0 (%1 bits) exceeds size of its type (%2 bits)">; def err_anon_bitfield_width_exceeds_type_size : Error< - "size of anonymous bit-field exceeds size of its type (%0 bits)">; + "size of anonymous bit-field (%0 bits) exceeds size of its type (%1 bits)">; + +// Used by C++ which allows bit-fields that are wider than the type. +def warn_bitfield_width_exceeds_type_size: Warning< + "size of bit-field %0 (%1 bits) exceeds the size of its type; value will be " + "truncated to %2 bits">; +def warn_anon_bitfield_width_exceeds_type_size : Warning< + "size of anonymous bit-field (%0 bits) exceeds size of its type; value will " + "be truncated to %1 bits">; + def warn_missing_braces : Warning< "suggest braces around initialization of subobject">, InGroup<DiagGroup<"missing-braces">>, DefaultIgnore; @@ -1758,6 +1821,7 @@ def ext_offsetof_extended_field_designator : Extension< "using extended field designator is an extension">; def warn_offsetof_non_pod_type : ExtWarn<"offset of on non-POD type %0">, InGroup<InvalidOffsetof>; +def err_offsetof_bitfield : Error<"cannot compute offset of bit-field %0">; def warn_floatingpoint_eq : Warning< "comparing floating point with == or != is unsafe">, @@ -1773,6 +1837,8 @@ def warn_precedence_bitwise_rel : Warning< InGroup<Parentheses>; def note_precedence_bitwise_first : Note< "place parentheses around the %0 expression to evaluate it first">; +def note_precedence_bitwise_silence : Note< + "place parentheses around the %0 expression to silence this warning">; def err_sizeof_nonfragile_interface : Error< "invalid application of '%select{alignof|sizeof}1' to interface %0 in " @@ -1807,9 +1873,9 @@ def err_typecheck_member_reference_arrow : Error< def err_typecheck_member_reference_suggestion : Error< "member reference type %0 is %select{a|not a}1 pointer; maybe you meant to use '%select{->|.}1'?">; def err_typecheck_member_reference_type : Error< - "cannot refer to type member %0 with '%select{.|->}1'">; + "cannot refer to type member %0 in %1 with '%select{.|->}2'">; def err_typecheck_member_reference_unknown : Error< - "cannot refer to member %0 with '%select{.|->}1'">; + "cannot refer to member %0 in %1 with '%select{.|->}2'">; def err_member_reference_needs_call : Error< "base of member reference has function type %0; perhaps you meant to call " "this function with '()'?">; @@ -1835,6 +1901,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">; +def err_ivar_reference_type : Error< + "instance variables cannot be of reference type">; def err_typecheck_illegal_increment_decrement : Error< "cannot %select{decrement|increment}1 value of type %0">; def err_typecheck_arithmetic_incomplete_type : Error< @@ -2003,10 +2071,16 @@ def error_no_super_class : Error< "no super class declared in @interface for %0">; def err_invalid_receiver_to_message : Error< "invalid receiver to message expression">; +def err_invalid_receiver_to_message_super : Error< + "'super' is only valid in a method body">; +def err_invalid_receiver_class_message : Error< + "receiver type %0 is not an Objective-C class">; def warn_bad_receiver_type : Warning< "receiver type %0 is not 'id' or interface pointer, consider " "casting it to 'id'">; def err_bad_receiver_type : Error<"bad receiver type %0">; +def err_unknown_receiver_suggest : Error< + "unknown receiver %0; did you mean %1?">; def error_objc_throw_expects_object : Error< "@throw requires an Objective-C object type (%0 invalid)">; def error_objc_synchronized_expects_object : Error< @@ -2019,8 +2093,15 @@ def err_catch_param_not_objc_type : Error< "@catch parameter is not a pointer to an interface type">; def err_illegal_qualifiers_on_catch_parm : Error< "illegal qualifiers on @catch parameter">; -def err_illegal_super_cast : Error< - "cannot cast 'super' (it isn't an expression)">; +def err_storage_spec_on_catch_parm : Error< + "@catch parameter cannot have storage specifier %select{|'typedef'|'extern'|" + "'static'|'auto'|'register'|'__private_extern__'|'mutable'}0">; +def warn_register_objc_catch_parm : Warning< + "'register' storage specifier on @catch parameter will be ignored">; +def err_qualified_objc_catch_parm : Error< + "@catch parameter declarator cannot be qualified">; + + def warn_setter_getter_impl_required : Warning< "property %0 requires method %1 to be defined - " "use @synthesize, @dynamic or provide a method implementation">; @@ -2029,7 +2110,10 @@ def warn_setter_getter_impl_required_in_category : Warning< "use @dynamic or provide a method implementation in category">; def note_property_impl_required : Note< "implementation is here">; - +def note_parameter_named_here : Note< + "passing argument to parameter %0 here">; +def note_parameter_here : Note< + "passing argument to parameter here">; // C++ casts // These messages adhere to the TryCast pattern: %0 is an int specifying the @@ -2099,6 +2183,8 @@ def err_new_incomplete_type : Error< "allocation of incomplete type %0">; def err_new_array_nonconst : Error< "only the first dimension of an allocated array may have dynamic size">; +def err_new_array_init_args : Error< + "array 'new' cannot have initialization arguments">; def err_new_paren_array_nonconst : Error< "when type is in parentheses, array cannot have dynamic size">; def err_placement_new_non_placement_delete : Error< @@ -2116,8 +2202,8 @@ def warn_delete_incomplete : Warning< "deleting pointer to incomplete type %0 may cause undefined behaviour">; def err_no_suitable_delete_member_function_found : Error< "no suitable member %0 in %1">; -def note_delete_member_function_declared_here : Note< - "%0 declared here">; +def note_member_declared_here : Note< + "member %0 declared here">; def err_decrement_bool : Error<"cannot decrement expression of type bool">; def warn_increment_bool : Warning< "incrementing expression of type bool is deprecated">, InGroup<Deprecated>; @@ -2132,6 +2218,8 @@ def err_qualified_catch_declarator : Error< def err_early_catch_all : Error<"catch-all handler must come last">; def err_bad_memptr_rhs : Error< "right hand operand to %0 has non pointer-to-member type %1">; +def err_memptr_rhs_to_incomplete : Error< + "cannot dereference pointer into incomplete class type %0">; def err_bad_memptr_lhs : Error< "left hand operand to %0 must be a %select{|pointer to }1class " "compatible with the right hand operand, but is %2">; @@ -2190,6 +2278,8 @@ def err_typecheck_deleted_function : Error< "conversion function from %0 to %1 invokes a deleted function">; def err_expected_class_or_namespace : Error<"expected a class or namespace">; +def err_missing_qualified_for_redecl : Error< + "must qualify the name %0 to declare %q1 in this scope">; def err_invalid_declarator_scope : Error< "definition or redeclaration of %0 not in a namespace enclosing %1">; def err_invalid_declarator_global_scope : Error< @@ -2213,6 +2303,8 @@ def warn_condition_is_idiomatic_assignment : Warning<"using the result " InGroup<DiagGroup<"idiomatic-parentheses">>, DefaultIgnore; def note_condition_assign_to_comparison : Note< "use '==' to turn this assignment into an equality comparison">; +def note_condition_assign_silence : Note< + "place parentheses around the assignment to silence this warning">; def warn_value_always_zero : Warning< "%0 is always %select{zero|false|NULL}1 in this context">; @@ -2221,53 +2313,91 @@ def warn_value_always_zero : Warning< // In most of these diagnostics the %2 is a value from the // Sema::AssignmentAction enumeration def err_typecheck_convert_incompatible : Error< - "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< - "cannot initialize a value of type %0 with an %select{rvalue|lvalue}1 " - "of type %2">; -def err_cannot_initialize_decl : Error< - "cannot initialize %0 with an %select{rvalue|lvalue}1 of type %2">; + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from incompatible type|to parameter of incompatible type|" + "from a function with incompatible result type|to incompatible type|" + "with an expression of incompatible type|to parameter of incompatible type|" + "to incompatible type}2 %1">; def warn_incompatible_qualified_id : Warning< - "incompatible type %select{assigning|passing|returning|converting|initializing|sending|casting}2" - " %1, expected %0">; + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from incompatible type|to parameter of incompatible type|" + "from a function with incompatible result type|to incompatible type|" + "with an expression of incompatible type|to parameter of incompatible type|" + "to incompatible type}2 %1">; def ext_typecheck_convert_pointer_int : ExtWarn< "incompatible pointer to integer conversion " - "%select{assigning|passing|returning|converting|initializing|sending|casting}2 %1, expected %0">; + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from|to parameter of type|from a function with result type|to type|" + "with an expression of type|to parameter of type|to type}2 %1">; def ext_typecheck_convert_int_pointer : ExtWarn< "incompatible integer to pointer conversion " - "%select{assigning|passing|returning|converting|initializing|sending|casting}2 %1, expected %0">; + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from|to parameter of type|from a function with result type|to type|" + "with an expression of type|to parameter of type|to type}2 %1">; def ext_typecheck_convert_pointer_void_func : Extension< - "%select{assigning|passing|returning|converting|initializing|sending|casting}2" - " %1 converts between void* and function pointer, expected %0">; + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from|to parameter of type|from a function with result type|to type|" + "with an expression of type|to parameter of type|to type}2 %1 " + "converts between void pointer and function pointer">; def ext_typecheck_convert_incompatible_pointer_sign : ExtWarn< - "pointer types point to integer types with different sign " - "%select{assigning|passing|returning|converting|initializing|sending|casting}2 %1, expected %0">, + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from|to parameter of type|from a function with result type|to type|" + "with an expression of type|to parameter of type|to type}2 %1 " + "converts between pointers to integer types with different sign">, InGroup<DiagGroup<"pointer-sign">>; def ext_typecheck_convert_incompatible_pointer : ExtWarn< "incompatible pointer types " - "%select{assigning|passing|returning|converting|initializing|sending|casting}2 %1, expected %0">; + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from|to parameter of type|from a function with result type|to type|" + "with an expression of type|to parameter of type|to type}2 %1">; def ext_typecheck_convert_discards_qualifiers : ExtWarn< - "%select{assigning|passing|returning|converting|initializing|sending|casting}2" - " %1 discards qualifiers, expected %0">; + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from|to parameter of type|from a function with result type|to type|" + "with an expression of type|to parameter of type|to type}2 %1 discards " + "qualifiers">; def ext_nested_pointer_qualifier_mismatch : ExtWarn< - "%select{assigning|passing|returning|converting|initializing|sending|casting}2," - " %0 and %1 have different qualifiers in nested pointer types">; + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from|to parameter of type|from a function with result type|to type|" + "with an expression of type|to parameter of type|to type}2 %1 discards " + "qualifiers in nested pointer types">; def warn_incompatible_vectors : Warning< - "incompatible vector types %select{assigning|passing|returning|converting|initializing|sending|casting}2" - " %1, expected %0">, + "incompatible vector types " + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from|to parameter of type|from a function with result type|to type|" + "with an expression of type|to parameter of type|to type}2 %1">, InGroup<VectorConversions>, DefaultIgnore; def err_int_to_block_pointer : Error< - "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)">; + "invalid block pointer conversion " + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from|to parameter of type|from a function with result type|to type|" + "with an expression of type|to parameter of type|to type}2 %1">; def err_typecheck_convert_incompatible_block_pointer : Error< "incompatible block pointer types " - "%select{assigning|passing|returning|converting|initializing|sending|casting}2 %1, expected %0">; + "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" + " %0 " + "%select{from|to parameter of type|from a function with result type|to type|" + "with an expression of type|to parameter of type|to type}2 %1">; + +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< + "cannot initialize a value of type %0 with an %select{rvalue|lvalue}1 " + "of type %2">; +def err_cannot_initialize_decl : Error< + "cannot initialize %0 with an %select{rvalue|lvalue}1 of type %2">; +def err_typecheck_comparison_of_distinct_blocks : Error< + "comparison of distinct block types (%0 and %1)">; def err_typecheck_array_not_modifiable_lvalue : Error< "array type %0 is not assignable">; @@ -2295,9 +2425,17 @@ def note_function_with_incomplete_return_type_declared_here : Note< def err_call_incomplete_argument : Error< "argument type %0 is incomplete">; def err_typecheck_call_too_few_args : Error< - "too few arguments to %select{function|block|method}0 call">; + "too few arguments to %select{function|block|method}0 call, " + "expected %1, have %2">; +def err_typecheck_call_too_few_args_at_least : Error< + "too few arguments to %select{function|block|method}0 call, " + "expected at least %1, have %2">; def err_typecheck_call_too_many_args : Error< - "too many arguments to %select{function|block|method}0 call">; + "too many arguments to %select{function|block|method}0 call, " + "expected %1, have %2">; +def err_typecheck_call_too_many_args_at_most : Error< + "too many arguments to %select{function|block|method}0 call, " + "expected at most %1, have %2">; def warn_call_wrong_number_of_arguments : Warning< "too %select{few|many}0 arguments in call to %1">; def err_atomic_builtin_must_be_pointer : Error< @@ -2359,8 +2497,11 @@ def ext_typecheck_expression_not_constant_but_accepted : Extension< InGroup<GNU>; def warn_unused_expr : Warning<"expression result unused">, InGroup<UnusedValue>; +def warn_unused_voidptr : Warning< + "expression result unused; should this cast be to 'void'?">, + InGroup<UnusedValue>; def warn_unused_property_expr : Warning< - "property access result unused - getters should not have side effects">, + "property access result unused - getters should not be used for side effects">, InGroup<UnusedValue>; def warn_unused_call : Warning< "ignoring return value of function declared with %0 attribute">, @@ -2412,24 +2553,21 @@ def err_overload_incorrect_fntype : Error< def err_only_constructors_take_base_inits : Error< "only constructors take base initializers">; -def error_multiple_mem_initialization : Error < - "multiple initializations given for non-static member '%0'">; - -def error_multiple_base_initialization : Error < +def err_multiple_mem_initialization : Error < + "multiple initializations given for non-static member %0">; +def err_multiple_mem_union_initialization : Error < + "initializing multiple members of anonymous union">; +def err_multiple_base_initialization : Error < "multiple initializations given for base %0">; def err_mem_init_not_member_or_class : Error< "member initializer %0 does not name a non-static data member or base " "class">; -def warn_field_initialized : Warning< - "member '%0' will be initialized after">, - InGroup<Reorder>, DefaultIgnore; -def warn_base_initialized : Warning< - "base class %0 will be initialized after">, +def warn_initializer_out_of_order : Warning< + "%select{field|base class}0 %1 will be initialized after " + "%select{field|base}2 %3">, InGroup<Reorder>, DefaultIgnore; -def note_fieldorbase_initialized_here : Note< - "%select{field|base}0 %1">; def err_base_init_does_not_name_class : Error< "constructor initializer %0 does not name a class">; @@ -2437,9 +2575,7 @@ def err_base_init_direct_and_virtual : Error< "base class initializer %0 names both a direct base class and an " "inherited virtual base class">; def err_not_direct_base_or_virtual : Error< - "type %0 is not a direct or virtual base of '%1'">; -def err_not_direct_base_or_virtual_multi : Error< - "type %0 is not a direct or virtual base of '%1'">; + "type %0 is not a direct or virtual base of %1">; def err_in_class_initializer_non_integral_type : Error< "in-class initializer has non-integral, non-enumeration type %0">; @@ -2587,6 +2723,8 @@ def err_conv_function_to_array : Error< "conversion function cannot convert to an array type">; def err_conv_function_to_function : Error< "conversion function cannot convert to a function type">; +def err_conv_function_with_complex_decl : Error< + "must use a typedef to declare a conversion to %0">; def err_conv_function_redeclared : Error< "conversion function cannot be redeclared">; def warn_conv_to_self_not_used : Warning< @@ -2669,7 +2807,7 @@ def warn_selfcomparison : Warning< "self-comparison always results in a constant value">; def warn_stringcompare : Warning< "result of comparison against %select{a string literal|@encode}0 is " - "unspecified (use strcmp instead)">; + "unspecified (use strncmp instead)">; @@ -2698,7 +2836,7 @@ def err_default_not_in_switch : Error< "'default' statement not in switch statement">; def err_case_not_in_switch : Error<"'case' statement not in switch statement">; def warn_bool_switch_condition : Warning< - "switch condition is a bool">; + "switch condition has boolean value">; def warn_case_value_overflow : Warning< "overflow converting case value to switch condition type (%0 to %1)">, InGroup<DiagGroup<"switch">>; @@ -2770,22 +2908,15 @@ def err_vector_incorrect_num_initializers : Error< "%select{too many|too few}0 elements in vector initialization (expected %1 elements, have %2)">; def err_altivec_empty_initializer : Error<"expected initializer">; -def err_stack_const_level : Error< - "level argument for a stack address builtin must be constant">; - -def err_prefetch_invalid_arg_type : Error< - "argument to __builtin_prefetch must be of integer type">; -def err_prefetch_invalid_arg_ice : Error< - "argument to __builtin_prefetch must be a constant integer">; def err_argument_invalid_range : Error< "argument should be a value from %0 to %1">; -def err_object_size_invalid_argument : Error< - "argument to __builtin_object_size must be a constant integer">; - def err_builtin_longjmp_invalid_val : Error< "argument to __builtin_longjmp must be a constant 1">; +def err_constant_integer_arg_type : Error< + "argument to %0 must be a constant integer">; + def ext_mixed_decls_code : Extension< "ISO C90 forbids mixing declarations and code">; def err_non_variable_decl_in_for : Error< @@ -2834,9 +2965,9 @@ def warn_ivar_use_hidden : Warning< def error_ivar_use_in_class_method : Error< "instance variable %0 accessed in class method">; def error_private_ivar_access : Error<"instance variable %0 is private">, - NoSFINAE; + NoSFINAE; def error_protected_ivar_access : Error<"instance variable %0 is protected">, - NoSFINAE; + NoSFINAE; def warn_maynot_respond : Warning<"%0 may not respond to %1">; def warn_attribute_method_def : Warning< "method attribute can only be specified on method declarations">; diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index fdf69d0..1ed86f1 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -28,6 +28,7 @@ public: unsigned DollarIdents : 1; // '$' allowed in identifiers. unsigned AsmPreprocessor : 1; // Preprocessor in asm mode. unsigned GNUMode : 1; // True in gnu99 mode false in c99 mode (etc) + unsigned GNUKeywords : 1; // True if GNU-only keywords are allowed unsigned ImplicitInt : 1; // C89 implicit 'int'. unsigned Digraphs : 1; // C94, C99 and C++ unsigned HexFloats : 1; // C99 Hexadecimal float constants. @@ -98,8 +99,13 @@ public: unsigned ElideConstructors : 1; // Whether C++ copy constructors should be // elided if possible. unsigned CatchUndefined : 1; // Generate code to check for undefined ops. - unsigned DumpVtableLayouts : 1; // Dump the layouts of all the emitted - // vtables. + unsigned DumpRecordLayouts : 1; /// Dump the layout of IRgen'd records. + unsigned DumpVTableLayouts : 1; /// Dump the layouts of emitted vtables. + unsigned NoConstantCFStrings : 1; // Do not do CF strings + + // FIXME: This is just a temporary option, for testing purposes. + unsigned NoBitFieldTypeAlign : 1; + private: unsigned GC : 2; // Objective-C Garbage Collection modes. We // declare this enum as unsigned because MSVC @@ -126,9 +132,10 @@ public: LangOptions() { Trigraphs = BCPLComment = Bool = DollarIdents = AsmPreprocessor = 0; - GNUMode = ImplicitInt = Digraphs = 0; + GNUMode = GNUKeywords = ImplicitInt = Digraphs = 0; HexFloats = 0; GC = ObjC1 = ObjC2 = ObjCNonFragileABI = ObjCNonFragileABI2 = 0; + NoConstantCFStrings = 0; C99 = Microsoft = CPlusPlus = CPlusPlus0x = 0; CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0; Exceptions = SjLjExceptions = Freestanding = NoBuiltin = 0; @@ -155,7 +162,7 @@ public: OverflowChecking = 0; ObjCGCBitmapPrint = 0; - InstantiationDepth = 500; + InstantiationDepth = 1024; Optimize = 0; OptimizeSize = 0; @@ -169,7 +176,9 @@ public: CharIsSigned = 1; ShortWChar = 0; CatchUndefined = 0; - DumpVtableLayouts = 0; + DumpRecordLayouts = 0; + DumpVTableLayouts = 0; + NoBitFieldTypeAlign = 0; } GCMode getGCMode() const { return (GCMode) GC; } diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h index 555e6f5..0bbeffe 100644 --- a/include/clang/Basic/SourceLocation.h +++ b/include/clang/Basic/SourceLocation.h @@ -176,19 +176,14 @@ public: /// FullSourceLoc - A SourceLocation and its associated SourceManager. Useful /// for argument passing to functions that expect both objects. class FullSourceLoc : public SourceLocation { - SourceManager* SrcMgr; + const SourceManager *SrcMgr; public: /// Creates a FullSourceLoc where isValid() returns false. - explicit FullSourceLoc() : SrcMgr((SourceManager*) 0) {} + explicit FullSourceLoc() : SrcMgr(0) {} - explicit FullSourceLoc(SourceLocation Loc, SourceManager &SM) + explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM) : SourceLocation(Loc), SrcMgr(&SM) {} - SourceManager &getManager() { - assert(SrcMgr && "SourceManager is NULL."); - return *SrcMgr; - } - const SourceManager &getManager() const { assert(SrcMgr && "SourceManager is NULL."); return *SrcMgr; diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index d123969..930fb52 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -78,8 +78,13 @@ namespace SrcMgr { /// \param Diag Object through which diagnostics will be emitted it the /// buffer cannot be retrieved. /// + /// \param Loc If specified, is the location that invalid file diagnostics + /// will be emitted at. + /// /// \param Invalid If non-NULL, will be set \c true if an error occurred. - const llvm::MemoryBuffer *getBuffer(Diagnostic &Diag, + const llvm::MemoryBuffer *getBuffer(Diagnostic &Diag, + const SourceManager &SM, + SourceLocation Loc = SourceLocation(), bool *Invalid = 0) const; /// getSize - Returns the size of the content encapsulated by this @@ -447,11 +452,17 @@ public: /// getBuffer - Return the buffer for the specified FileID. If there is an /// error opening this buffer the first time, this manufactures a temporary /// buffer and returns a non-empty error string. - const llvm::MemoryBuffer *getBuffer(FileID FID, bool *Invalid = 0) const { - return getSLocEntry(FID).getFile().getContentCache()->getBuffer(Diag, - Invalid); + const llvm::MemoryBuffer *getBuffer(FileID FID, SourceLocation Loc, + bool *Invalid = 0) const { + return getSLocEntry(FID).getFile().getContentCache() + ->getBuffer(Diag, *this, Loc, Invalid); } + const llvm::MemoryBuffer *getBuffer(FileID FID, bool *Invalid = 0) const { + return getSLocEntry(FID).getFile().getContentCache() + ->getBuffer(Diag, *this, SourceLocation(), Invalid); + } + /// getFileEntryForID - Returns the FileEntry record for the provided FileID. const FileEntry *getFileEntryForID(FileID FID) const { return getSLocEntry(FID).getFile().getContentCache()->Entry; diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index bc2cf19..1998750 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -45,6 +45,7 @@ protected: // Target values set by the ctor of the actual target implementation. Default // values are specified by the TargetInfo constructor. bool TLSSupported; + bool NoAsmVariants; // True if {|} are normal characters. unsigned char PointerWidth, PointerAlign; unsigned char IntWidth, IntAlign; unsigned char FloatWidth, FloatAlign; @@ -85,6 +86,14 @@ public: protected: IntType SizeType, IntMaxType, UIntMaxType, PtrDiffType, IntPtrType, WCharType, WIntType, Char16Type, Char32Type, Int64Type, SigAtomicType; + + /// Control whether the alignment of bit-field types is respected when laying + /// out structures. If true, then the alignment of the bit-field type will be + /// used to (a) impact the alignment of the containing structure, and (b) + /// ensure that the individual bit-field will not straddle an alignment + /// boundary. + unsigned UseBitFieldTypeAlignment : 1; + public: IntType getSizeType() const { return SizeType; } IntType getIntMaxType() const { return IntMaxType; } @@ -197,6 +206,10 @@ public: return UserLabelPrefix; } + bool useBitFieldTypeAlignment() const { + return UseBitFieldTypeAlignment; + } + /// getTypeName - Return the user string for the specified integer type enum. /// For example, SignedShort -> "short". static const char *getTypeName(IntType T); @@ -326,6 +339,18 @@ public: return "__DATA,__cfstring"; } + /// getNSStringSection - Return the section to use for NSString + /// literals, or 0 if no special section is used. + virtual const char *getNSStringSection() const { + return "__OBJC,__cstring_object,regular,no_dead_strip"; + } + + /// getNSStringNonFragileABISection - Return the section to use for + /// NSString literals, or 0 if no special section is used (NonFragile ABI). + virtual const char *getNSStringNonFragileABISection() const { + return "__DATA, __objc_stringobj, regular, no_dead_strip"; + } + /// isValidSectionSpecifier - This is an optional hook that targets can /// implement to perform semantic checking on attribute((section("foo"))) /// specifiers. In this case, "foo" is passed in to be checked. If the @@ -402,6 +427,15 @@ public: return TLSSupported; } + /// hasNoAsmVariants - Return true if {|} are normal characters in the + /// asm string. If this returns false (the default), then {abc|xyz} is syntax + /// that says that when compiling for asm variant #0, "abc" should be + /// generated, but when compiling for asm variant #1, "xyz" should be + /// generated. + bool hasNoAsmVariants() const { + return NoAsmVariants; + } + /// getEHDataRegisterNumber - Return the register number that /// __builtin_eh_return_regno would return with the specified argument. virtual int getEHDataRegisterNumber(unsigned RegNo) const { diff --git a/include/clang/Basic/Version.h b/include/clang/Basic/Version.h index 2e0993a..b3b6184 100644 --- a/include/clang/Basic/Version.h +++ b/include/clang/Basic/Version.h @@ -18,11 +18,11 @@ #include "llvm/ADT/StringRef.h" /// \brief Clang major version -#define CLANG_VERSION_MAJOR 1 +#define CLANG_VERSION_MAJOR 2 // FIXME: Updates to this file must also update CMakeLists.txt and VER. /// \brief Clang minor version -#define CLANG_VERSION_MINOR 5 +#define CLANG_VERSION_MINOR 0 /// \brief Clang patchlevel version // #define CLANG_VERSION_PATCHLEVEL 1 diff --git a/include/clang/Checker/BugReporter/BugReporter.h b/include/clang/Checker/BugReporter/BugReporter.h index 6170342..5b65d52 100644 --- a/include/clang/Checker/BugReporter/BugReporter.h +++ b/include/clang/Checker/BugReporter/BugReporter.h @@ -458,7 +458,6 @@ public: namespace bugreporter { const Stmt *GetDerefExpr(const ExplodedNode *N); -const Stmt *GetReceiverExpr(const ExplodedNode *N); const Stmt *GetDenomExpr(const ExplodedNode *N); const Stmt *GetCalleeExpr(const ExplodedNode *N); const Stmt *GetRetValExpr(const ExplodedNode *N); diff --git a/include/clang/Checker/PathSensitive/AnalysisManager.h b/include/clang/Checker/PathSensitive/AnalysisManager.h index fdf52a7..0c59d7b 100644 --- a/include/clang/Checker/PathSensitive/AnalysisManager.h +++ b/include/clang/Checker/PathSensitive/AnalysisManager.h @@ -37,6 +37,8 @@ class AnalysisManager : public BugReporterData { enum AnalysisScope { ScopeTU, ScopeDecl } AScope; + unsigned MaxNodes; + bool VisualizeEGDot; bool VisualizeEGUbi; bool PurgeDead; @@ -55,12 +57,12 @@ public: AnalysisManager(ASTContext &ctx, Diagnostic &diags, const LangOptions &lang, PathDiagnosticClient *pd, StoreManagerCreator storemgr, - ConstraintManagerCreator constraintmgr, + ConstraintManagerCreator constraintmgr, unsigned maxnodes, bool vizdot, bool vizubi, bool purge, bool eager, bool trim) : Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd), CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr), - AScope(ScopeDecl), + AScope(ScopeDecl), MaxNodes(maxnodes), VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge), EagerlyAssume(eager), TrimGraph(trim) {} @@ -104,6 +106,8 @@ public: PD->FlushDiagnostics(); } + unsigned getMaxNodes() const { return MaxNodes; } + bool shouldVisualizeGraphviz() const { return VisualizeEGDot; } bool shouldVisualizeUbigraph() const { return VisualizeEGUbi; } diff --git a/include/clang/Checker/PathSensitive/GRCoreEngine.h b/include/clang/Checker/PathSensitive/GRCoreEngine.h index a3ff0db..2d8afee 100644 --- a/include/clang/Checker/PathSensitive/GRCoreEngine.h +++ b/include/clang/Checker/PathSensitive/GRCoreEngine.h @@ -239,31 +239,7 @@ public: } ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred, - const GRState* St, ProgramPoint::Kind K) { - - const GRState* PredState = GetState(Pred); - - // If the state hasn't changed, don't generate a new node. - if (!BuildSinks && St == PredState && Auditor == 0) { - Dst.Add(Pred); - return NULL; - } - - ExplodedNode* N = generateNode(S, St, Pred, K); - - if (N) { - if (BuildSinks) - N->markAsSink(); - else { - if (Auditor && Auditor->Audit(N, Mgr)) - N->markAsSink(); - - Dst.Add(N); - } - } - - return N; - } + const GRState* St, ProgramPoint::Kind K); ExplodedNode* MakeSinkNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred, const GRState* St) { @@ -273,7 +249,6 @@ public: BuildSinks = Tmp; return N; } - }; class GRBranchNodeBuilder { diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h index 161cb28..f04ca75 100644 --- a/include/clang/Checker/PathSensitive/GRExprEngine.h +++ b/include/clang/Checker/PathSensitive/GRExprEngine.h @@ -87,6 +87,15 @@ class GRExprEngine : public GRSubEngine { llvm::OwningPtr<GRTransferFuncs> TF; + class CallExprWLItem { + public: + CallExpr::arg_iterator I; + ExplodedNode *N; + + CallExprWLItem(const CallExpr::arg_iterator &i, ExplodedNode *n) + : I(i), N(n) {} + }; + public: GRExprEngine(AnalysisManager &mgr, GRTransferFuncs *tf); @@ -333,6 +342,10 @@ public: /// VisitReturnStmt - Transfer function logic for return statements. void VisitReturnStmt(ReturnStmt* R, ExplodedNode* Pred, ExplodedNodeSet& Dst); + + /// VisitOffsetOfExpr - Transfer function for offsetof. + void VisitOffsetOfExpr(OffsetOfExpr* Ex, ExplodedNode* Pred, + ExplodedNodeSet& Dst); /// VisitSizeOfAlignOfExpr - Transfer function for sizeof. void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex, ExplodedNode* Pred, @@ -352,6 +365,12 @@ public: void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, ExplodedNode *Pred, ExplodedNodeSet &Dst); + void VisitCXXNewExpr(CXXNewExpr *CNE, ExplodedNode *Pred, + ExplodedNodeSet &Dst); + + void VisitCXXDeleteExpr(CXXDeleteExpr *CDE, ExplodedNode *Pred, + ExplodedNodeSet &Dst); + void VisitAggExpr(const Expr *E, SVal Dest, ExplodedNode *Pred, ExplodedNodeSet &Dst); @@ -363,6 +382,11 @@ public: const CXXThisRegion *getCXXThisRegion(const CXXMethodDecl *MD, const StackFrameContext *SFC); + /// Evaluate arguments with a work list algorithm. + void EvalArguments(ExprIterator AI, ExprIterator AE, + const FunctionProtoType *FnType, + 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) /// with those assumptions. diff --git a/include/clang/Checker/PathSensitive/MemRegion.h b/include/clang/Checker/PathSensitive/MemRegion.h index 57ea8a3..2ab3b42 100644 --- a/include/clang/Checker/PathSensitive/MemRegion.h +++ b/include/clang/Checker/PathSensitive/MemRegion.h @@ -869,11 +869,11 @@ public: /// getElementRegion - Retrieve the memory region associated with the /// associated element type, index, and super region. const ElementRegion *getElementRegion(QualType elementType, SVal Idx, - const MemRegion *superRegion, - ASTContext &Ctx); + const MemRegion *superRegion, + ASTContext &Ctx); const ElementRegion *getElementRegionWithSuper(const ElementRegion *ER, - const MemRegion *superRegion) { + const MemRegion *superRegion) { return getElementRegion(ER->getElementType(), ER->getIndex(), superRegion, ER->getContext()); } diff --git a/include/clang/Checker/PathSensitive/Store.h b/include/clang/Checker/PathSensitive/Store.h index 72565f4..41d7c2b 100644 --- a/include/clang/Checker/PathSensitive/Store.h +++ b/include/clang/Checker/PathSensitive/Store.h @@ -129,11 +129,14 @@ public: CastResult(const GRState *s, const MemRegion* r = 0) : state(s), region(r){} }; + const ElementRegion *GetElementZeroRegion(const MemRegion *R, QualType T); + /// CastRegion - Used by GRExprEngine::VisitCast to handle casts from /// a MemRegion* to a specific location type. 'R' is the region being /// casted and 'CastToTy' the result type of the cast. const MemRegion *CastRegion(const MemRegion *region, QualType CastToTy); + /// EvalBinOp - Perform pointer arithmetic. virtual SVal EvalBinOp(BinaryOperator::Opcode Op, Loc lhs, NonLoc rhs, QualType resultTy) { diff --git a/include/clang/Checker/PathSensitive/ValueManager.h b/include/clang/Checker/PathSensitive/ValueManager.h index f80ad42..5a9d54d 100644 --- a/include/clang/Checker/PathSensitive/ValueManager.h +++ b/include/clang/Checker/PathSensitive/ValueManager.h @@ -22,6 +22,7 @@ #include "clang/Checker/PathSensitive/BasicValueFactory.h" #include "clang/Checker/PathSensitive/SymbolManager.h" #include "clang/Checker/PathSensitive/SValuator.h" +#include "clang/AST/ExprCXX.h" namespace llvm { class BumpPtrAllocator; } @@ -133,6 +134,11 @@ public: I->getType()->isUnsignedIntegerType())); } + nonloc::ConcreteInt makeIntVal(const CXXBoolLiteralExpr *E) { + return E->getValue() ? nonloc::ConcreteInt(BasicVals.getValue(1, 1, true)) + : nonloc::ConcreteInt(BasicVals.getValue(0, 1, true)); + } + nonloc::ConcreteInt makeIntVal(const llvm::APSInt& V) { return nonloc::ConcreteInt(BasicVals.getValue(V)); } diff --git a/include/clang/CodeGen/CodeGenOptions.h b/include/clang/CodeGen/CodeGenOptions.h index 638ed51..54d3ba0 100644 --- a/include/clang/CodeGen/CodeGenOptions.h +++ b/include/clang/CodeGen/CodeGenOptions.h @@ -28,10 +28,17 @@ public: OnlyAlwaysInlining // Only run the always inlining pass. }; + enum ObjCDispatchMethodKind { + Legacy = 0, + NonLegacy = 1, + Mixed = 2 + }; + unsigned AsmVerbose : 1; /// -dA, -fverbose-asm. unsigned CXAAtExit : 1; /// Use __cxa_atexit for calling destructors. unsigned CXXCtorDtorAliases: 1; /// Emit complete ctors/dtors as linker /// aliases to base ctors when possible. + unsigned DataSections : 1; /// Set when -fdata-sections is enabled unsigned DebugInfo : 1; /// Should generate deubg info (-g). unsigned DisableFPElim : 1; /// Set when -fomit-frame-pointer is enabled. unsigned DisableLLVMOpts : 1; /// Don't run any optimizations, for use in @@ -39,12 +46,12 @@ public: /// internal state before optimizations are /// done. unsigned DisableRedZone : 1; /// Set when -mno-red-zone is enabled. + unsigned FunctionSections : 1; /// Set when -ffunction-sections is enabled unsigned MergeAllConstants : 1; /// Merge identical constants. unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled. unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled. unsigned NoZeroInitializedInBSS : 1; /// -fno-zero-initialized-in-bss - unsigned ObjCLegacyDispatch: 1; /// Use legacy Objective-C dispatch, even with - /// 2.0 runtime. + unsigned ObjCDispatchMethod : 2; /// Method of Objective-C dispatch to use. unsigned OptimizationLevel : 3; /// The -O[0-4] option specified. unsigned OptimizeSize : 1; /// If -Os is specified. unsigned SoftFloat : 1; /// -soft-float. @@ -88,15 +95,17 @@ public: AsmVerbose = 0; CXAAtExit = 1; CXXCtorDtorAliases = 0; + DataSections = 0; DebugInfo = 0; DisableFPElim = 0; DisableLLVMOpts = 0; DisableRedZone = 0; + FunctionSections = 0; MergeAllConstants = 1; NoCommon = 0; NoImplicitFloat = 0; NoZeroInitializedInBSS = 0; - ObjCLegacyDispatch = 0; + ObjCDispatchMethod = Legacy; OptimizationLevel = 0; OptimizeSize = 0; SoftFloat = 0; @@ -109,6 +118,10 @@ public: Inlining = NoInlining; RelocationModel = "pic"; } + + ObjCDispatchMethodKind getObjCDispatchMethod() const { + return ObjCDispatchMethodKind(ObjCDispatchMethod); + } }; } // end namespace clang diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 124288a..18b54ef 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -97,6 +97,8 @@ def analyzer_viz_egraph_graphviz : Flag<"-analyzer-viz-egraph-graphviz">, HelpText<"Display exploded graph using GraphViz">; def analyzer_viz_egraph_ubigraph : Flag<"-analyzer-viz-egraph-ubigraph">, HelpText<"Display exploded graph using Ubigraph">; +def analyzer_max_nodes : Separate<"-analyzer-max-nodes">, + HelpText<"The maximum number of nodes the analyzer can generate">; //===----------------------------------------------------------------------===// // CodeGen Options @@ -123,6 +125,10 @@ def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, HelpText<"Do not emit code to make initialization of local statics thread safe">; def fdump_vtable_layouts : Flag<"-fdump-vtable-layouts">, HelpText<"Dump the layouts of all vtables that will be emitted in a translation unit">; +def ffunction_sections : Flag<"-ffunction-sections">, + HelpText<"Place each function in its own section (ELF Only)">; +def fdata_sections : Flag<"-fdata-sections">, + HelpText<"Place each data in its own section (ELF Only)">; def masm_verbose : Flag<"-masm-verbose">, HelpText<"Generate verbose assembly output">; def mcode_model : Separate<"-mcode-model">, @@ -192,6 +198,10 @@ def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, HelpText<"Print diagnostic name with mappable diagnostics">; def ftabstop : Separate<"-ftabstop">, MetaVarName<"<N>">, HelpText<"Set the tab stop distance.">; +def ferror_limit : Separate<"-ferror-limit">, MetaVarName<"<N>">, + HelpText<"Set the maximum number of errors to emit before stopping (0 = no limit).">; +def ftemplate_backtrace_limit : Separate<"-ftemplate-backtrace-limit">, MetaVarName<"<N>">, + HelpText<"Set the maximum number of entries to print in a template instantiation backtrace (0 = no limit).">; def fmessage_length : Separate<"-fmessage-length">, MetaVarName<"<N>">, HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">; def fcolor_diagnostics : Flag<"-fcolor-diagnostics">, @@ -235,8 +245,6 @@ def x : Separate<"-x">, HelpText<"Input language type">; def cxx_inheritance_view : Separate<"-cxx-inheritance-view">, MetaVarName<"<class name>">, HelpText<"View C++ inheritance for a specified class">; -def fixit_at : Separate<"-fixit-at">, MetaVarName<"<source location>">, - HelpText<"Perform Fix-It modifications at the given source location">; def o : Separate<"-o">, MetaVarName<"<path>">, HelpText<"Specify output file">; def load : Separate<"-load">, MetaVarName<"<dsopath>">, HelpText<"Load the named plugin (dynamic shared object)">; @@ -269,6 +277,8 @@ def fsyntax_only : Flag<"-fsyntax-only">, HelpText<"Run parser and perform semantic analysis">; def fixit : Flag<"-fixit">, HelpText<"Apply fix-it advice to the input source">; +def fixit_EQ : Joined<"-fixit=">, + HelpText<"Apply fix-it advice creating a file with the given suffix">; def parse_print_callbacks : Flag<"-parse-print-callbacks">, HelpText<"Run parser and print each callback invoked">; def emit_html : Flag<"-emit-html">, @@ -283,8 +293,6 @@ def ast_view : Flag<"-ast-view">, HelpText<"Build ASTs and view them with GraphViz">; def print_decl_contexts : Flag<"-print-decl-contexts">, HelpText<"Print DeclContexts and their Decls">; -def dump_record_layouts : Flag<"-dump-record-layouts">, - HelpText<"Dump record layout information">; def emit_pth : Flag<"-emit-pth">, HelpText<"Generate pre-tokenized header file">; def emit_pch : Flag<"-emit-pch">, @@ -315,6 +323,14 @@ def print_stats : Flag<"-print-stats">, def ftime_report : Flag<"-ftime-report">, HelpText<"Print the amount of time each phase of compilation takes">; +def fdump_record_layouts : Flag<"-fdump-record-layouts">, + HelpText<"Dump record layout information">; + +// Generic forwarding to LLVM options. This should only be used for debugging +// and experimental features. +def mllvm : Separate<"-mllvm">, + HelpText<"Additional arguments to forward to LLVM's option processing">; + //===----------------------------------------------------------------------===// // Language Options //===----------------------------------------------------------------------===// @@ -323,10 +339,14 @@ def fno_builtin : Flag<"-fno-builtin">, HelpText<"Disable implicit builtin knowledge of functions">; def faltivec : Flag<"-faltivec">, HelpText<"Enable AltiVec vector initializer syntax">; -def faccess_control : Flag<"-faccess-control">, - HelpText<"Enable C++ access control">; +def fno_access_control : Flag<"-fno-access-control">, + HelpText<"Disable C++ access control">; def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">, HelpText<"Don't assume that C++'s global operator new can't alias any pointer">; +def fgnu_keywords : Flag<"-fgnu-keywords">, + HelpText<"Allow GNU-extension keywords regardless of language standard">; +def fno_gnu_keywords : Flag<"-fno-gnu-keywords">, + HelpText<"Disallow GNU-extension keywords regardless of language standard">; def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, HelpText<"Allow '$' in identifiers">; def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, @@ -365,12 +385,14 @@ def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">, def fconstant_string_class : Separate<"-fconstant-string-class">, MetaVarName<"<class name>">, HelpText<"Specify the class to use for constant Objective-C string objects.">; +def fno_constant_cfstrings : Flag<"-fno-constant-cfstrings">, + HelpText<"Enable creation of CodeFoundation-type constant strings">; def fobjc_gc : Flag<"-fobjc-gc">, HelpText<"Enable Objective-C garbage collection">; def fobjc_gc_only : Flag<"-fobjc-gc-only">, HelpText<"Use GC exclusively for Objective-C related memory management">; -def fobjc_legacy_dispatch : Flag<"-fobjc-legacy-dispatch">, - HelpText<"Use legacy dispatch with the Objective-C non-fragile ABI">; +def fobjc_dispatch_method_EQ : Joined<"-fobjc-dispatch-method=">, + HelpText<"Objective-C dispatch method to use">; def print_ivar_layout : Flag<"-print-ivar-layout">, HelpText<"Enable Objective-C Ivar layout bitmap print trace">; def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">, @@ -401,6 +423,8 @@ def trigraphs : Flag<"-trigraphs">, HelpText<"Process trigraph sequences">; def fwritable_strings : Flag<"-fwritable-strings">, HelpText<"Store string literals as writable data">; +def fno_bitfield_type_align : Flag<"-fno-bitfield-type-align">, + HelpText<"Ignore bit-field types when aligning structures">; //===----------------------------------------------------------------------===// // Header Search Options diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index ed68d68..2127e57 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -248,7 +248,7 @@ def fclasspath_EQ : Joined<"-fclasspath=">, Group<f_Group>; def fcolor_diagnostics : Flag<"-fcolor-diagnostics">, Group<f_Group>; def fcommon : Flag<"-fcommon">, Group<f_Group>; def fcompile_resource_EQ : Joined<"-fcompile-resource=">, Group<f_Group>; -def fconstant_cfstrings : Flag<"-fconstant-cfstrings">, Group<clang_ignored_f_Group>; +def fconstant_cfstrings : Flag<"-fconstant-cfstrings">, Group<f_Group>; def fconstant_string_class_EQ : Joined<"-fconstant-string-class=">, Group<f_Group>; def fcreate_profile : Flag<"-fcreate-profile">, Group<f_Group>; def fdebug_pass_arguments : Flag<"-fdebug-pass-arguments">, Group<f_Group>; @@ -265,6 +265,10 @@ def fexceptions : Flag<"-fexceptions">, Group<f_Group>; def fextdirs_EQ : Joined<"-fextdirs=">, Group<f_Group>; def fhosted : Flag<"-fhosted">, Group<f_Group>; def ffreestanding : Flag<"-ffreestanding">, Group<f_Group>; + +def fgnu_keywords : Flag<"-fgnu-keywords">, Group<f_Group>; +def fasm : Flag<"-fasm">, Alias<fgnu_keywords>; + def fgnu_runtime : Flag<"-fgnu-runtime">, Group<f_Group>; def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">; def filelist : Separate<"-filelist">, Flags<[LinkerInput]>; @@ -300,6 +304,10 @@ def fno_diagnostics_show_option : Flag<"-fno-diagnostics-show-option">, Group<f_ def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, Group<f_Group>; def fno_eliminate_unused_debug_symbols : Flag<"-fno-eliminate-unused-debug-symbols">, Group<f_Group>; def fno_exceptions : Flag<"-fno-exceptions">, Group<f_Group>; + +def fno_gnu_keywords : Flag<"-fno-gnu-keywords">, Group<f_Group>; +def fno_asm : Flag<"-fno-asm">, Alias<fno_gnu_keywords>; + def fno_inline_functions : Flag<"-fno-inline-functions">, Group<clang_ignored_f_Group>; def fno_inline : Flag<"-fno-inline">, Group<clang_ignored_f_Group>; def fno_keep_inline_functions : Flag<"-fno-keep-inline-functions">, Group<clang_ignored_f_Group>; @@ -321,6 +329,7 @@ def fno_unit_at_a_time : Flag<"-fno-unit-at-a-time">, Group<f_Group>; def fno_unwind_tables : Flag<"-fno-unwind-tables">, Group<f_Group>; def fno_working_directory : Flag<"-fno-working-directory">, Group<f_Group>; def fno_zero_initialized_in_bss : Flag<"-fno-zero-initialized-in-bss">, Group<f_Group>; +def fobjc_abi_version_EQ : Joined<"-fobjc-abi-version=">, Group<f_Group>; def fobjc_atdefs : Flag<"-fobjc-atdefs">, Group<clang_ignored_f_Group>; def fobjc_call_cxx_cdtors : Flag<"-fobjc-call-cxx-cdtors">, Group<clang_ignored_f_Group>; def fobjc_gc_only : Flag<"-fobjc-gc-only">, Group<f_Group>; @@ -356,7 +365,10 @@ def fstack_protector : Flag<"-fstack-protector">, Group<f_Group>; def fstrict_aliasing : Flag<"-fstrict-aliasing">, Group<clang_ignored_f_Group>; def fsyntax_only : Flag<"-fsyntax-only">, Flags<[DriverOption]>; def ftabstop_EQ : Joined<"-ftabstop=">, Group<f_Group>; +def ferror_limit_EQ : Joined<"-ferror-limit=">, Group<f_Group>; def ftemplate_depth_ : Joined<"-ftemplate-depth-">, Group<f_Group>; +def ftemplate_backtrace_limit_EQ : Joined<"-ftemplate-backtrace-limit=">, + Group<f_Group>; def fterminated_vtables : Flag<"-fterminated-vtables">, Group<f_Group>; def fthreadsafe_statics : Flag<"-fthreadsafe-statics">, Group<f_Group>; def ftime_report : Flag<"-ftime-report">, Group<f_Group>; diff --git a/include/clang/Driver/Tool.h b/include/clang/Driver/Tool.h index 851e423..ef77206 100644 --- a/include/clang/Driver/Tool.h +++ b/include/clang/Driver/Tool.h @@ -48,6 +48,10 @@ public: virtual bool hasIntegratedAssembler() const { return false; } virtual bool hasIntegratedCPP() const = 0; + /// \brief Does this tool have "good" standardized diagnostics, or should the + /// driver add an additional "command failed" diagnostic on failures. + virtual bool hasGoodDiagnostics() const { return false; } + /// ConstructJob - Construct jobs to perform the action \arg JA, /// writing to \arg Output and with \arg Inputs. /// diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index 9a82973..1a8ae77 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -103,6 +103,10 @@ public: /// ABI). virtual bool IsObjCLegacyDispatchDefault() const { return false; } + /// UseObjCMixedDispatchDefault - When using non-legacy dispatch, should the + /// mixed dispatch method be used? + virtual bool UseObjCMixedDispatch() const { return false; } + /// GetDefaultStackProtectorLevel - Get the default stack protector level for /// this tool chain (0=off, 1=on, 2=all). virtual unsigned GetDefaultStackProtectorLevel() const { return 0; } @@ -120,6 +124,9 @@ public: /// particular PIC mode. virtual const char *GetForcedPicModel() const = 0; + /// Does this tool chain support Objective-C garbage collection. + virtual bool SupportsObjCGC() const { return false; } + /// UseDwarfDebugFlags - Embed the compile options to clang into the Dwarf /// compile unit information. virtual bool UseDwarfDebugFlags() const { return false; } diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h index b5b09f5..9163a20 100644 --- a/include/clang/Frontend/ASTConsumers.h +++ b/include/clang/Frontend/ASTConsumers.h @@ -57,10 +57,6 @@ ASTConsumer *CreateASTViewer(); // to stderr; this is intended for debugging. ASTConsumer *CreateDeclContextPrinter(); -// RecordLayout dumper: prints out the record layout information for all records -// in the translation unit; this is intended for debugging. -ASTConsumer *CreateRecordLayoutDumper(); - // ObjC rewriter: attempts tp rewrite ObjC constructs into pure C code. // This is considered experimental, and only works with Apple's ObjC runtime. ASTConsumer *CreateObjCRewriter(const std::string &InFile, diff --git a/include/clang/Frontend/Analyses.def b/include/clang/Frontend/Analyses.def index 287c67e..aaa3920 100644 --- a/include/clang/Frontend/Analyses.def +++ b/include/clang/Frontend/Analyses.def @@ -15,22 +15,21 @@ #define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) #endif -ANALYSIS(CFGDump, "cfg-dump", +ANALYSIS(CFGDump, "cfg-dump", "Display Control-Flow Graphs", Code) -ANALYSIS(CFGView, "cfg-view", +ANALYSIS(CFGView, "cfg-view", "View Control-Flow Graphs using GraphViz", Code) ANALYSIS(DisplayLiveVariables, "dump-live-variables", "Print results of live variable analysis", Code) ANALYSIS(SecuritySyntacticChecks, "analyzer-check-security-syntactic", - "Perform quick security checks that require no data flow", - Code) + "Perform quick security checks that require no data flow", Code) ANALYSIS(LLVMConventionChecker, "analyzer-check-llvm-conventions", - "Check code for LLVM codebase conventions (domain-specific)", - TranslationUnit) + "Check code for LLVM codebase conventions (domain-specific)", + TranslationUnit) ANALYSIS(WarnDeadStores, "analyzer-check-dead-stores", "Warn about stores to dead variables", Code) @@ -39,15 +38,15 @@ ANALYSIS(WarnUninitVals, "warn-uninit-values", "Warn about uses of uninitialized variables", Code) ANALYSIS(WarnObjCMethSigs, "analyzer-check-objc-methodsigs", - "Warn about Objective-C method signatures with type incompatibilities", - ObjCImplementation) + "Warn about Objective-C method signatures with type incompatibilities", + ObjCImplementation) ANALYSIS(WarnObjCDealloc, "analyzer-check-objc-missing-dealloc", - "Warn about Objective-C classes that lack a correct implementation of -dealloc", - ObjCImplementation) +"Warn about Objective-C classes that lack a correct implementation of -dealloc", + ObjCImplementation) ANALYSIS(WarnObjCUnusedIvars, "analyzer-check-objc-unused-ivars", - "Warn about private ivars that are never used", ObjCImplementation) + "Warn about private ivars that are never used", ObjCImplementation) ANALYSIS(ObjCMemChecker, "analyzer-check-objc-mem", "Run the [Core] Foundation reference count checker", Code) @@ -55,10 +54,6 @@ ANALYSIS(ObjCMemChecker, "analyzer-check-objc-mem", ANALYSIS(WarnSizeofPointer, "warn-sizeof-pointer", "Warn about unintended use of sizeof() on pointer expressions", Code) -ANALYSIS(InlineCall, "inline-call", - "Experimental transfer function inling callees when its definition" - " is available.", TranslationUnit) - #ifndef ANALYSIS_STORE #define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) #endif diff --git a/include/clang/Frontend/AnalysisConsumer.h b/include/clang/Frontend/AnalysisConsumer.h index f55e5dc..3341bb0 100644 --- a/include/clang/Frontend/AnalysisConsumer.h +++ b/include/clang/Frontend/AnalysisConsumer.h @@ -60,6 +60,7 @@ public: AnalysisConstraints AnalysisConstraintsOpt; AnalysisDiagClients AnalysisDiagOpt; std::string AnalyzeSpecificFunction; + unsigned MaxNodes; unsigned AnalyzeAll : 1; unsigned AnalyzerDisplayProgress : 1; unsigned AnalyzeNestedBlocks : 1; diff --git a/include/clang/Frontend/DiagnosticOptions.h b/include/clang/Frontend/DiagnosticOptions.h index b37c180..797cb34 100644 --- a/include/clang/Frontend/DiagnosticOptions.h +++ b/include/clang/Frontend/DiagnosticOptions.h @@ -38,6 +38,9 @@ public: /// binary serialization mechanism, to be /// deserialized by, e.g., the CIndex library. + unsigned ErrorLimit; /// Limit # errors emitted. + unsigned TemplateBacktraceLimit; /// Limit depth of instantiation backtrace. + /// The distance between tab stops. unsigned TabStop; enum { DefaultTabStop = 8, MaxTabStop = 100 }; @@ -70,6 +73,8 @@ public: ShowSourceRanges = 0; VerifyDiagnostics = 0; BinaryOutput = 0; + ErrorLimit = 0; + TemplateBacktraceLimit = 0; } }; diff --git a/include/clang/Frontend/FixItRewriter.h b/include/clang/Frontend/FixItRewriter.h index fac87af..b432d74 100644 --- a/include/clang/Frontend/FixItRewriter.h +++ b/include/clang/Frontend/FixItRewriter.h @@ -16,23 +16,24 @@ #define LLVM_CLANG_FRONTEND_FIX_IT_REWRITER_H #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Rewrite/Rewriter.h" #include "llvm/ADT/SmallVector.h" +namespace llvm { class raw_ostream; } + namespace clang { class SourceManager; class FileEntry; -/// \brief Stores a source location in the form that it shows up on -/// the Clang command line, e.g., file:line:column. -/// -/// FIXME: Would prefer to use real SourceLocations, but I don't see a -/// good way to resolve them during parsing. -struct RequestedSourceLocation { - const FileEntry *File; - unsigned Line; - unsigned Column; +class FixItPathRewriter { +public: + virtual ~FixItPathRewriter(); + + /// \brief This file is about to be rewritten. Return the name of the file + /// that is okay to write to. + virtual std::string RewriteFilename(const std::string &Filename) = 0; }; class FixItRewriter : public DiagnosticClient { @@ -47,38 +48,46 @@ class FixItRewriter : public DiagnosticClient { /// of error messages. DiagnosticClient *Client; + /// \brief Turn an input path into an output path. NULL implies overwriting + /// the original. + FixItPathRewriter *PathRewriter; + /// \brief The number of rewriter failures. unsigned NumFailures; - /// \brief Locations at which we should perform fix-its. - /// - /// When empty, perform fix-it modifications everywhere. - llvm::SmallVector<RequestedSourceLocation, 4> FixItLocations; - public: + typedef Rewriter::buffer_iterator iterator; + /// \brief Initialize a new fix-it rewriter. FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr, - const LangOptions &LangOpts); + const LangOptions &LangOpts, FixItPathRewriter *PathRewriter); /// \brief Destroy the fix-it rewriter. ~FixItRewriter(); - /// \brief Add a location where fix-it modifications should be - /// performed. - void addFixItLocation(RequestedSourceLocation Loc) { - FixItLocations.push_back(Loc); + /// \brief Check whether there are modifications for a given file. + bool IsModified(FileID ID) const { + return Rewrite.getRewriteBufferFor(ID) != NULL; } - /// \brief Write the modified source file. + // Iteration over files with changes. + iterator buffer_begin() { return Rewrite.buffer_begin(); } + iterator buffer_end() { return Rewrite.buffer_end(); } + + /// \brief Write a single modified source file. + /// + /// \returns true if there was an error, false otherwise. + bool WriteFixedFile(FileID ID, llvm::raw_ostream &OS); + + /// \brief Write the modified source files. /// /// \returns true if there was an error, false otherwise. - bool WriteFixedFile(const std::string &InFileName, - const std::string &OutFileName = std::string()); + bool WriteFixedFiles(); /// IncludeInDiagnosticCounts - This method (whose default implementation - /// returns true) indicates whether the diagnostics handled by this - /// DiagnosticClient should be included in the number of diagnostics - /// reported by Diagnostic. + /// returns true) indicates whether the diagnostics handled by this + /// DiagnosticClient should be included in the number of diagnostics + /// reported by Diagnostic. virtual bool IncludeInDiagnosticCounts() const; /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h index a7b6aa7..3ddd77d 100644 --- a/include/clang/Frontend/FrontendActions.h +++ b/include/clang/Frontend/FrontendActions.h @@ -16,6 +16,7 @@ namespace clang { class FixItRewriter; +class FixItPathRewriter; //===----------------------------------------------------------------------===// // Custom Consumer Actions @@ -73,15 +74,10 @@ protected: llvm::StringRef InFile); }; -class DumpRecordAction : public ASTFrontendAction { -protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - llvm::StringRef InFile); -}; - class FixItAction : public ASTFrontendAction { private: llvm::OwningPtr<FixItRewriter> Rewriter; + llvm::OwningPtr<FixItPathRewriter> PathRewriter; protected: diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index ee3811a..60512ed 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -24,7 +24,6 @@ namespace frontend { ASTPrintXML, ///< Parse ASTs and print them in XML. ASTView, ///< Parse ASTs and view them in Graphviz. DumpRawTokens, ///< Dump out raw tokens. - DumpRecordLayouts, ///< Dump record layout information. DumpTokens, ///< Dump out preprocessed tokens. EmitAssembly, ///< Emit a .s file. EmitBC, ///< Emit a .bc file. @@ -93,8 +92,8 @@ public: /// If given, the name for a C++ class to view the inheritance of. std::string ViewClassInheritance; - /// A list of locations to apply fix-its at. - std::vector<ParsedSourceLocation> FixItLocations; + /// If given, the new suffix for fix-it rewritten files. + std::string FixItSuffix; /// If given, enable code completion at the provided location. ParsedSourceLocation CodeCompletionAt; @@ -111,6 +110,10 @@ public: /// \brief The list of AST files to merge. std::vector<std::string> ASTMergeFiles; + /// \brief A list of arguments to forward to LLVM's option processing; this + /// should only be used for debugging and experimental features. + std::vector<std::string> LLVMArgs; + public: FrontendOptions() { DebugCodeCompletionPrinter = 1; diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index f975c49..1640afb 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -453,7 +453,9 @@ namespace clang { /// \brief Block extedned descriptor type for Blocks CodeGen SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR = 13, /// \brief Objective-C "SEL" redefinition type - SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 14 + SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 14, + /// \brief NSConstantString type + SPECIAL_TYPE_NS_CONSTANT_STRING = 15 }; /// \brief Record codes for each kind of declaration. @@ -601,6 +603,8 @@ namespace clang { EXPR_PAREN, /// \brief A UnaryOperator record. EXPR_UNARY_OPERATOR, + /// \brief An OffsetOfExpr record. + EXPR_OFFSETOF, /// \brief A SizefAlignOfExpr record. EXPR_SIZEOF_ALIGN_OF, /// \brief An ArraySubscriptExpr record. diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index 73c1bf4..c235230 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -436,7 +436,7 @@ private: std::deque<PendingIdentifierInfo> PendingIdentifierInfos; /// \brief FIXME: document! - llvm::SmallVector<uint64_t, 4> SpecialTypes; + llvm::SmallVector<uint64_t, 16> SpecialTypes; /// \brief Contains declarations and definitions that will be /// "interesting" to the ASTConsumer, when we get that AST consumer. @@ -688,6 +688,9 @@ public: Selector DecodeSelector(unsigned Idx); + virtual Selector GetSelector(uint32_t ID); + virtual uint32_t GetNumKnownSelectors(); + Selector GetSelector(const RecordData &Record, unsigned &Idx) { return DecodeSelector(Record[Idx++]); } diff --git a/include/clang/Frontend/StmtXML.def b/include/clang/Frontend/StmtXML.def index 2f0da9e..f63761a 100644 --- a/include/clang/Frontend/StmtXML.def +++ b/include/clang/Frontend/StmtXML.def @@ -254,7 +254,7 @@ NODE_XML(UnaryOperator, "UnaryOperator") // op(expr) or (expr)op ENUM_XML(UnaryOperator::Real, "__real") ENUM_XML(UnaryOperator::Imag, "__imag") ENUM_XML(UnaryOperator::Extension, "__extension__") - ENUM_XML(UnaryOperator::OffsetOf, "__builtin_offsetof") + ENUM_XML(UnaryOperator::OffsetOf, "__builtin_offsetof") END_ENUM_XML SUB_NODE_XML(Expr) // expr END_NODE_XML @@ -311,6 +311,13 @@ NODE_XML(ConditionalOperator, "ConditionalOperator") // expr1 ? expr2 : expr3 SUB_NODE_XML(Expr) // expr3 END_NODE_XML +NODE_XML(OffsetOfExpr, "OffsetOfExpr") // offsetof(basetype, components) + ATTRIBUTE_FILE_LOCATION_XML + TYPE_ATTRIBUTE_XML(getTypeSourceInfo()->getType()) + ATTRIBUTE_XML(getNumComponents(), "num_components") + SUB_NODE_SEQUENCE_XML(OffsetOfExpr::OffsetOfNode) +END_NODE_XML + NODE_XML(SizeOfAlignOfExpr, "SizeOfAlignOfExpr") // sizeof(expr) or alignof(expr) ATTRIBUTE_FILE_LOCATION_XML TYPE_ATTRIBUTE_XML(getType()) diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h index 157876b..3367136 100644 --- a/include/clang/Frontend/TextDiagnosticPrinter.h +++ b/include/clang/Frontend/TextDiagnosticPrinter.h @@ -68,7 +68,7 @@ public: void EmitCaretDiagnostic(SourceLocation Loc, SourceRange *Ranges, unsigned NumRanges, - SourceManager &SM, + const SourceManager &SM, const FixItHint *Hints, unsigned NumHints, unsigned Columns); diff --git a/include/clang/Frontend/VerifyDiagnosticsClient.h b/include/clang/Frontend/VerifyDiagnosticsClient.h index 08adbb0..6f45e49 100644 --- a/include/clang/Frontend/VerifyDiagnosticsClient.h +++ b/include/clang/Frontend/VerifyDiagnosticsClient.h @@ -25,7 +25,10 @@ class TextDiagnosticBuffer; /// USING THE DIAGNOSTIC CHECKER: /// /// Indicating that a line expects an error or a warning is simple. Put a -/// comment on the line that has the diagnostic, use "expected-{error,warning}" +/// comment on the line that has the diagnostic, use: +/// +/// expected-{error,warning,note} +/// /// to tag if it's an expected error or warning, and place the expected text /// between {{ and }} markers. The full text doesn't have to be included, only /// enough to ensure that the correct diagnostic was emitted. @@ -45,6 +48,20 @@ class TextDiagnosticBuffer; /// /// void f(); // expected-note 2 {{previous declaration is here}} /// +/// Regex matching mode may be selected by appending '-re' to type. Example: +/// +/// expected-error-re +/// +/// Examples matching error: "variable has incomplete type 'struct s'" +/// +/// // expected-error {{variable has incomplete type 'struct s'}} +/// // expected-error {{variable has incomplete type}} +/// +/// // expected-error-re {{variable has has type 'struct .'}} +/// // expected-error-re {{variable has has type 'struct .*'}} +/// // expected-error-re {{variable has has type 'struct (.*)'}} +/// // expected-error-re {{variable has has type 'struct[[:space:]](.*)'}} +/// class VerifyDiagnosticsClient : public DiagnosticClient { public: Diagnostic &Diags; diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h index e891e94..d74124e 100644 --- a/include/clang/Lex/PPCallbacks.h +++ b/include/clang/Lex/PPCallbacks.h @@ -44,6 +44,14 @@ public: SrcMgr::CharacteristicKind FileType) { } + /// FileSkipped - This callback is invoked whenever a source file is + /// skipped as the result of header guard optimization. ParentFile + /// is the file that #includes the skipped file. FilenameTok is the + /// token in ParentFile that indicates the skipped file. + virtual void FileSkipped(const FileEntry &ParentFile, + const Token &FilenameTok, + SrcMgr::CharacteristicKind FileType) { + } /// EndOfMainFile - This callback is invoked when the end of the main file is /// reach, no subsequent callbacks will be made. @@ -96,6 +104,13 @@ public: Second->FileChanged(Loc, Reason, FileType); } + virtual void FileSkipped(const FileEntry &ParentFile, + const Token &FilenameTok, + SrcMgr::CharacteristicKind FileType) { + First->FileSkipped(ParentFile, FilenameTok, FileType); + Second->FileSkipped(ParentFile, FilenameTok, FileType); + } + virtual void EndOfMainFile() { First->EndOfMainFile(); Second->EndOfMainFile(); diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 312a760..20d9fc5 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -366,17 +366,17 @@ public: /// EnterMainSourceFile - Enter the specified FileID as the main source file, /// which implicitly adds the builtin defines etc. - bool EnterMainSourceFile(); + void EnterMainSourceFile(); /// EndSourceFile - Inform the preprocessor callbacks that processing is /// complete. void EndSourceFile(); /// EnterSourceFile - Add a source file to the top of the include stack and - /// start lexing tokens from it instead of the current buffer. Return true - /// and fill in ErrorStr with the error information on failure. - bool EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir, - std::string &ErrorStr); + /// start lexing tokens from it instead of the current buffer. Emit an error + /// and don't enter the file on error. + void EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir, + SourceLocation Loc); /// EnterMacro - Add a Macro to the top of the include stack and start lexing /// tokens from it instead of the current buffer. Args specifies the diff --git a/include/clang/Lex/TokenConcatenation.h b/include/clang/Lex/TokenConcatenation.h index d759e47..094990a 100644 --- a/include/clang/Lex/TokenConcatenation.h +++ b/include/clang/Lex/TokenConcatenation.h @@ -58,7 +58,9 @@ namespace clang { public: TokenConcatenation(Preprocessor &PP); - bool AvoidConcat(const Token &PrevTok, const Token &Tok) const; + bool AvoidConcat(const Token &PrevPrevTok, + const Token &PrevTok, + const Token &Tok) const; private: /// StartsWithL - Return true if the spelling of this token starts with 'L'. diff --git a/include/clang/Makefile b/include/clang/Makefile index 624292a..d76e0a9 100644 --- a/include/clang/Makefile +++ b/include/clang/Makefile @@ -2,3 +2,30 @@ LEVEL = ../../../.. DIRS := Basic Driver include $(LEVEL)/Makefile.common + +install-local:: + $(Echo) Installing Clang include files + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_includedir) + $(Verb) if test -d "$(PROJ_SRC_ROOT)/tools/clang/include/clang" ; then \ + cd $(PROJ_SRC_ROOT)/tools/clang/include && \ + for hdr in `find clang -type f '!' '(' -name '*~' \ + -o -name '.#*' -o -name '*.in' -o -name '*.txt' \ + -o -name 'Makefile' -o -name '*.td' ')' -print \ + | grep -v CVS | grep -v .svn | grep -v .dir` ; do \ + instdir=$(DESTDIR)`dirname "$(PROJ_includedir)/$$hdr"` ; \ + if test \! -d "$$instdir" ; then \ + $(EchoCmd) Making install directory $$instdir ; \ + $(MKDIR) $$instdir ;\ + fi ; \ + $(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \ + done ; \ + fi +ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT)) + $(Verb) if test -d "$(PROJ_OBJ_ROOT)/tools/clang/include/clang" ; then \ + cd $(PROJ_OBJ_ROOT)/tools/clang/include && \ + for hdr in `find clang -type f '!' '(' -name 'Makefile' ')' -print \ + | grep -v CVS | grep -v .tmp | grep -v .dir` ; do \ + $(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \ + done ; \ + fi +endif diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 59cc0d2..3d68d80 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -205,7 +205,7 @@ public: /// \returns the type referred to by this identifier, or NULL if the type /// does not name an identifier. virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc, - Scope *S, const CXXScopeSpec *SS = 0, + Scope *S, CXXScopeSpec *SS = 0, bool isClassName = false, TypeTy *ObjectType = 0) = 0; @@ -243,7 +243,7 @@ public: virtual bool DiagnoseUnknownTypeName(const IdentifierInfo &II, SourceLocation IILoc, Scope *S, - const CXXScopeSpec *SS, + CXXScopeSpec *SS, TypeTy *&SuggestedType) { return false; } @@ -281,7 +281,7 @@ public: /// /// \returns the kind of template that this name refers to. virtual TemplateNameKind isTemplateName(Scope *S, - const CXXScopeSpec &SS, + CXXScopeSpec &SS, UnqualifiedId &Name, TypeTy *ObjectType, bool EnteringContext, @@ -329,7 +329,7 @@ public: /// This actual is used in the parsing of pseudo-destructor names to /// distinguish a nested-name-specifier and a "type-name ::" when we /// see the token sequence "X :: ~". - virtual bool isNonTypeNestedNameSpecifier(Scope *S, const CXXScopeSpec &SS, + virtual bool isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS, SourceLocation IdLoc, IdentifierInfo &II, TypeTy *ObjectType) { @@ -371,7 +371,7 @@ public: /// /// \returns a CXXScopeTy* object representing the C++ scope. virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S, - const CXXScopeSpec &SS, + CXXScopeSpec &SS, SourceLocation IdLoc, SourceLocation CCLoc, IdentifierInfo &II, @@ -387,7 +387,7 @@ public: /// /// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier. virtual bool IsInvalidUnlessNestedName(Scope *S, - const CXXScopeSpec &SS, + CXXScopeSpec &SS, IdentifierInfo &II, TypeTy *ObjectType, bool EnteringContext) { @@ -428,7 +428,7 @@ public: /// ActOnCXXExitDeclaratorScope is called. /// The 'SS' should be a non-empty valid CXXScopeSpec. /// \returns true if an error occurred, false otherwise. - virtual bool ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { + virtual bool ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS) { return false; } @@ -468,7 +468,11 @@ public: virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D) { return DeclPtrTy(); } - virtual void ActOnObjCCatchParam(DeclPtrTy D) { + + /// \brief Parsed an exception object declaration within an Objective-C + /// @catch statement. + virtual DeclPtrTy ActOnObjCExceptionDecl(Scope *S, Declarator &D) { + return DeclPtrTy(); } /// AddInitializerToDecl - This action is called immediately after @@ -576,8 +580,7 @@ public: virtual DeclPtrTy ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc, SourceLocation LangLoc, - const char *Lang, - unsigned StrSize, + llvm::StringRef Lang, SourceLocation LBraceLoc) { return DeclPtrTy(); } @@ -655,7 +658,7 @@ public: /// /// \returns the declaration to which this tag refers. virtual DeclPtrTy ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, - SourceLocation KWLoc, const CXXScopeSpec &SS, + SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr, AccessSpecifier AS, MultiTemplateParamsArg TemplateParameterLists, @@ -938,20 +941,46 @@ public: } // Objective-c statements + + /// \brief Parsed an Objective-C @catch statement. + /// + /// \param AtLoc The location of the '@' starting the '@catch'. + /// + /// \param RParen The location of the right parentheses ')' after the + /// exception variable. + /// + /// \param Parm The variable that will catch the exception. Will be NULL if + /// this is a @catch(...) block. + /// + /// \param Body The body of the @catch block. virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen, - DeclPtrTy Parm, StmtArg Body, - StmtArg CatchList) { + DeclPtrTy Parm, StmtArg Body) { return StmtEmpty(); } + /// \brief Parsed an Objective-C @finally statement. + /// + /// \param AtLoc The location of the '@' starting the '@finally'. + /// + /// \param Body The body of the @finally block. virtual OwningStmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, StmtArg Body) { return StmtEmpty(); } + /// \brief Parsed an Objective-C @try-@catch-@finally statement. + /// + /// \param AtLoc The location of the '@' starting '@try'. + /// + /// \param Try The body of the '@try' statement. + /// + /// \param CatchStmts The @catch statements. + /// + /// \param Finally The @finally statement. virtual OwningStmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, - StmtArg Try, StmtArg Catch, + StmtArg Try, + MultiStmtArg CatchStmts, StmtArg Finally) { return StmtEmpty(); } @@ -1049,7 +1078,7 @@ public: /// id-expression or identifier was an ampersand ('&'), indicating that /// we will be taking the address of this expression. virtual OwningExprResult ActOnIdExpression(Scope *S, - const CXXScopeSpec &SS, + CXXScopeSpec &SS, UnqualifiedId &Name, bool HasTrailingLParen, bool IsAddressOfOperand) { @@ -1127,7 +1156,7 @@ public: virtual OwningExprResult ActOnMemberAccessExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, tok::TokenKind OpKind, - const CXXScopeSpec &SS, + CXXScopeSpec &SS, UnqualifiedId &Member, DeclPtrTy ObjCImpDecl, bool HasTrailingLParen) { @@ -1315,7 +1344,7 @@ public: virtual DeclPtrTy ActOnUsingDirective(Scope *CurScope, SourceLocation UsingLoc, SourceLocation NamespcLoc, - const CXXScopeSpec &SS, + CXXScopeSpec &SS, SourceLocation IdentLoc, IdentifierInfo *NamespcName, AttributeList *AttrList); @@ -1326,7 +1355,7 @@ public: SourceLocation NamespaceLoc, SourceLocation AliasLoc, IdentifierInfo *Alias, - const CXXScopeSpec &SS, + CXXScopeSpec &SS, SourceLocation IdentLoc, IdentifierInfo *Ident) { return DeclPtrTy(); @@ -1372,7 +1401,7 @@ public: AccessSpecifier AS, bool HasUsingKeyword, SourceLocation UsingLoc, - const CXXScopeSpec &SS, + CXXScopeSpec &SS, UnqualifiedId &Name, AttributeList *AttrList, bool IsTypeName, @@ -1501,7 +1530,7 @@ public: /// \returns the type being destructed. virtual TypeTy *getDestructorName(SourceLocation TildeLoc, IdentifierInfo &II, SourceLocation NameLoc, - Scope *S, const CXXScopeSpec &SS, + Scope *S, CXXScopeSpec &SS, TypeTy *ObjectType, bool EnteringContext) { return getTypeName(II, NameLoc, S, &SS, false, ObjectType); @@ -1683,7 +1712,7 @@ public: virtual OwningExprResult ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, tok::TokenKind OpKind, - const CXXScopeSpec &SS, + CXXScopeSpec &SS, UnqualifiedId &FirstTypeName, SourceLocation CCLoc, SourceLocation TildeLoc, @@ -1729,7 +1758,7 @@ public: virtual MemInitResult ActOnMemInitializer(DeclPtrTy ConstructorDecl, Scope *S, - const CXXScopeSpec &SS, + CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, TypeTy *TemplateTypeTy, SourceLocation IdLoc, @@ -1939,7 +1968,7 @@ public: /// \param EnteringContext whether we are entering the context of this /// template. virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc, - const CXXScopeSpec &SS, + CXXScopeSpec &SS, UnqualifiedId &Name, TypeTy *ObjectType, bool EnteringContext) { @@ -1995,7 +2024,7 @@ public: virtual DeclResult ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, - const CXXScopeSpec &SS, + CXXScopeSpec &SS, TemplateTy Template, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, @@ -2133,7 +2162,7 @@ public: SourceLocation TemplateLoc, unsigned TagSpec, SourceLocation KWLoc, - const CXXScopeSpec &SS, + CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr) { @@ -2306,7 +2335,7 @@ public: TypeTy *ReturnType, // the method return type. Selector Sel, // a unique name for the method. ObjCArgInfo *ArgInfo, // ArgInfo: Has 'Sel.getNumArgs()' entries. - llvm::SmallVectorImpl<Declarator> &Cdecls, // c-style args + DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args AttributeList *MethodAttrList, // optional // tok::objc_not_keyword, tok::objc_optional, tok::objc_required tok::ObjCKeywordKind impKind, @@ -2336,36 +2365,118 @@ public: return DeclPtrTy(); } - virtual OwningExprResult ActOnClassPropertyRefExpr( - IdentifierInfo &receiverName, - IdentifierInfo &propertyName, - SourceLocation &receiverNameLoc, - SourceLocation &propertyNameLoc) { + virtual OwningExprResult + ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, + IdentifierInfo &propertyName, + SourceLocation receiverNameLoc, + SourceLocation propertyNameLoc) { return ExprEmpty(); } - // ActOnClassMessage - used for both unary and keyword messages. - // ArgExprs is optional - if it is present, the number of expressions - // is obtained from NumArgs. - virtual ExprResult ActOnClassMessage( - Scope *S, - IdentifierInfo *receivingClassName, - Selector Sel, - SourceLocation lbrac, SourceLocation receiverLoc, - SourceLocation selectorLoc, - SourceLocation rbrac, - ExprTy **ArgExprs, unsigned NumArgs) { - return ExprResult(); - } - // ActOnInstanceMessage - used for both unary and keyword messages. - // ArgExprs is optional - if it is present, the number of expressions - // is obtained from NumArgs. - virtual ExprResult ActOnInstanceMessage( - ExprTy *receiver, Selector Sel, - SourceLocation lbrac, SourceLocation selectorLoc, SourceLocation rbrac, - ExprTy **ArgExprs, unsigned NumArgs) { - return ExprResult(); + /// \brief Describes the kind of message expression indicated by a message + /// send that starts with an identifier. + enum ObjCMessageKind { + /// \brief The message is sent to 'super'. + ObjCSuperMessage, + /// \brief The message is an instance message. + ObjCInstanceMessage, + /// \brief The message is a class message, and the identifier is a type + /// name. + ObjCClassMessage + }; + + /// \brief Determine the kind of Objective-C message send that we will be + /// performing based on the identifier given. + /// + /// This action determines how a message send that starts with [ + /// identifier (followed by another identifier) will be parsed, + /// e.g., as a class message, instance message, super message. The + /// result depends on the meaning of the given identifier. If the + /// identifier is unknown, the action should indicate that the + /// message is an instance message. + /// + /// By default, this routine applies syntactic disambiguation and uses + /// \c getTypeName() to determine whether the identifier refers to a type. + /// However, \c Action subclasses may override this routine to improve + /// error recovery. + /// + /// \param S The scope in which the message send occurs. + /// + /// \param Name The identifier following the '['. + /// + /// \param NameLoc The location of the identifier. + /// + /// \param IsSuper Whether the name is the pseudo-keyword "super". + /// + /// \param HasTrailingDot Whether the name is followed by a period. + /// + /// \param ReceiverType If this routine returns \c ObjCClassMessage, + /// this argument will be set to the receiver type. + /// + /// \returns The kind of message send. + virtual ObjCMessageKind getObjCMessageKind(Scope *S, + IdentifierInfo *Name, + SourceLocation NameLoc, + bool IsSuper, + bool HasTrailingDot, + TypeTy *&ReceiverType); + + /// \brief Parsed a message send to 'super'. + /// + /// \param S The scope in which the message send occurs. + /// \param SuperLoc The location of the 'super' keyword. + /// \param Sel The selector to which the message is being sent. + /// \param LBracLoc The location of the opening square bracket ']'. + /// \param SelectorLoc The location of the first identifier in the selector. + /// \param RBrac The location of the closing square bracket ']'. + /// \param Args The message arguments. + virtual OwningExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args) { + return OwningExprResult(*this); + } + + /// \brief Parsed a message send to a class. + /// + /// \param S The scope in which the message send occurs. + /// \param Receiver The type of the class receiving the message. + /// \param Sel The selector to which the message is being sent. + /// \param LBracLoc The location of the opening square bracket ']'. + /// \param SelectorLoc The location of the first identifier in the selector. + /// \param RBrac The location of the closing square bracket ']'. + /// \param Args The message arguments. + virtual OwningExprResult ActOnClassMessage(Scope *S, + TypeTy *Receiver, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args) { + return OwningExprResult(*this); + } + + /// \brief Parsed a message send to an object instance. + /// + /// \param S The scope in which the message send occurs. + /// \param Receiver The expression that computes the receiver object. + /// \param Sel The selector to which the message is being sent. + /// \param LBracLoc The location of the opening square bracket ']'. + /// \param SelectorLoc The location of the first identifier in the selector. + /// \param RBrac The location of the closing square bracket ']'. + /// \param Args The message arguments. + virtual OwningExprResult ActOnInstanceMessage(Scope *S, + ExprArg Receiver, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args) { + return OwningExprResult(*this); } + virtual DeclPtrTy ActOnForwardClassDeclaration( SourceLocation AtClassLoc, IdentifierInfo **IdentList, @@ -2581,7 +2692,7 @@ public: /// /// \parame EnteringContext whether we're entering the context of this /// scope specifier. - virtual void CodeCompleteQualifiedId(Scope *S, const CXXScopeSpec &SS, + virtual void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext) { } /// \brief Code completion for a C++ "using" declaration or directive. @@ -2692,21 +2803,33 @@ public: unsigned NumMethods) { } + /// \brief Code completion for an ObjC message expression that sends + /// a message to the superclass. + /// + /// This code completion action is invoked when the code-completion token is + /// found after the class name and after each argument. + /// + /// \param S The scope in which the message expression occurs. + /// \param SuperLoc The location of the 'super' keyword. + /// \param SelIdents The identifiers that describe the selector (thus far). + /// \param NumSelIdents The number of identifiers in \p SelIdents. + virtual void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, + IdentifierInfo **SelIdents, + unsigned NumSelIdents) { } + /// \brief Code completion for an ObjC message expression that refers to /// a class method. /// /// This code completion action is invoked when the code-completion token is /// found after the class name and after each argument. /// - /// \param S the scope in which the message expression occurs. - /// \param FName the factory name. - /// \param FNameLoc the source location of the factory name. - /// \param SelIdents the identifiers that describe the selector (thus far). - /// \param NumSelIdents the number of identifiers in \p SelIdents. - virtual void CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName, - SourceLocation FNameLoc, + /// \param S The scope in which the message expression occurs. + /// \param Receiver The type of the class that is receiving a message. + /// \param SelIdents The identifiers that describe the selector (thus far). + /// \param NumSelIdents The number of identifiers in \p SelIdents. + virtual void CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver, IdentifierInfo **SelIdents, - unsigned NumSelIdents){ } + unsigned NumSelIdents) { } /// \brief Code completion for an ObjC message expression that refers to /// an instance method. @@ -2752,7 +2875,8 @@ public: /// /// \param ClassName the name of the class being defined. virtual void CodeCompleteObjCSuperclass(Scope *S, - IdentifierInfo *ClassName) { + IdentifierInfo *ClassName, + SourceLocation ClassNameLoc) { } /// \brief Code completion for an Objective-C implementation, after the @@ -2765,7 +2889,8 @@ public: /// This code completion action is invoked after the '(' that indicates /// a category name within an Objective-C interface declaration. virtual void CodeCompleteObjCInterfaceCategory(Scope *S, - IdentifierInfo *ClassName) { + IdentifierInfo *ClassName, + SourceLocation ClassNameLoc) { } /// \brief Code completion for the category name in an Objective-C category @@ -2774,7 +2899,8 @@ public: /// This code completion action is invoked after the '(' that indicates /// the category name within an Objective-C category implementation. virtual void CodeCompleteObjCImplementationCategory(Scope *S, - IdentifierInfo *ClassName) { + IdentifierInfo *ClassName, + SourceLocation ClassNameLoc) { } /// \brief Code completion for the property names when defining an @@ -2795,6 +2921,32 @@ public: IdentifierInfo *PropertyName, DeclPtrTy ObjCImpDecl) { } + + /// \brief Code completion for an Objective-C method declaration or + /// definition, which may occur within an interface, category, + /// extension, protocol, or implementation thereof (where applicable). + /// + /// This code completion action is invoked after the "-" or "+" that + /// starts a method declaration or definition, and after the return + /// type such a declaration (e.g., "- (id)"). + /// + /// \param S The scope in which the completion occurs. + /// + /// \param IsInstanceMethod Whether this is an instance method + /// (introduced with '-'); otherwise, it's a class method + /// (introduced with '+'). + /// + /// \param ReturnType If non-NULL, the specified return type of the method + /// being declared or defined. + /// + /// \param IDecl The interface, category, protocol, or + /// implementation, or category implementation in which this method + /// declaration or definition occurs. + virtual void CodeCompleteObjCMethodDecl(Scope *S, + bool IsInstanceMethod, + TypeTy *ReturnType, + DeclPtrTy IDecl) { + } //@} }; @@ -2837,7 +2989,7 @@ public: /// \returns the type referred to by this identifier, or NULL if the type /// does not name an identifier. virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc, - Scope *S, const CXXScopeSpec *SS, + Scope *S, CXXScopeSpec *SS, bool isClassName = false, TypeTy *ObjectType = 0); @@ -2847,7 +2999,7 @@ public: const CXXScopeSpec *SS); virtual TemplateNameKind isTemplateName(Scope *S, - const CXXScopeSpec &SS, + CXXScopeSpec &SS, UnqualifiedId &Name, TypeTy *ObjectType, bool EnteringContext, diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h index 37acab9..12512f3 100644 --- a/include/clang/Parse/AttributeList.h +++ b/include/clang/Parse/AttributeList.h @@ -41,6 +41,7 @@ class AttributeList { unsigned NumArgs; AttributeList *Next; bool DeclspecAttribute, CXX0XAttribute; + mutable bool Invalid; /// True if already diagnosed as invalid. AttributeList(const AttributeList &); // DO NOT IMPLEMENT void operator=(const AttributeList &); // DO NOT IMPLEMENT public: @@ -128,6 +129,9 @@ public: bool isDeclspecAttribute() const { return DeclspecAttribute; } bool isCXX0XAttribute() const { return CXX0XAttribute; } + bool isInvalid() const { return Invalid; } + void setInvalid(bool b = true) const { Invalid = b; } + Kind getKind() const { return getKind(getName()); } static Kind getKind(const IdentifierInfo *Name); diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index f6f1eb9..9c19a67 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -27,9 +27,18 @@ namespace clang { class Preprocessor; class Declarator; struct TemplateIdAnnotation; - + /// CXXScopeSpec - Represents a C++ nested-name-specifier or a global scope -/// specifier. +/// specifier. These can be in 3 states: +/// 1) Not present, identified by isEmpty() +/// 2) Present, identified by isNotEmpty() +/// 2.a) Valid, idenified by isValid() +/// 2.b) Invalid, identified by isInvalid(). +/// +/// isSet() is deprecated because it mostly corresponded to "valid" but was +/// often used as if it meant "present". +/// +/// The actual scope is described by getScopeRep(). class CXXScopeSpec { SourceRange Range; void *ScopeRep; @@ -47,13 +56,18 @@ public: ActionBase::CXXScopeTy *getScopeRep() const { return ScopeRep; } void setScopeRep(ActionBase::CXXScopeTy *S) { ScopeRep = S; } + /// No scope specifier. bool isEmpty() const { return !Range.isValid(); } + /// A scope specifier is present, but may be valid or invalid. bool isNotEmpty() const { return !isEmpty(); } - /// isInvalid - An error occured during parsing of the scope specifier. + /// An error occured during parsing of the scope specifier. bool isInvalid() const { return isNotEmpty() && ScopeRep == 0; } + /// A scope specifier is present, and it refers to a real scope. + bool isValid() const { return isNotEmpty() && ScopeRep != 0; } - /// isSet - A scope specifier was resolved to a valid C++ scope. + /// Deprecated. Some call sites intend isNotEmpty() while others intend + /// isValid(). bool isSet() const { return ScopeRep != 0; } void clear() { @@ -68,8 +82,9 @@ public: class DeclSpec { public: // storage-class-specifier + // Note: The order of these enumerators is important for diagnostics. enum SCS { - SCS_unspecified, + SCS_unspecified = 0, SCS_typedef, SCS_extern, SCS_static, @@ -171,6 +186,8 @@ private: // constexpr-specifier bool Constexpr_specified : 1; + /*SCS*/unsigned StorageClassSpecAsWritten : 3; + /// TypeRep - This contains action-specific information about a specific TST. /// For example, for a typedef or struct, it might contain the declaration for /// these. @@ -203,6 +220,9 @@ private: WrittenBuiltinSpecs writtenBS; void SaveWrittenBuiltinSpecs(); + void SaveStorageSpecifierAsWritten() { + StorageClassSpecAsWritten = StorageClassSpec; + } DeclSpec(const DeclSpec&); // DO NOT IMPLEMENT void operator=(const DeclSpec&); // DO NOT IMPLEMENT @@ -224,6 +244,7 @@ public: FS_explicit_specified(false), Friend_specified(false), Constexpr_specified(false), + StorageClassSpecAsWritten(SCS_unspecified), TypeRep(0), AttrList(0), ProtocolQualifiers(0), @@ -321,6 +342,10 @@ public: /// unsigned getParsedSpecifiers() const; + SCS getStorageClassSpecAsWritten() const { + return (SCS)StorageClassSpecAsWritten; + } + /// isEmpty - Return true if this declaration specifier is completely empty: /// no tokens were parsed in the production of it. bool isEmpty() const { diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 9a4634a..42a41d6 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -41,6 +41,29 @@ public: virtual void print(llvm::raw_ostream &OS) const; }; +/// PrecedenceLevels - These are precedences for the binary/ternary +/// operators in the C99 grammar. These have been named to relate +/// with the C99 grammar productions. Low precedences numbers bind +/// more weakly than high numbers. +namespace prec { + enum Level { + Unknown = 0, // Not binary operator. + Comma = 1, // , + Assignment = 2, // =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |= + Conditional = 3, // ? + LogicalOr = 4, // || + LogicalAnd = 5, // && + InclusiveOr = 6, // | + ExclusiveOr = 7, // ^ + And = 8, // & + Equality = 9, // ==, != + Relational = 10, // >=, <=, >, < + Shift = 11, // <<, >> + Additive = 12, // -, + + Multiplicative = 13, // *, /, % + PointerToMember = 14 // .*, ->* + }; +} /// Parser - This implements a parser for the C family of languages. After /// parsing units of the grammar, productions are invoked to handle whatever has @@ -460,9 +483,11 @@ private: //===--------------------------------------------------------------------===// // Diagnostic Emission and Error recovery. +public: DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID); DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID); +private: void SuggestParentheses(SourceLocation Loc, unsigned DK, SourceRange ParenRange); @@ -771,9 +796,15 @@ private: const ParsedTemplateInfo &TemplateInfo); void ParseLexedMethodDeclarations(ParsingClass &Class); void ParseLexedMethodDefs(ParsingClass &Class); + bool ConsumeAndStoreUntil(tok::TokenKind T1, + CachedTokens &Toks, + bool StopAtSemi = true, + bool ConsumeFinalToken = true) { + return ConsumeAndStoreUntil(T1, T1, Toks, StopAtSemi, ConsumeFinalToken); + } bool ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, CachedTokens &Toks, - tok::TokenKind EarlyAbortIf = tok::unknown, + bool StopAtSemi = true, bool ConsumeFinalToken = true); //===--------------------------------------------------------------------===// @@ -846,7 +877,7 @@ private: //===--------------------------------------------------------------------===// // C99 6.5: Expressions. - + OwningExprResult ParseExpression(); OwningExprResult ParseConstantExpression(); // Expr that doesn't include commas. @@ -857,7 +888,7 @@ private: OwningExprResult ParseExpressionWithLeadingExtension(SourceLocation ExtLoc); OwningExprResult ParseRHSOfBinaryExpression(OwningExprResult LHS, - unsigned MinPrec); + prec::Level MinPrec); OwningExprResult ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand, bool &NotCastExpr, @@ -954,6 +985,8 @@ private: // C++ 5.2.3: Explicit type conversion (functional notation) OwningExprResult ParseCXXTypeConstructExpression(const DeclSpec &DS); + bool isCXXSimpleTypeSpecifier() const; + /// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers. /// This should only be called when the current token is known to be part of /// simple-type-specifier. @@ -998,18 +1031,6 @@ private: //===--------------------------------------------------------------------===// // Objective-C Expressions - - bool isTokObjCMessageIdentifierReceiver() const { - if (!Tok.is(tok::identifier)) - return false; - - IdentifierInfo *II = Tok.getIdentifierInfo(); - if (Actions.getTypeName(*II, Tok.getLocation(), CurScope)) - return true; - - return II == Ident_super; - } - OwningExprResult ParseObjCAtExpression(SourceLocation AtLocation); OwningExprResult ParseObjCStringLiteral(SourceLocation AtLoc); OwningExprResult ParseObjCEncodeExpression(SourceLocation AtLoc); @@ -1017,12 +1038,13 @@ private: OwningExprResult ParseObjCProtocolExpression(SourceLocation AtLoc); OwningExprResult ParseObjCMessageExpression(); OwningExprResult ParseObjCMessageExpressionBody(SourceLocation LBracloc, - SourceLocation NameLoc, - IdentifierInfo *ReceiverName, + SourceLocation SuperLoc, + TypeTy *ReceiverType, ExprArg ReceiverExpr); OwningExprResult ParseAssignmentExprWithObjCMessageExprStart( - SourceLocation LBracloc, SourceLocation NameLoc, - IdentifierInfo *ReceiverName, ExprArg ReceiverExpr); + SourceLocation LBracloc, SourceLocation SuperLoc, + TypeTy *ReceiverType, ExprArg ReceiverExpr); + bool ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr); //===--------------------------------------------------------------------===// // C99 6.8: Statements and Blocks. @@ -1354,7 +1376,7 @@ private: //===--------------------------------------------------------------------===// // C++ 9: classes [class] and C structs/unions. TypeResult ParseClassName(SourceLocation &EndLocation, - const CXXScopeSpec *SS = 0); + CXXScopeSpec *SS = 0); void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc, DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), diff --git a/include/clang/Parse/Scope.h b/include/clang/Parse/Scope.h index c9825f6..d7a0e35 100644 --- a/include/clang/Parse/Scope.h +++ b/include/clang/Parse/Scope.h @@ -52,8 +52,8 @@ public: /// BlockScope - This is a scope that corresponds to a block object. /// Blocks serve as top-level scopes for some objects like labels, they - /// also prevent things like break and continue. BlockScopes have the - /// other flags set as well. + /// also prevent things like break and continue. BlockScopes always have + /// the FnScope, BreakScope, ContinueScope, and DeclScope flags set as well. BlockScope = 0x40, /// TemplateParamScope - This is a scope that corresponds to the @@ -68,7 +68,15 @@ public: /// AtCatchScope - This is a scope that corresponds to the Objective-C /// @catch statement. - AtCatchScope = 0x200 + AtCatchScope = 0x200, + + /// ObjCMethodScope - This scope corresponds to an Objective-C method body. + /// It always has FnScope and DeclScope set as well. + ObjCMethodScope = 0x400, + + /// ElseScope - This scoep corresponds to an 'else' scope of an if/then/else + /// statement. + ElseScope = 0x800 }; private: /// The parent scope for this scope. This is null for the translation-unit @@ -77,15 +85,11 @@ private: /// Depth - This is the depth of this scope. The translation-unit scope has /// depth 0. - unsigned Depth : 16; + unsigned short Depth; /// Flags - This contains a set of ScopeFlags, which indicates how the scope /// interrelates with other control flow statements. - unsigned Flags : 10; - - /// WithinElse - Whether this scope is part of the "else" branch in - /// its parent ControlScope. - bool WithinElse : 1; + unsigned short Flags; /// FnParent - If this scope has a parent scope that is a function body, this /// pointer is non-null and points to it. This is used for label processing. @@ -140,6 +144,7 @@ public: /// getFlags - Return the flags for this scope. /// unsigned getFlags() const { return Flags; } + void setFlags(unsigned F) { Flags = F; } /// isBlockScope - Return true if this scope does not correspond to a /// closure. @@ -233,6 +238,17 @@ public: } return false; } + + /// isInObjcMethodScope - Return true if this scope is, or is contained in, an + /// Objective-C method body. Note that this method is not constant time. + bool isInObjcMethodScope() const { + for (const Scope *S = this; S; S = S->getParent()) { + // If this scope is an objc method scope, then we succeed. + if (S->getFlags() & ObjCMethodScope) + return true; + } + return false; + } /// isTemplateParamScope - Return true if this scope is a C++ /// template parameter scope. @@ -251,12 +267,6 @@ public: return getFlags() & Scope::AtCatchScope; } - /// isWithinElse - Whether we are within the "else" of the - /// ControlParent (if any). - bool isWithinElse() const { return WithinElse; } - - void setWithinElse(bool WE) { WithinElse = WE; } - typedef UsingDirectivesTy::iterator udir_iterator; typedef UsingDirectivesTy::const_iterator const_udir_iterator; @@ -286,7 +296,6 @@ public: AnyParent = Parent; Depth = AnyParent ? AnyParent->Depth+1 : 0; Flags = ScopeFlags; - WithinElse = false; if (AnyParent) { FnParent = AnyParent->FnParent; diff --git a/include/clang/Rewrite/Rewriter.h b/include/clang/Rewrite/Rewriter.h index 1692180..adda866 100644 --- a/include/clang/Rewrite/Rewriter.h +++ b/include/clang/Rewrite/Rewriter.h @@ -16,18 +16,20 @@ #define LLVM_CLANG_REWRITER_H #include "clang/Basic/SourceLocation.h" +#include "clang/Rewrite/DeltaTree.h" #include "clang/Rewrite/RewriteRope.h" -#include <map> -#include <vector> +#include "llvm/ADT/StringRef.h" #include <cstring> +#include <map> #include <string> -#include "clang/Rewrite/DeltaTree.h" -#include "llvm/ADT/StringRef.h" +#include <vector> + +namespace llvm { class raw_ostream; } namespace clang { - class SourceManager; class LangOptions; class Rewriter; + class SourceManager; class Stmt; /// RewriteBuffer - As code is rewritten, SourceBuffer's from the original @@ -53,6 +55,8 @@ public: iterator end() const { return Buffer.end(); } unsigned size() const { return Buffer.size(); } + llvm::raw_ostream &write(llvm::raw_ostream &) const; + /// RemoveText - Remove the specified text. void RemoveText(unsigned OrigOffset, unsigned Size); @@ -125,6 +129,8 @@ class Rewriter { const LangOptions *LangOpts; std::map<FileID, RewriteBuffer> RewriteBuffers; public: + typedef std::map<FileID, RewriteBuffer>::iterator buffer_iterator; + explicit Rewriter(SourceManager &SM, const LangOptions &LO) : SourceMgr(&SM), LangOpts(&LO) {} explicit Rewriter() : SourceMgr(0), LangOpts(0) {} @@ -192,6 +198,12 @@ public: /// could not be rewritten, or false if successful. bool ReplaceStmt(Stmt *From, Stmt *To); + /// getEditBuffer - This is like getRewriteBufferFor, but always returns a + /// buffer, and allows you to write on it directly. This is useful if you + /// want efficient low-level access to apis for scribbling on one specific + /// FileID's buffer. + RewriteBuffer &getEditBuffer(FileID FID); + /// getRewriteBufferFor - Return the rewrite buffer for the specified FileID. /// If no modification has been made to it, return null. const RewriteBuffer *getRewriteBufferFor(FileID FID) const { @@ -200,11 +212,9 @@ public: return I == RewriteBuffers.end() ? 0 : &I->second; } - /// getEditBuffer - This is like getRewriteBufferFor, but always returns a - /// buffer, and allows you to write on it directly. This is useful if you - /// want efficient low-level access to apis for scribbling on one specific - /// FileID's buffer. - RewriteBuffer &getEditBuffer(FileID FID); + // Iterators over rewrite buffers. + buffer_iterator buffer_begin() { return RewriteBuffers.begin(); } + buffer_iterator buffer_end() { return RewriteBuffers.end(); } private: unsigned getLocationOffsetAndFileID(SourceLocation Loc, FileID &FID) const; |