diff options
292 files changed, 9232 insertions, 4858 deletions
diff --git a/contrib/llvm/include/llvm/ADT/APInt.h b/contrib/llvm/include/llvm/ADT/APInt.h index b91d5dc..d1fd3e5 100644 --- a/contrib/llvm/include/llvm/ADT/APInt.h +++ b/contrib/llvm/include/llvm/ADT/APInt.h @@ -1193,6 +1193,12 @@ public: /// @brief Count the number of leading one bits. unsigned countLeadingOnes() const; + /// Computes the number of leading bits of this APInt that are equal to its + /// sign bit. + unsigned getNumSignBits() const { + return isNegative() ? countLeadingOnes() : countLeadingZeros(); + } + /// countTrailingZeros - This function is an APInt version of the /// countTrailingZeros_{32,64} functions in MathExtras.h. It counts /// the number of zeros from the least significant bit to the first set bit. diff --git a/contrib/llvm/include/llvm/ADT/ArrayRef.h b/contrib/llvm/include/llvm/ADT/ArrayRef.h index 1c5470d..d3ea9c0 100644 --- a/contrib/llvm/include/llvm/ADT/ArrayRef.h +++ b/contrib/llvm/include/llvm/ADT/ArrayRef.h @@ -64,7 +64,10 @@ namespace llvm { /*implicit*/ ArrayRef(const std::vector<T> &Vec) : Data(Vec.empty() ? (T*)0 : &Vec[0]), Length(Vec.size()) {} - // TODO: C arrays. + /// Construct an ArrayRef from a C array. + template <size_t N> + /*implicit*/ ArrayRef(const T (&Arr)[N]) + : Data(Arr), Length(N) {} /// @} /// @name Simple Operations diff --git a/contrib/llvm/include/llvm/ADT/ImmutableIntervalMap.h b/contrib/llvm/include/llvm/ADT/ImmutableIntervalMap.h index d3196ca..0d8fcf3 100644 --- a/contrib/llvm/include/llvm/ADT/ImmutableIntervalMap.h +++ b/contrib/llvm/include/llvm/ADT/ImmutableIntervalMap.h @@ -215,7 +215,7 @@ public: ImmutableIntervalMap add(ImmutableIntervalMap Old, key_type_ref K, data_type_ref D) { - TreeTy *T = F.add(Old.Root, std::make_pair<key_type, data_type>(K, D)); + TreeTy *T = F.add(Old.Root, std::pair<key_type, data_type>(K, D)); return ImmutableIntervalMap(F.getCanonicalTree(T)); } diff --git a/contrib/llvm/include/llvm/ADT/ImmutableMap.h b/contrib/llvm/include/llvm/ADT/ImmutableMap.h index e439a09..d6cce7c 100644 --- a/contrib/llvm/include/llvm/ADT/ImmutableMap.h +++ b/contrib/llvm/include/llvm/ADT/ImmutableMap.h @@ -108,7 +108,7 @@ public: ImmutableMap getEmptyMap() { return ImmutableMap(F.getEmptyTree()); } ImmutableMap add(ImmutableMap Old, key_type_ref K, data_type_ref D) { - TreeTy *T = F.add(Old.Root, std::make_pair<key_type,data_type>(K,D)); + TreeTy *T = F.add(Old.Root, std::pair<key_type,data_type>(K,D)); return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T); } diff --git a/contrib/llvm/include/llvm/Analysis/DIBuilder.h b/contrib/llvm/include/llvm/Analysis/DIBuilder.h index bd22134..417dbc4 100644 --- a/contrib/llvm/include/llvm/Analysis/DIBuilder.h +++ b/contrib/llvm/include/llvm/Analysis/DIBuilder.h @@ -58,7 +58,7 @@ namespace llvm { const MDNode *getCU() { return TheCU; } enum ComplexAddrKind { OpPlus=1, OpDeref }; - /// CreateCompileUnit - A CompileUnit provides an anchor for all debugging + /// createCompileUnit - A CompileUnit provides an anchor for all debugging /// information generated during this instance of compilation. /// @param Lang Source programming language, eg. dwarf::DW_LANG_C99 /// @param File File name @@ -72,67 +72,67 @@ namespace llvm { /// by a tool analyzing generated debugging information. /// @param RV This indicates runtime version for languages like /// Objective-C. - void CreateCompileUnit(unsigned Lang, StringRef File, StringRef Dir, + void createCompileUnit(unsigned Lang, StringRef File, StringRef Dir, StringRef Producer, bool isOptimized, StringRef Flags, unsigned RV); - /// CreateFile - Create a file descriptor to hold debugging information + /// createFile - Create a file descriptor to hold debugging information /// for a file. - DIFile CreateFile(StringRef Filename, StringRef Directory); + DIFile createFile(StringRef Filename, StringRef Directory); - /// CreateEnumerator - Create a single enumerator value. - DIEnumerator CreateEnumerator(StringRef Name, uint64_t Val); + /// createEnumerator - Create a single enumerator value. + DIEnumerator createEnumerator(StringRef Name, uint64_t Val); - /// CreateBasicType - Create debugging information entry for a basic + /// createBasicType - Create debugging information entry for a basic /// type. /// @param Name Type name. /// @param SizeInBits Size of the type. /// @param AlignInBits Type alignment. /// @param Encoding DWARF encoding code, e.g. dwarf::DW_ATE_float. - DIType CreateBasicType(StringRef Name, uint64_t SizeInBits, + DIType createBasicType(StringRef Name, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding); - /// CreateQualifiedType - Create debugging information entry for a qualified + /// createQualifiedType - Create debugging information entry for a qualified /// type, e.g. 'const int'. /// @param Tag Tag identifing type, e.g. dwarf::TAG_volatile_type /// @param FromTy Base Type. - DIType CreateQualifiedType(unsigned Tag, DIType FromTy); + DIType createQualifiedType(unsigned Tag, DIType FromTy); - /// CreatePointerType - Create debugging information entry for a pointer. + /// createPointerType - Create debugging information entry for a pointer. /// @param PointeeTy Type pointed by this pointer. /// @param SizeInBits Size. /// @param AlignInBits Alignment. (optional) /// @param Name Pointer type name. (optional) - DIType CreatePointerType(DIType PointeeTy, uint64_t SizeInBits, + DIType createPointerType(DIType PointeeTy, uint64_t SizeInBits, uint64_t AlignInBits = 0, StringRef Name = StringRef()); - /// CreateReferenceType - Create debugging information entry for a c++ + /// createReferenceType - Create debugging information entry for a c++ /// style reference. - DIType CreateReferenceType(DIType RTy); + DIType createReferenceType(DIType RTy); - /// CreateTypedef - Create debugging information entry for a typedef. + /// createTypedef - Create debugging information entry for a typedef. /// @param Ty Original type. /// @param Name Typedef name. /// @param File File where this type is defined. /// @param LineNo Line number. - DIType CreateTypedef(DIType Ty, StringRef Name, DIFile File, + DIType createTypedef(DIType Ty, StringRef Name, DIFile File, unsigned LineNo); - /// CreateFriend - Create debugging information entry for a 'friend'. - DIType CreateFriend(DIType Ty, DIType FriendTy); + /// createFriend - Create debugging information entry for a 'friend'. + DIType createFriend(DIType Ty, DIType FriendTy); - /// CreateInheritance - Create debugging information entry to establish + /// createInheritance - Create debugging information entry to establish /// inheritance relationship between two types. /// @param Ty Original type. /// @param BaseTy Base type. Ty is inherits from base. /// @param BaseOffset Base offset. /// @param Flags Flags to describe inheritance attribute, /// e.g. private - DIType CreateInheritance(DIType Ty, DIType BaseTy, uint64_t BaseOffset, + DIType createInheritance(DIType Ty, DIType BaseTy, uint64_t BaseOffset, unsigned Flags); - /// CreateMemberType - Create debugging information entry for a member. + /// createMemberType - Create debugging information entry for a member. /// @param Name Member name. /// @param File File where this member is defined. /// @param LineNo Line number. @@ -141,12 +141,12 @@ namespace llvm { /// @param OffsetInBits Member offset. /// @param Flags Flags to encode member attribute, e.g. private /// @param Ty Parent type. - DIType CreateMemberType(StringRef Name, DIFile File, + DIType createMemberType(StringRef Name, DIFile File, unsigned LineNo, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, DIType Ty); - /// CreateClassType - Create debugging information entry for a class. + /// createClassType - Create debugging information entry for a class. /// @param Scope Scope in which this class is defined. /// @param Name class name. /// @param File File where this member is defined. @@ -161,14 +161,14 @@ namespace llvm { /// DW_AT_containing_type. See DWARF documentation /// for more info. /// @param TemplateParms Template type parameters. - DIType CreateClassType(DIDescriptor Scope, StringRef Name, DIFile File, + DIType createClassType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, DIType DerivedFrom, DIArray Elements, MDNode *VTableHolder = 0, MDNode *TemplateParms = 0); - /// CreateStructType - Create debugging information entry for a struct. + /// createStructType - Create debugging information entry for a struct. /// @param Scope Scope in which this struct is defined. /// @param Name Struct name. /// @param File File where this member is defined. @@ -178,12 +178,12 @@ namespace llvm { /// @param Flags Flags to encode member attribute, e.g. private /// @param Elements Struct elements. /// @param RunTimeLang Optional parameter, Objective-C runtime version. - DIType CreateStructType(DIDescriptor Scope, StringRef Name, DIFile File, + DIType createStructType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, DIArray Elements, unsigned RunTimeLang = 0); - /// CreateUnionType - Create debugging information entry for an union. + /// createUnionType - Create debugging information entry for an union. /// @param Scope Scope in which this union is defined. /// @param Name Union name. /// @param File File where this member is defined. @@ -193,12 +193,12 @@ namespace llvm { /// @param Flags Flags to encode member attribute, e.g. private /// @param Elements Union elements. /// @param RunTimeLang Optional parameter, Objective-C runtime version. - DIType CreateUnionType(DIDescriptor Scope, StringRef Name, DIFile File, + DIType createUnionType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, DIArray Elements, unsigned RunTimeLang = 0); - /// CreateTemplateTypeParameter - Create debugging information for template + /// createTemplateTypeParameter - Create debugging information for template /// type parameter. /// @param Scope Scope in which this type is defined. /// @param Name Type parameter name. @@ -207,11 +207,11 @@ namespace llvm { /// @param LineNo Line number. /// @param ColumnNo Column Number. DITemplateTypeParameter - CreateTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty, + createTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty, MDNode *File = 0, unsigned LineNo = 0, unsigned ColumnNo = 0); - /// CreateTemplateValueParameter - Create debugging information for template + /// createTemplateValueParameter - Create debugging information for template /// value parameter. /// @param Scope Scope in which this type is defined. /// @param Name Value parameter name. @@ -221,28 +221,28 @@ namespace llvm { /// @param LineNo Line number. /// @param ColumnNo Column Number. DITemplateValueParameter - CreateTemplateValueParameter(DIDescriptor Scope, StringRef Name, DIType Ty, + createTemplateValueParameter(DIDescriptor Scope, StringRef Name, DIType Ty, uint64_t Value, MDNode *File = 0, unsigned LineNo = 0, unsigned ColumnNo = 0); - /// CreateArrayType - Create debugging information entry for an array. + /// createArrayType - Create debugging information entry for an array. /// @param Size Array size. /// @param AlignInBits Alignment. /// @param Ty Element type. /// @param Subscripts Subscripts. - DIType CreateArrayType(uint64_t Size, uint64_t AlignInBits, + DIType createArrayType(uint64_t Size, uint64_t AlignInBits, DIType Ty, DIArray Subscripts); - /// CreateVectorType - Create debugging information entry for a vector type. + /// createVectorType - Create debugging information entry for a vector type. /// @param Size Array size. /// @param AlignInBits Alignment. /// @param Ty Element type. /// @param Subscripts Subscripts. - DIType CreateVectorType(uint64_t Size, uint64_t AlignInBits, + DIType createVectorType(uint64_t Size, uint64_t AlignInBits, DIType Ty, DIArray Subscripts); - /// CreateEnumerationType - Create debugging information entry for an + /// createEnumerationType - Create debugging information entry for an /// enumeration. /// @param Scope Scope in which this enumeration is defined. /// @param Name Union name. @@ -251,40 +251,40 @@ namespace llvm { /// @param SizeInBits Member size. /// @param AlignInBits Member alignment. /// @param Elements Enumeration elements. - DIType CreateEnumerationType(DIDescriptor Scope, StringRef Name, + DIType createEnumerationType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, DIArray Elements); - /// CreateSubroutineType - Create subroutine type. + /// createSubroutineType - Create subroutine type. /// @param File File in which this subroutine is defined. /// @param ParamterTypes An array of subroutine parameter types. This /// includes return type at 0th index. - DIType CreateSubroutineType(DIFile File, DIArray ParameterTypes); + DIType createSubroutineType(DIFile File, DIArray ParameterTypes); - /// CreateArtificialType - Create a new DIType with "artificial" flag set. - DIType CreateArtificialType(DIType Ty); + /// createArtificialType - Create a new DIType with "artificial" flag set. + DIType createArtificialType(DIType Ty); - /// CreateTemporaryType - Create a temporary forward-declared type. - DIType CreateTemporaryType(); - DIType CreateTemporaryType(DIFile F); + /// createTemporaryType - Create a temporary forward-declared type. + DIType createTemporaryType(); + DIType createTemporaryType(DIFile F); - /// RetainType - Retain DIType in a module even if it is not referenced + /// retainType - Retain DIType in a module even if it is not referenced /// through debug info anchors. - void RetainType(DIType T); + void retainType(DIType T); - /// CreateUnspecifiedParameter - Create unspeicified type descriptor + /// createUnspecifiedParameter - Create unspeicified type descriptor /// for a subroutine type. - DIDescriptor CreateUnspecifiedParameter(); + DIDescriptor createUnspecifiedParameter(); - /// GetOrCreateArray - Get a DIArray, create one if required. - DIArray GetOrCreateArray(Value *const *Elements, unsigned NumElements); + /// getOrCreateArray - Get a DIArray, create one if required. + DIArray getOrCreateArray(Value *const *Elements, unsigned NumElements); - /// GetOrCreateSubrange - Create a descriptor for a value range. This + /// getOrCreateSubrange - Create a descriptor for a value range. This /// implicitly uniques the values returned. - DISubrange GetOrCreateSubrange(int64_t Lo, int64_t Hi); + DISubrange getOrCreateSubrange(int64_t Lo, int64_t Hi); - /// CreateGlobalVariable - Create a new descriptor for the specified global. + /// createGlobalVariable - Create a new descriptor for the specified global. /// @param Name Name of the variable. /// @param File File where this variable is defined. /// @param LineNo Line number. @@ -293,11 +293,11 @@ namespace llvm { /// externally visible or not. /// @param Val llvm::Value of the variable. DIGlobalVariable - CreateGlobalVariable(StringRef Name, DIFile File, unsigned LineNo, + createGlobalVariable(StringRef Name, DIFile File, unsigned LineNo, DIType Ty, bool isLocalToUnit, llvm::Value *Val); - /// CreateStaticVariable - Create a new descriptor for the specified + /// createStaticVariable - Create a new descriptor for the specified /// variable. /// @param Conext Variable scope. /// @param Name Name of the variable. @@ -309,12 +309,12 @@ namespace llvm { /// externally visible or not. /// @param Val llvm::Value of the variable. DIGlobalVariable - CreateStaticVariable(DIDescriptor Context, StringRef Name, + createStaticVariable(DIDescriptor Context, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, DIType Ty, bool isLocalToUnit, llvm::Value *Val); - /// CreateLocalVariable - Create a new descriptor for the specified + /// createLocalVariable - Create a new descriptor for the specified /// local variable. /// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or /// DW_TAG_arg_variable. @@ -326,14 +326,14 @@ namespace llvm { /// @param AlwaysPreserve Boolean. Set to true if debug info for this /// variable should be preserved in optimized build. /// @param Flags Flags, e.g. artificial variable. - DIVariable CreateLocalVariable(unsigned Tag, DIDescriptor Scope, + DIVariable createLocalVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNo, DIType Ty, bool AlwaysPreserve = false, unsigned Flags = 0); - /// CreateComplexVariable - Create a new descriptor for the specified + /// createComplexVariable - Create a new descriptor for the specified /// variable which has a complex address expression for its address. /// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or /// DW_TAG_arg_variable. @@ -344,12 +344,12 @@ namespace llvm { /// @param Ty Variable Type /// @param Addr A pointer to a vector of complex address operations. /// @param NumAddr Num of address operations in the vector. - DIVariable CreateComplexVariable(unsigned Tag, DIDescriptor Scope, + DIVariable createComplexVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, DIFile F, unsigned LineNo, DIType Ty, Value *const *Addr, unsigned NumAddr); - /// CreateFunction - Create a new descriptor for the specified subprogram. + /// createFunction - Create a new descriptor for the specified subprogram. /// See comments in DISubprogram for descriptions of these fields. /// @param Scope Function scope. /// @param Name Function name. @@ -363,7 +363,7 @@ namespace llvm { /// This flags are used to emit dwarf attributes. /// @param isOptimized True if optimization is ON. /// @param Fn llvm::Function pointer. - DISubprogram CreateFunction(DIDescriptor Scope, StringRef Name, + DISubprogram createFunction(DIDescriptor Scope, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, DIType Ty, bool isLocalToUnit, @@ -372,7 +372,7 @@ namespace llvm { bool isOptimized = false, Function *Fn = 0); - /// CreateMethod - Create a new descriptor for the specified C++ method. + /// createMethod - Create a new descriptor for the specified C++ method. /// See comments in DISubprogram for descriptions of these fields. /// @param Scope Function scope. /// @param Name Function name. @@ -390,7 +390,7 @@ namespace llvm { /// This flags are used to emit dwarf attributes. /// @param isOptimized True if optimization is ON. /// @param Fn llvm::Function pointer. - DISubprogram CreateMethod(DIDescriptor Scope, StringRef Name, + DISubprogram createMethod(DIDescriptor Scope, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, DIType Ty, bool isLocalToUnit, @@ -401,55 +401,55 @@ namespace llvm { bool isOptimized = false, Function *Fn = 0); - /// CreateNameSpace - This creates new descriptor for a namespace + /// createNameSpace - This creates new descriptor for a namespace /// with the specified parent scope. /// @param Scope Namespace scope /// @param Name Name of this namespace /// @param File Source file /// @param LineNo Line number - DINameSpace CreateNameSpace(DIDescriptor Scope, StringRef Name, + DINameSpace createNameSpace(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNo); - /// CreateLexicalBlock - This creates a descriptor for a lexical block + /// createLexicalBlock - This creates a descriptor for a lexical block /// with the specified parent context. /// @param Scope Parent lexical scope. /// @param File Source file /// @param Line Line number /// @param Col Column number - DILexicalBlock CreateLexicalBlock(DIDescriptor Scope, DIFile File, + DILexicalBlock createLexicalBlock(DIDescriptor Scope, DIFile File, unsigned Line, unsigned Col); - /// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. + /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. /// @param Storage llvm::Value of the variable /// @param VarInfo Variable's debug info descriptor. /// @param InsertAtEnd Location for the new intrinsic. - Instruction *InsertDeclare(llvm::Value *Storage, DIVariable VarInfo, + Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo, BasicBlock *InsertAtEnd); - /// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. + /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. /// @param Storage llvm::Value of the variable /// @param VarInfo Variable's debug info descriptor. /// @param InsertBefore Location for the new intrinsic. - Instruction *InsertDeclare(llvm::Value *Storage, DIVariable VarInfo, + Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo, Instruction *InsertBefore); - /// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. + /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. /// @param Val llvm::Value of the variable /// @param Offset Offset /// @param VarInfo Variable's debug info descriptor. /// @param InsertAtEnd Location for the new intrinsic. - Instruction *InsertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, + Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, DIVariable VarInfo, BasicBlock *InsertAtEnd); - /// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. + /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. /// @param Val llvm::Value of the variable /// @param Offset Offset /// @param VarInfo Variable's debug info descriptor. /// @param InsertBefore Location for the new intrinsic. - Instruction *InsertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, + Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, DIVariable VarInfo, Instruction *InsertBefore); diff --git a/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h b/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h index 357b933..a071feb 100644 --- a/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -445,7 +445,8 @@ namespace llvm { /// EmitVisibility - This emits visibility information about symbol, if /// this is suported by the target. - void EmitVisibility(MCSymbol *Sym, unsigned Visibility) const; + void EmitVisibility(MCSymbol *Sym, unsigned Visibility, + bool IsDefinition = true) const; void EmitLinkage(unsigned Linkage, MCSymbol *GVSym) const; diff --git a/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h b/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h index 27631b7..b41f30d 100644 --- a/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -101,13 +101,16 @@ public: #endif struct LiveOutInfo { - unsigned NumSignBits; + unsigned NumSignBits : 31; + bool IsValid : 1; APInt KnownOne, KnownZero; - LiveOutInfo() : NumSignBits(0), KnownOne(1, 0), KnownZero(1, 0) {} + LiveOutInfo() : NumSignBits(0), IsValid(true), KnownOne(1, 0), + KnownZero(1, 0) {} }; - - /// LiveOutRegInfo - Information about live out vregs. - IndexedMap<LiveOutInfo, VirtReg2IndexFunctor> LiveOutRegInfo; + + /// VisitedBBs - The set of basic blocks visited thus far by instruction + /// selection. + DenseSet<const BasicBlock*> VisitedBBs; /// PHINodesToUpdate - A list of phi instructions whose operand list will /// be updated after processing the current basic block. @@ -143,12 +146,62 @@ public: return R = CreateRegs(V->getType()); } + /// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the + /// register is a PHI destination and the PHI's LiveOutInfo is not valid. + const LiveOutInfo *GetLiveOutRegInfo(unsigned Reg) { + if (!LiveOutRegInfo.inBounds(Reg)) + return NULL; + + const LiveOutInfo *LOI = &LiveOutRegInfo[Reg]; + if (!LOI->IsValid) + return NULL; + + return LOI; + } + + /// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the + /// register is a PHI destination and the PHI's LiveOutInfo is not valid. If + /// the register's LiveOutInfo is for a smaller bit width, it is extended to + /// the larger bit width by zero extension. The bit width must be no smaller + /// than the LiveOutInfo's existing bit width. + const LiveOutInfo *GetLiveOutRegInfo(unsigned Reg, unsigned BitWidth); + + /// AddLiveOutRegInfo - Adds LiveOutInfo for a register. + void AddLiveOutRegInfo(unsigned Reg, unsigned NumSignBits, + const APInt &KnownZero, const APInt &KnownOne) { + // Only install this information if it tells us something. + if (NumSignBits == 1 && KnownZero == 0 && KnownOne == 0) + return; + + LiveOutRegInfo.grow(Reg); + LiveOutInfo &LOI = LiveOutRegInfo[Reg]; + LOI.NumSignBits = NumSignBits; + LOI.KnownOne = KnownOne; + LOI.KnownZero = KnownZero; + } + + /// ComputePHILiveOutRegInfo - Compute LiveOutInfo for a PHI's destination + /// register based on the LiveOutInfo of its operands. + void ComputePHILiveOutRegInfo(const PHINode*); + + /// InvalidatePHILiveOutRegInfo - Invalidates a PHI's LiveOutInfo, to be + /// called when a block is visited before all of its predecessors. + void InvalidatePHILiveOutRegInfo(const PHINode *PN) { + unsigned Reg = ValueMap[PN]; + LiveOutRegInfo.grow(Reg); + LiveOutRegInfo[Reg].IsValid = false; + } + /// setByValArgumentFrameIndex - Record frame index for the byval /// argument. void setByValArgumentFrameIndex(const Argument *A, int FI); /// getByValArgumentFrameIndex - Get frame index for the byval argument. int getByValArgumentFrameIndex(const Argument *A); + +private: + /// LiveOutRegInfo - Information about live out vregs. + IndexedMap<LiveOutInfo, VirtReg2IndexFunctor> LiveOutRegInfo; }; /// AddCatchInfo - Extract the personality and type infos from an eh.selector diff --git a/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h b/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h index 498f815..5727321 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h @@ -16,6 +16,7 @@ #ifndef LLVM_CODEGEN_MACHINECONSTANTPOOL_H #define LLVM_CODEGEN_MACHINECONSTANTPOOL_H +#include "llvm/ADT/DenseSet.h" #include <cassert> #include <climits> #include <vector> @@ -130,6 +131,8 @@ class MachineConstantPool { const TargetData *TD; ///< The machine's TargetData. unsigned PoolAlignment; ///< The alignment for the pool. std::vector<MachineConstantPoolEntry> Constants; ///< The pool of constants. + /// MachineConstantPoolValues that use an existing MachineConstantPoolEntry. + DenseSet<MachineConstantPoolValue*> MachineCPVsSharingEntries; public: /// @brief The only constructor. explicit MachineConstantPool(const TargetData *td) diff --git a/contrib/llvm/include/llvm/CodeGen/MachineFunction.h b/contrib/llvm/include/llvm/CodeGen/MachineFunction.h index abeaa4f..f56c053 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineFunction.h @@ -281,7 +281,7 @@ public: /// addLiveIn - Add the specified physical register as a live-in value and /// create a corresponding virtual register for it. - unsigned addLiveIn(unsigned PReg, const TargetRegisterClass *RC, DebugLoc DL); + unsigned addLiveIn(unsigned PReg, const TargetRegisterClass *RC); //===--------------------------------------------------------------------===// // BasicBlock accessor functions. diff --git a/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h index 79ff714..74df8da 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h @@ -17,8 +17,6 @@ #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/IndexedMap.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/Support/DebugLoc.h" #include <vector> namespace llvm { @@ -66,10 +64,7 @@ class MachineRegisterInfo { /// stored in the second element. std::vector<std::pair<unsigned, unsigned> > LiveIns; std::vector<unsigned> LiveOuts; - - /// LiveInLocs - Keep track of location livein registers. - DenseMap<unsigned, DebugLoc> LiveInLocs; - + MachineRegisterInfo(const MachineRegisterInfo&); // DO NOT IMPLEMENT void operator=(const MachineRegisterInfo&); // DO NOT IMPLEMENT public: @@ -276,12 +271,7 @@ public: LiveIns.push_back(std::make_pair(Reg, vreg)); } void addLiveOut(unsigned Reg) { LiveOuts.push_back(Reg); } - - /// addLiveInLoc - Keep track of location info for live in reg. - void addLiveInLoc(unsigned VReg, DebugLoc DL) { - LiveInLocs[VReg] = DL; - } - + // Iteration support for live in/out sets. These sets are kept in sorted // order by their register number. typedef std::vector<std::pair<unsigned,unsigned> >::const_iterator diff --git a/contrib/llvm/include/llvm/IntrinsicsXCore.td b/contrib/llvm/include/llvm/IntrinsicsXCore.td index 97bac1d..944120f 100644 --- a/contrib/llvm/include/llvm/IntrinsicsXCore.td +++ b/contrib/llvm/include/llvm/IntrinsicsXCore.td @@ -33,4 +33,23 @@ let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". [NoCapture<0>]>; def int_xcore_setc : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], [NoCapture<0>]>; + def int_xcore_inshr : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_outshr : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_setpt : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_getts : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_syncr : Intrinsic<[],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_settw : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_setv : Intrinsic<[],[llvm_anyptr_ty, llvm_ptr_ty], + [NoCapture<0>]>; + def int_xcore_eeu : Intrinsic<[],[llvm_anyptr_ty], [NoCapture<0>]>; + + // Intrinsics for events. + def int_xcore_waitevent : Intrinsic<[llvm_ptr_ty],[], [IntrReadMem]>; + def int_xcore_clre : Intrinsic<[],[],[]>; } diff --git a/contrib/llvm/include/llvm/MC/MCAsmInfo.h b/contrib/llvm/include/llvm/MC/MCAsmInfo.h index 9cfd004..0bf364a 100644 --- a/contrib/llvm/include/llvm/MC/MCAsmInfo.h +++ b/contrib/llvm/include/llvm/MC/MCAsmInfo.h @@ -246,6 +246,11 @@ namespace llvm { /// declare a symbol as having hidden visibility. MCSymbolAttr HiddenVisibilityAttr; // Defaults to MCSA_Hidden. + /// HiddenDeclarationVisibilityAttr - This attribute, if not MCSA_Invalid, + /// is used to declare an undefined symbol as having hidden visibility. + MCSymbolAttr HiddenDeclarationVisibilityAttr; // Defaults to MCSA_Hidden. + + /// ProtectedVisibilityAttr - This attribute, if not MCSA_Invalid, is used /// to declare a symbol as having protected visibility. MCSymbolAttr ProtectedVisibilityAttr; // Defaults to MCSA_Protected @@ -425,6 +430,9 @@ namespace llvm { const char *getLinkOnceDirective() const { return LinkOnceDirective; } MCSymbolAttr getHiddenVisibilityAttr() const { return HiddenVisibilityAttr;} + MCSymbolAttr getHiddenDeclarationVisibilityAttr() const { + return HiddenDeclarationVisibilityAttr; + } MCSymbolAttr getProtectedVisibilityAttr() const { return ProtectedVisibilityAttr; } diff --git a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h index 95184cd..ceb57f5 100644 --- a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h +++ b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h @@ -38,6 +38,8 @@ protected: return (Obj->*Handler)(Directive, DirectiveLoc); } + bool BracketExpressionsSupported; + public: virtual ~MCAsmParserExtension(); @@ -68,6 +70,8 @@ public: const AsmToken &getTok() { return getParser().getTok(); } + bool HasBracketExpressions() const { return BracketExpressionsSupported; } + /// @} }; diff --git a/contrib/llvm/include/llvm/MC/MCStreamer.h b/contrib/llvm/include/llvm/MC/MCStreamer.h index fc2451f..4451199 100644 --- a/contrib/llvm/include/llvm/MC/MCStreamer.h +++ b/contrib/llvm/include/llvm/MC/MCStreamer.h @@ -57,13 +57,10 @@ namespace llvm { MCDwarfFrameInfo *getCurrentFrameInfo(); void EnsureValidFrame(); - /// CurSectionStack - This is stack of CurSection values saved by - /// PushSection. - SmallVector<const MCSection *, 4> CurSectionStack; - - /// PrevSectionStack - This is stack of PrevSection values saved by - /// PushSection. - SmallVector<const MCSection *, 4> PrevSectionStack; + /// SectionStack - This is stack of current and previous section + /// values saved by PushSection. + SmallVector<std::pair<const MCSection *, + const MCSection *>, 4> SectionStack; protected: MCStreamer(MCContext &Ctx); @@ -117,16 +114,16 @@ namespace llvm { /// getCurrentSection - Return the current section that the streamer is /// emitting code to. const MCSection *getCurrentSection() const { - if (!CurSectionStack.empty()) - return CurSectionStack.back(); + if (!SectionStack.empty()) + return SectionStack.back().first; return NULL; } /// getPreviousSection - Return the previous section that the streamer is /// emitting code to. const MCSection *getPreviousSection() const { - if (!PrevSectionStack.empty()) - return PrevSectionStack.back(); + if (!SectionStack.empty()) + return SectionStack.back().second; return NULL; } @@ -139,8 +136,8 @@ namespace llvm { /// pushSection - Save the current and previous section on the /// section stack. void PushSection() { - PrevSectionStack.push_back(getPreviousSection()); - CurSectionStack.push_back(getCurrentSection()); + SectionStack.push_back(std::make_pair(getCurrentSection(), + getPreviousSection())); } /// popSection - Restore the current and previous section from @@ -148,12 +145,10 @@ namespace llvm { /// /// Returns false if the stack was empty. bool PopSection() { - if (PrevSectionStack.size() <= 1) + if (SectionStack.size() <= 1) return false; - assert(CurSectionStack.size() > 1); - PrevSectionStack.pop_back(); - const MCSection *oldSection = CurSectionStack.pop_back_val(); - const MCSection *curSection = CurSectionStack.back(); + const MCSection *oldSection = SectionStack.pop_back_val().first; + const MCSection *curSection = SectionStack.back().first; if (oldSection != curSection) ChangeSection(curSection); @@ -166,10 +161,10 @@ namespace llvm { /// This corresponds to assembler directives like .section, .text, etc. void SwitchSection(const MCSection *Section) { assert(Section && "Cannot switch to a null section!"); - const MCSection *curSection = CurSectionStack.back(); - PrevSectionStack.back() = curSection; + const MCSection *curSection = SectionStack.back().first; + SectionStack.back().second = curSection; if (Section != curSection) { - CurSectionStack.back() = Section; + SectionStack.back().first = Section; ChangeSection(Section); } } diff --git a/contrib/llvm/include/llvm/Support/NoFolder.h b/contrib/llvm/include/llvm/Support/NoFolder.h index d7b5b42..92a9fd6 100644 --- a/contrib/llvm/include/llvm/Support/NoFolder.h +++ b/contrib/llvm/include/llvm/Support/NoFolder.h @@ -38,8 +38,12 @@ public: // Binary Operators //===--------------------------------------------------------------------===// - Instruction *CreateAdd(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateAdd(LHS, RHS); + Instruction *CreateAdd(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + BinaryOperator *BO = BinaryOperator::CreateAdd(LHS, RHS); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; } Instruction *CreateNSWAdd(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNSWAdd(LHS, RHS); @@ -50,8 +54,12 @@ public: Instruction *CreateFAdd(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateFAdd(LHS, RHS); } - Instruction *CreateSub(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateSub(LHS, RHS); + Instruction *CreateSub(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + BinaryOperator *BO = BinaryOperator::CreateSub(LHS, RHS); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; } Instruction *CreateNSWSub(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNSWSub(LHS, RHS); @@ -62,8 +70,12 @@ public: Instruction *CreateFSub(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateFSub(LHS, RHS); } - Instruction *CreateMul(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateMul(LHS, RHS); + Instruction *CreateMul(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + BinaryOperator *BO = BinaryOperator::CreateMul(LHS, RHS); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; } Instruction *CreateNSWMul(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNSWMul(LHS, RHS); @@ -74,14 +86,20 @@ public: Instruction *CreateFMul(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateFMul(LHS, RHS); } - Instruction *CreateUDiv(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateUDiv(LHS, RHS); + Instruction *CreateUDiv(Constant *LHS, Constant *RHS, + bool isExact = false) const { + if (!isExact) + return BinaryOperator::CreateUDiv(LHS, RHS); + return BinaryOperator::CreateExactUDiv(LHS, RHS); } Instruction *CreateExactUDiv(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateExactUDiv(LHS, RHS); } - Instruction *CreateSDiv(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateSDiv(LHS, RHS); + Instruction *CreateSDiv(Constant *LHS, Constant *RHS, + bool isExact = false) const { + if (!isExact) + return BinaryOperator::CreateSDiv(LHS, RHS); + return BinaryOperator::CreateExactSDiv(LHS, RHS); } Instruction *CreateExactSDiv(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateExactSDiv(LHS, RHS); @@ -98,14 +116,24 @@ public: Instruction *CreateFRem(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateFRem(LHS, RHS); } - Instruction *CreateShl(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateShl(LHS, RHS); - } - Instruction *CreateLShr(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateLShr(LHS, RHS); - } - Instruction *CreateAShr(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateAShr(LHS, RHS); + Instruction *CreateShl(Constant *LHS, Constant *RHS, bool HasNUW = false, + bool HasNSW = false) const { + BinaryOperator *BO = BinaryOperator::CreateShl(LHS, RHS); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; + } + Instruction *CreateLShr(Constant *LHS, Constant *RHS, + bool isExact = false) const { + if (!isExact) + return BinaryOperator::CreateLShr(LHS, RHS); + return BinaryOperator::CreateExactLShr(LHS, RHS); + } + Instruction *CreateAShr(Constant *LHS, Constant *RHS, + bool isExact = false) const { + if (!isExact) + return BinaryOperator::CreateAShr(LHS, RHS); + return BinaryOperator::CreateExactAShr(LHS, RHS); } Instruction *CreateAnd(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateAnd(LHS, RHS); @@ -126,8 +154,12 @@ public: // Unary Operators //===--------------------------------------------------------------------===// - Instruction *CreateNeg(Constant *C) const { - return BinaryOperator::CreateNeg(C); + Instruction *CreateNeg(Constant *C, + bool HasNUW = false, bool HasNSW = false) const { + BinaryOperator *BO = BinaryOperator::CreateNeg(C); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; } Instruction *CreateNSWNeg(Constant *C) const { return BinaryOperator::CreateNSWNeg(C); diff --git a/contrib/llvm/include/llvm/Support/PathV1.h b/contrib/llvm/include/llvm/Support/PathV1.h index a1c3f6a..d7753a3 100644 --- a/contrib/llvm/include/llvm/Support/PathV1.h +++ b/contrib/llvm/include/llvm/Support/PathV1.h @@ -312,9 +312,9 @@ namespace sys { /// This function determines if the path name is absolute, as opposed to /// relative. /// @brief Determine if the path is absolute. -//FIXME: LLVM_ATTRIBUTE_DEPRECATED( - bool isAbsolute() const; -//FIXME: LLVMV_PATH_DEPRECATED_MSG(path::is_absolute)); + LLVM_ATTRIBUTE_DEPRECATED( + bool isAbsolute() const, + LLVM_PATH_DEPRECATED_MSG(path::is_absolute)); /// This function determines if the path name is absolute, as opposed to /// relative. diff --git a/contrib/llvm/include/llvm/Target/TargetLowering.h b/contrib/llvm/include/llvm/Target/TargetLowering.h index 5141b7b..ba7574d 100644 --- a/contrib/llvm/include/llvm/Target/TargetLowering.h +++ b/contrib/llvm/include/llvm/Target/TargetLowering.h @@ -111,7 +111,7 @@ public: bool isBigEndian() const { return !IsLittleEndian; } bool isLittleEndian() const { return IsLittleEndian; } MVT getPointerTy() const { return PointerTy; } - MVT getShiftAmountTy() const { return ShiftAmountTy; } + virtual MVT getShiftAmountTy(EVT LHSTy) const; /// isSelectExpensive - Return true if the select operation is expensive for /// this target. @@ -210,7 +210,7 @@ public: /// ValueTypeActions - For each value type, keep a LegalizeAction enum /// that indicates how instruction selection should deal with the type. uint8_t ValueTypeActions[MVT::LAST_VALUETYPE]; - + LegalizeAction getExtendedTypeAction(EVT VT) const { // Handle non-vector integers. if (!VT.isVector()) { @@ -221,42 +221,56 @@ public: return Promote; return Expand; } - - // If this is a type smaller than a legal vector type, promote to that - // type, e.g. <2 x float> -> <4 x float>. - if (VT.getVectorElementType().isSimple() && - VT.getVectorNumElements() != 1) { - MVT EltType = VT.getVectorElementType().getSimpleVT(); - unsigned NumElts = VT.getVectorNumElements(); - while (1) { - // Round up to the nearest power of 2. - NumElts = (unsigned)NextPowerOf2(NumElts); - - MVT LargerVector = MVT::getVectorVT(EltType, NumElts); - if (LargerVector == MVT()) break; - - // If this the larger type is legal, promote to it. - if (getTypeAction(LargerVector) == Legal) return Promote; - } + + // Vectors with only one element are always scalarized. + if (VT.getVectorNumElements() == 1) + return Expand; + + // Vectors with a number of elements that is not a power of two are always + // widened, for example <3 x float> -> <4 x float>. + if (!VT.isPow2VectorType()) + return Promote; + + // Vectors with a crazy element type are always expanded, for example + // <4 x i2> is expanded into two vectors of type <2 x i2>. + if (!VT.getVectorElementType().isSimple()) + return Expand; + + // If this type is smaller than a legal vector type then widen it, + // otherwise expand it. E.g. <2 x float> -> <4 x float>. + MVT EltType = VT.getVectorElementType().getSimpleVT(); + unsigned NumElts = VT.getVectorNumElements(); + while (1) { + // Round up to the next power of 2. + NumElts = (unsigned)NextPowerOf2(NumElts); + + // If there is no simple vector type with this many elements then there + // cannot be a larger legal vector type. Note that this assumes that + // there are no skipped intermediate vector types in the simple types. + MVT LargerVector = MVT::getVectorVT(EltType, NumElts); + if (LargerVector == MVT()) + return Expand; + + // If this type is legal then widen the vector. + if (getTypeAction(LargerVector) == Legal) + return Promote; } - - return VT.isPow2VectorType() ? Expand : Promote; - } + } public: ValueTypeActionImpl() { std::fill(ValueTypeActions, array_endof(ValueTypeActions), 0); } - + LegalizeAction getTypeAction(EVT VT) const { if (!VT.isExtended()) return getTypeAction(VT.getSimpleVT()); return getExtendedTypeAction(VT); } - + LegalizeAction getTypeAction(MVT VT) const { return (LegalizeAction)ValueTypeActions[VT.SimpleTy]; } - + void setTypeAction(EVT VT, LegalizeAction Action) { unsigned I = VT.getSimpleVT().SimpleTy; ValueTypeActions[I] = Action; @@ -277,7 +291,7 @@ public: LegalizeAction getTypeAction(MVT VT) const { return ValueTypeActions.getTypeAction(VT); } - + /// getTypeToTransformTo - For types supported by the target, this is an /// identity function. For types that must be promoted to larger types, this /// returns the larger type to promote to. For integer types that are larger @@ -310,7 +324,7 @@ public: EVT NVT = VT.getRoundIntegerType(Context); if (NVT == VT) // Size is a power of two - expand to half the size. return EVT::getIntegerVT(Context, VT.getSizeInBits() / 2); - + // Promote to a power of two size, avoiding multi-step promotion. return getTypeAction(NVT) == Promote ? getTypeToTransformTo(Context, NVT) : NVT; @@ -983,10 +997,6 @@ public: // protected: - /// setShiftAmountType - Describe the type that should be used for shift - /// amounts. This type defaults to the pointer type. - void setShiftAmountType(MVT VT) { ShiftAmountTy = VT; } - /// setBooleanContents - Specify how the target extends the result of a /// boolean value from i1 to a wider type. See getBooleanContents. void setBooleanContents(BooleanContent Ty) { BooleanContents = Ty; } @@ -1033,12 +1043,12 @@ protected: /// SelectIsExpensive - Tells the code generator not to expand operations /// into sequences that use the select operations if possible. - void setSelectIsExpensive(bool isExpensive = true) { - SelectIsExpensive = isExpensive; + void setSelectIsExpensive(bool isExpensive = true) { + SelectIsExpensive = isExpensive; } - /// JumpIsExpensive - Tells the code generator not to expand sequence of - /// operations into a seperate sequences that increases the amount of + /// JumpIsExpensive - Tells the code generator not to expand sequence of + /// operations into a seperate sequences that increases the amount of /// flow control. void setJumpIsExpensive(bool isExpensive = true) { JumpIsExpensive = isExpensive; @@ -1355,7 +1365,7 @@ public: CW_Good = 1, // Good weight. CW_Better = 2, // Better weight. CW_Best = 3, // Best weight. - + // Well-known weights. CW_SpecificReg = CW_Okay, // Specific register operands. CW_Register = CW_Good, // Register operands. @@ -1408,21 +1418,21 @@ public: CallOperandVal(0), ConstraintVT(MVT::Other) { } }; - + typedef std::vector<AsmOperandInfo> AsmOperandInfoVector; - + /// ParseConstraints - Split up the constraint string from the inline /// assembly value into the specific constraints and their prefixes, /// and also tie in the associated operand values. /// If this returns an empty vector, and if the constraint string itself /// isn't empty, there was an error parsing. virtual AsmOperandInfoVector ParseConstraints(ImmutableCallSite CS) const; - + /// Examine constraint type and operand type and determine a weight value. /// The operand object must already have been set up with the operand type. virtual ConstraintWeight getMultipleConstraintMatchWeight( AsmOperandInfo &info, int maIndex) const; - + /// Examine constraint string and operand type and determine a weight value. /// The operand object must already have been set up with the operand type. virtual ConstraintWeight getSingleConstraintMatchWeight( @@ -1432,7 +1442,7 @@ public: /// type to use for the specific AsmOperandInfo, setting /// OpInfo.ConstraintCode and OpInfo.ConstraintType. If the actual operand /// being passed in is available, it can be passed in as Op, otherwise an - /// empty SDValue can be passed. + /// empty SDValue can be passed. virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo, SDValue Op, SelectionDAG *DAG = 0) const; @@ -1646,10 +1656,6 @@ private: /// llvm.longjmp. Defaults to false. bool UseUnderscoreLongJmp; - /// ShiftAmountTy - The type to use for shift amounts, usually i8 or whatever - /// PointerTy is. - MVT ShiftAmountTy; - /// BooleanContents - Information about the contents of the high-bits in /// boolean values held in a type wider than i1. See getBooleanContents. BooleanContent BooleanContents; diff --git a/contrib/llvm/include/llvm/Transforms/Utils/Local.h b/contrib/llvm/include/llvm/Transforms/Utils/Local.h index 26b5dd8..2823fbb 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/Local.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/Local.h @@ -60,7 +60,7 @@ bool RecursivelyDeleteTriviallyDeadInstructions(Value *V); /// dead PHI node, due to being a def-use chain of single-use nodes that /// either forms a cycle or is terminated by a trivially dead instruction, /// delete it. If that makes any of its operands trivially dead, delete them -/// too, recursively. Return true if the PHI node is actually deleted. +/// too, recursively. Return true if a change was made. bool RecursivelyDeleteDeadPHINode(PHINode *PN); diff --git a/contrib/llvm/lib/Analysis/DIBuilder.cpp b/contrib/llvm/lib/Analysis/DIBuilder.cpp index c1072df..590a9c1 100644 --- a/contrib/llvm/lib/Analysis/DIBuilder.cpp +++ b/contrib/llvm/lib/Analysis/DIBuilder.cpp @@ -31,9 +31,9 @@ static Constant *GetTagConstant(LLVMContext &VMContext, unsigned Tag) { DIBuilder::DIBuilder(Module &m) : M(m), VMContext(M.getContext()), TheCU(0), DeclareFn(0), ValueFn(0) {} -/// CreateCompileUnit - A CompileUnit provides an anchor for all debugging +/// createCompileUnit - A CompileUnit provides an anchor for all debugging /// information generated during this instance of compilation. -void DIBuilder::CreateCompileUnit(unsigned Lang, StringRef Filename, +void DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, StringRef Directory, StringRef Producer, bool isOptimized, StringRef Flags, unsigned RunTimeVer) { @@ -53,9 +53,9 @@ void DIBuilder::CreateCompileUnit(unsigned Lang, StringRef Filename, TheCU = DICompileUnit(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); } -/// CreateFile - Create a file descriptor to hold debugging information +/// createFile - Create a file descriptor to hold debugging information /// for a file. -DIFile DIBuilder::CreateFile(StringRef Filename, StringRef Directory) { +DIFile DIBuilder::createFile(StringRef Filename, StringRef Directory) { assert(TheCU && "Unable to create DW_TAG_file_type without CompileUnit"); Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_file_type), @@ -66,8 +66,8 @@ DIFile DIBuilder::CreateFile(StringRef Filename, StringRef Directory) { return DIFile(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); } -/// CreateEnumerator - Create a single enumerator value. -DIEnumerator DIBuilder::CreateEnumerator(StringRef Name, uint64_t Val) { +/// createEnumerator - Create a single enumerator value. +DIEnumerator DIBuilder::createEnumerator(StringRef Name, uint64_t Val) { Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_enumerator), MDString::get(VMContext, Name), @@ -76,9 +76,9 @@ DIEnumerator DIBuilder::CreateEnumerator(StringRef Name, uint64_t Val) { return DIEnumerator(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); } -/// CreateBasicType - Create debugging information entry for a basic +/// createBasicType - Create debugging information entry for a basic /// type, e.g 'char'. -DIType DIBuilder::CreateBasicType(StringRef Name, uint64_t SizeInBits, +DIType DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding) { // Basic types are encoded in DIBasicType format. Line number, filename, @@ -98,9 +98,9 @@ DIType DIBuilder::CreateBasicType(StringRef Name, uint64_t SizeInBits, return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); } -/// CreateQaulifiedType - Create debugging information entry for a qualified +/// createQaulifiedType - Create debugging information entry for a qualified /// type, e.g. 'const int'. -DIType DIBuilder::CreateQualifiedType(unsigned Tag, DIType FromTy) { +DIType DIBuilder::createQualifiedType(unsigned Tag, DIType FromTy) { // Qualified types are encoded in DIDerivedType format. Value *Elts[] = { GetTagConstant(VMContext, Tag), @@ -117,8 +117,8 @@ DIType DIBuilder::CreateQualifiedType(unsigned Tag, DIType FromTy) { return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); } -/// CreatePointerType - Create debugging information entry for a pointer. -DIType DIBuilder::CreatePointerType(DIType PointeeTy, uint64_t SizeInBits, +/// createPointerType - Create debugging information entry for a pointer. +DIType DIBuilder::createPointerType(DIType PointeeTy, uint64_t SizeInBits, uint64_t AlignInBits, StringRef Name) { // Pointer types are encoded in DIDerivedType format. Value *Elts[] = { @@ -136,8 +136,8 @@ DIType DIBuilder::CreatePointerType(DIType PointeeTy, uint64_t SizeInBits, return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); } -/// CreateReferenceType - Create debugging information entry for a reference. -DIType DIBuilder::CreateReferenceType(DIType RTy) { +/// createReferenceType - Create debugging information entry for a reference. +DIType DIBuilder::createReferenceType(DIType RTy) { // References are encoded in DIDerivedType format. Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_reference_type), @@ -154,8 +154,8 @@ DIType DIBuilder::CreateReferenceType(DIType RTy) { return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); } -/// CreateTypedef - Create debugging information entry for a typedef. -DIType DIBuilder::CreateTypedef(DIType Ty, StringRef Name, DIFile File, +/// createTypedef - Create debugging information entry for a typedef. +DIType DIBuilder::createTypedef(DIType Ty, StringRef Name, DIFile File, unsigned LineNo) { // typedefs are encoded in DIDerivedType format. assert(Ty.Verify() && "Invalid typedef type!"); @@ -174,8 +174,8 @@ DIType DIBuilder::CreateTypedef(DIType Ty, StringRef Name, DIFile File, return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); } -/// CreateFriend - Create debugging information entry for a 'friend'. -DIType DIBuilder::CreateFriend(DIType Ty, DIType FriendTy) { +/// createFriend - Create debugging information entry for a 'friend'. +DIType DIBuilder::createFriend(DIType Ty, DIType FriendTy) { // typedefs are encoded in DIDerivedType format. assert(Ty.Verify() && "Invalid type!"); assert(FriendTy.Verify() && "Invalid friend type!"); @@ -194,9 +194,9 @@ DIType DIBuilder::CreateFriend(DIType Ty, DIType FriendTy) { return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); } -/// CreateInheritance - Create debugging information entry to establish +/// createInheritance - Create debugging information entry to establish /// inheritnace relationship between two types. -DIType DIBuilder::CreateInheritance(DIType Ty, DIType BaseTy, +DIType DIBuilder::createInheritance(DIType Ty, DIType BaseTy, uint64_t BaseOffset, unsigned Flags) { // TAG_inheritance is encoded in DIDerivedType format. Value *Elts[] = { @@ -214,8 +214,8 @@ DIType DIBuilder::CreateInheritance(DIType Ty, DIType BaseTy, return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); } -/// CreateMemberType - Create debugging information entry for a member. -DIType DIBuilder::CreateMemberType(StringRef Name, +/// createMemberType - Create debugging information entry for a member. +DIType DIBuilder::createMemberType(StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, @@ -236,8 +236,8 @@ DIType DIBuilder::CreateMemberType(StringRef Name, return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); } -/// CreateClassType - Create debugging information entry for a class. -DIType DIBuilder::CreateClassType(DIDescriptor Context, StringRef Name, +/// createClassType - Create debugging information entry for a class. +DIType DIBuilder::createClassType(DIDescriptor Context, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, @@ -263,10 +263,10 @@ DIType DIBuilder::CreateClassType(DIDescriptor Context, StringRef Name, return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); } -/// CreateTemplateTypeParameter - Create debugging information for template +/// createTemplateTypeParameter - Create debugging information for template /// type parameter. DITemplateTypeParameter -DIBuilder::CreateTemplateTypeParameter(DIDescriptor Context, StringRef Name, +DIBuilder::createTemplateTypeParameter(DIDescriptor Context, StringRef Name, DIType Ty, MDNode *File, unsigned LineNo, unsigned ColumnNo) { Value *Elts[] = { @@ -282,10 +282,10 @@ DIBuilder::CreateTemplateTypeParameter(DIDescriptor Context, StringRef Name, array_lengthof(Elts))); } -/// CreateTemplateValueParameter - Create debugging information for template +/// createTemplateValueParameter - Create debugging information for template /// value parameter. DITemplateValueParameter -DIBuilder::CreateTemplateValueParameter(DIDescriptor Context, StringRef Name, +DIBuilder::createTemplateValueParameter(DIDescriptor Context, StringRef Name, DIType Ty, uint64_t Val, MDNode *File, unsigned LineNo, unsigned ColumnNo) { @@ -303,8 +303,8 @@ DIBuilder::CreateTemplateValueParameter(DIDescriptor Context, StringRef Name, array_lengthof(Elts))); } -/// CreateStructType - Create debugging information entry for a struct. -DIType DIBuilder::CreateStructType(DIDescriptor Context, StringRef Name, +/// createStructType - Create debugging information entry for a struct. +DIType DIBuilder::createStructType(DIDescriptor Context, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, DIArray Elements, @@ -328,8 +328,8 @@ DIType DIBuilder::CreateStructType(DIDescriptor Context, StringRef Name, return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); } -/// CreateUnionType - Create debugging information entry for an union. -DIType DIBuilder::CreateUnionType(DIDescriptor Scope, StringRef Name, +/// createUnionType - Create debugging information entry for an union. +DIType DIBuilder::createUnionType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, @@ -353,8 +353,8 @@ DIType DIBuilder::CreateUnionType(DIDescriptor Scope, StringRef Name, return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); } -/// CreateSubroutineType - Create subroutine type. -DIType DIBuilder::CreateSubroutineType(DIFile File, DIArray ParameterTypes) { +/// createSubroutineType - Create subroutine type. +DIType DIBuilder::createSubroutineType(DIFile File, DIArray ParameterTypes) { // TAG_subroutine_type is encoded in DICompositeType format. Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_subroutine_type), @@ -374,9 +374,9 @@ DIType DIBuilder::CreateSubroutineType(DIFile File, DIArray ParameterTypes) { return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); } -/// CreateEnumerationType - Create debugging information entry for an +/// createEnumerationType - Create debugging information entry for an /// enumeration. -DIType DIBuilder::CreateEnumerationType(DIDescriptor Scope, StringRef Name, +DIType DIBuilder::createEnumerationType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, DIArray Elements) { @@ -402,8 +402,8 @@ DIType DIBuilder::CreateEnumerationType(DIDescriptor Scope, StringRef Name, return DIType(Node); } -/// CreateArrayType - Create debugging information entry for an array. -DIType DIBuilder::CreateArrayType(uint64_t Size, uint64_t AlignInBits, +/// createArrayType - Create debugging information entry for an array. +DIType DIBuilder::createArrayType(uint64_t Size, uint64_t AlignInBits, DIType Ty, DIArray Subscripts) { // TAG_array_type is encoded in DICompositeType format. Value *Elts[] = { @@ -424,8 +424,8 @@ DIType DIBuilder::CreateArrayType(uint64_t Size, uint64_t AlignInBits, return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); } -/// CreateVectorType - Create debugging information entry for a vector. -DIType DIBuilder::CreateVectorType(uint64_t Size, uint64_t AlignInBits, +/// createVectorType - Create debugging information entry for a vector. +DIType DIBuilder::createVectorType(uint64_t Size, uint64_t AlignInBits, DIType Ty, DIArray Subscripts) { // TAG_vector_type is encoded in DICompositeType format. Value *Elts[] = { @@ -446,8 +446,8 @@ DIType DIBuilder::CreateVectorType(uint64_t Size, uint64_t AlignInBits, return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); } -/// CreateArtificialType - Create a new DIType with "artificial" flag set. -DIType DIBuilder::CreateArtificialType(DIType Ty) { +/// createArtificialType - Create a new DIType with "artificial" flag set. +DIType DIBuilder::createArtificialType(DIType Ty) { if (Ty.isArtificial()) return Ty; @@ -470,24 +470,24 @@ DIType DIBuilder::CreateArtificialType(DIType Ty) { return DIType(MDNode::get(VMContext, Elts.data(), Elts.size())); } -/// RetainType - Retain DIType in a module even if it is not referenced +/// retainType - Retain DIType in a module even if it is not referenced /// through debug info anchors. -void DIBuilder::RetainType(DIType T) { +void DIBuilder::retainType(DIType T) { NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.ty"); NMD->addOperand(T); } -/// CreateUnspecifiedParameter - Create unspeicified type descriptor +/// createUnspecifiedParameter - Create unspeicified type descriptor /// for the subroutine type. -DIDescriptor DIBuilder::CreateUnspecifiedParameter() { +DIDescriptor DIBuilder::createUnspecifiedParameter() { Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_unspecified_parameters) }; return DIDescriptor(MDNode::get(VMContext, &Elts[0], 1)); } -/// CreateTemporaryType - Create a temporary forward-declared type. -DIType DIBuilder::CreateTemporaryType() { +/// createTemporaryType - Create a temporary forward-declared type. +DIType DIBuilder::createTemporaryType() { // Give the temporary MDNode a tag. It doesn't matter what tag we // use here as long as DIType accepts it. Value *Elts[] = { GetTagConstant(VMContext, DW_TAG_base_type) }; @@ -495,8 +495,8 @@ DIType DIBuilder::CreateTemporaryType() { return DIType(Node); } -/// CreateTemporaryType - Create a temporary forward-declared type. -DIType DIBuilder::CreateTemporaryType(DIFile F) { +/// createTemporaryType - Create a temporary forward-declared type. +DIType DIBuilder::createTemporaryType(DIFile F) { // Give the temporary MDNode a tag. It doesn't matter what tag we // use here as long as DIType accepts it. Value *Elts[] = { @@ -509,8 +509,8 @@ DIType DIBuilder::CreateTemporaryType(DIFile F) { return DIType(Node); } -/// GetOrCreateArray - Get a DIArray, create one if required. -DIArray DIBuilder::GetOrCreateArray(Value *const *Elements, unsigned NumElements) { +/// getOrCreateArray - Get a DIArray, create one if required. +DIArray DIBuilder::getOrCreateArray(Value *const *Elements, unsigned NumElements) { if (NumElements == 0) { Value *Null = llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)); return DIArray(MDNode::get(VMContext, &Null, 1)); @@ -518,9 +518,9 @@ DIArray DIBuilder::GetOrCreateArray(Value *const *Elements, unsigned NumElements return DIArray(MDNode::get(VMContext, Elements, NumElements)); } -/// GetOrCreateSubrange - Create a descriptor for a value range. This +/// getOrCreateSubrange - Create a descriptor for a value range. This /// implicitly uniques the values returned. -DISubrange DIBuilder::GetOrCreateSubrange(int64_t Lo, int64_t Hi) { +DISubrange DIBuilder::getOrCreateSubrange(int64_t Lo, int64_t Hi) { Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_subrange_type), ConstantInt::get(Type::getInt64Ty(VMContext), Lo), @@ -530,9 +530,9 @@ DISubrange DIBuilder::GetOrCreateSubrange(int64_t Lo, int64_t Hi) { return DISubrange(MDNode::get(VMContext, &Elts[0], 3)); } -/// CreateGlobalVariable - Create a new descriptor for the specified global. +/// createGlobalVariable - Create a new descriptor for the specified global. DIGlobalVariable DIBuilder:: -CreateGlobalVariable(StringRef Name, DIFile F, unsigned LineNumber, +createGlobalVariable(StringRef Name, DIFile F, unsigned LineNumber, DIType Ty, bool isLocalToUnit, llvm::Value *Val) { Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_variable), @@ -555,10 +555,10 @@ CreateGlobalVariable(StringRef Name, DIFile F, unsigned LineNumber, return DIGlobalVariable(Node); } -/// CreateStaticVariable - Create a new descriptor for the specified static +/// createStaticVariable - Create a new descriptor for the specified static /// variable. DIGlobalVariable DIBuilder:: -CreateStaticVariable(DIDescriptor Context, StringRef Name, +createStaticVariable(DIDescriptor Context, StringRef Name, StringRef LinkageName, DIFile F, unsigned LineNumber, DIType Ty, bool isLocalToUnit, llvm::Value *Val) { Value *Elts[] = { @@ -582,8 +582,8 @@ CreateStaticVariable(DIDescriptor Context, StringRef Name, return DIGlobalVariable(Node); } -/// CreateVariable - Create a new descriptor for the specified variable. -DIVariable DIBuilder::CreateLocalVariable(unsigned Tag, DIDescriptor Scope, +/// createVariable - Create a new descriptor for the specified variable. +DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNo, DIType Ty, bool AlwaysPreserve, unsigned Flags) { @@ -614,9 +614,9 @@ DIVariable DIBuilder::CreateLocalVariable(unsigned Tag, DIDescriptor Scope, return DIVariable(Node); } -/// CreateComplexVariable - Create a new descriptor for the specified variable +/// createComplexVariable - Create a new descriptor for the specified variable /// which has a complex address expression for its address. -DIVariable DIBuilder::CreateComplexVariable(unsigned Tag, DIDescriptor Scope, +DIVariable DIBuilder::createComplexVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, DIFile F, unsigned LineNo, DIType Ty, Value *const *Addr, @@ -633,8 +633,8 @@ DIVariable DIBuilder::CreateComplexVariable(unsigned Tag, DIDescriptor Scope, return DIVariable(MDNode::get(VMContext, Elts.data(), Elts.size())); } -/// CreateFunction - Create a new descriptor for the specified function. -DISubprogram DIBuilder::CreateFunction(DIDescriptor Context, +/// createFunction - Create a new descriptor for the specified function. +DISubprogram DIBuilder::createFunction(DIDescriptor Context, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, @@ -670,8 +670,8 @@ DISubprogram DIBuilder::CreateFunction(DIDescriptor Context, return DISubprogram(Node); } -/// CreateMethod - Create a new descriptor for the specified C++ method. -DISubprogram DIBuilder::CreateMethod(DIDescriptor Context, +/// createMethod - Create a new descriptor for the specified C++ method. +DISubprogram DIBuilder::createMethod(DIDescriptor Context, StringRef Name, StringRef LinkageName, DIFile F, @@ -710,9 +710,9 @@ DISubprogram DIBuilder::CreateMethod(DIDescriptor Context, return DISubprogram(Node); } -/// CreateNameSpace - This creates new descriptor for a namespace +/// createNameSpace - This creates new descriptor for a namespace /// with the specified parent scope. -DINameSpace DIBuilder::CreateNameSpace(DIDescriptor Scope, StringRef Name, +DINameSpace DIBuilder::createNameSpace(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNo) { Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_namespace), @@ -724,7 +724,7 @@ DINameSpace DIBuilder::CreateNameSpace(DIDescriptor Scope, StringRef Name, return DINameSpace(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); } -DILexicalBlock DIBuilder::CreateLexicalBlock(DIDescriptor Scope, DIFile File, +DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File, unsigned Line, unsigned Col) { // Defeat MDNode uniqing for lexical blocks by using unique id. static unsigned int unique_id = 0; @@ -739,8 +739,8 @@ DILexicalBlock DIBuilder::CreateLexicalBlock(DIDescriptor Scope, DIFile File, return DILexicalBlock(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); } -/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. -Instruction *DIBuilder::InsertDeclare(Value *Storage, DIVariable VarInfo, +/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. +Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, Instruction *InsertBefore) { assert(Storage && "no storage passed to dbg.declare"); assert(VarInfo.Verify() && "empty DIVariable passed to dbg.declare"); @@ -751,8 +751,8 @@ Instruction *DIBuilder::InsertDeclare(Value *Storage, DIVariable VarInfo, return CallInst::Create(DeclareFn, Args, Args+2, "", InsertBefore); } -/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. -Instruction *DIBuilder::InsertDeclare(Value *Storage, DIVariable VarInfo, +/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. +Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, BasicBlock *InsertAtEnd) { assert(Storage && "no storage passed to dbg.declare"); assert(VarInfo.Verify() && "invalid DIVariable passed to dbg.declare"); @@ -769,8 +769,8 @@ Instruction *DIBuilder::InsertDeclare(Value *Storage, DIVariable VarInfo, return CallInst::Create(DeclareFn, Args, Args+2, "", InsertAtEnd); } -/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. -Instruction *DIBuilder::InsertDbgValueIntrinsic(Value *V, uint64_t Offset, +/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. +Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, DIVariable VarInfo, Instruction *InsertBefore) { assert(V && "no value passed to dbg.value"); @@ -784,8 +784,8 @@ Instruction *DIBuilder::InsertDbgValueIntrinsic(Value *V, uint64_t Offset, return CallInst::Create(ValueFn, Args, Args+3, "", InsertBefore); } -/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. -Instruction *DIBuilder::InsertDbgValueIntrinsic(Value *V, uint64_t Offset, +/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. +Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, DIVariable VarInfo, BasicBlock *InsertAtEnd) { assert(V && "no value passed to dbg.value"); diff --git a/contrib/llvm/lib/Analysis/InstructionSimplify.cpp b/contrib/llvm/lib/Analysis/InstructionSimplify.cpp index a2f9862..982dacb 100644 --- a/contrib/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/contrib/llvm/lib/Analysis/InstructionSimplify.cpp @@ -1161,6 +1161,16 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const TargetData *TD, (A == Op0 || B == Op0)) return Op0; + // ~(A & ?) | A = -1 + if (match(Op0, m_Not(m_And(m_Value(A), m_Value(B)))) && + (A == Op1 || B == Op1)) + return Constant::getAllOnesValue(Op1->getType()); + + // A | ~(A & ?) = -1 + if (match(Op1, m_Not(m_And(m_Value(A), m_Value(B)))) && + (A == Op0 || B == Op0)) + return Constant::getAllOnesValue(Op0->getType()); + // Try some generic simplifications for associative operations. if (Value *V = SimplifyAssociativeBinOp(Instruction::Or, Op0, Op1, TD, DT, MaxRecurse)) diff --git a/contrib/llvm/lib/CodeGen/AllocationOrder.h b/contrib/llvm/lib/CodeGen/AllocationOrder.h index 3db4b69..61fd8f8 100644 --- a/contrib/llvm/lib/CodeGen/AllocationOrder.h +++ b/contrib/llvm/lib/CodeGen/AllocationOrder.h @@ -47,6 +47,8 @@ public: /// rewind - Start over from the beginning. void rewind() { Pos = 0; } + /// isHint - Return true if PhysReg is a preferred register. + bool isHint(unsigned PhysReg) const { return PhysReg == Hint; } }; } // end namespace llvm diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 43e8990..9cb882e 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -764,7 +764,7 @@ bool AsmPrinter::doFinalization(Module &M) { continue; MCSymbol *Name = Mang->getSymbol(&F); - EmitVisibility(Name, V); + EmitVisibility(Name, V, false); } // Finalize debug and EH information. @@ -1820,13 +1820,17 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const { } } -void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility) const { +void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility, + bool IsDefinition) const { MCSymbolAttr Attr = MCSA_Invalid; switch (Visibility) { default: break; case GlobalValue::HiddenVisibility: - Attr = MAI->getHiddenVisibilityAttr(); + if (IsDefinition) + Attr = MAI->getHiddenVisibilityAttr(); + else + Attr = MAI->getHiddenDeclarationVisibilityAttr(); break; case GlobalValue::ProtectedVisibility: Attr = MAI->getProtectedVisibilityAttr(); diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 5106d57..780fa40 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -31,6 +31,7 @@ #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Analysis/DebugInfo.h" +#include "llvm/Analysis/DIBuilder.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" @@ -644,12 +645,12 @@ void DwarfDebug::addComplexAddress(DbgVariable *&DV, DIE *Die, for (unsigned i = 0, N = DV->getNumAddrElements(); i < N; ++i) { uint64_t Element = DV->getAddrElement(i); - if (Element == DIFactory::OpPlus) { + if (Element == DIBuilder::OpPlus) { addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); addUInt(Block, 0, dwarf::DW_FORM_udata, DV->getAddrElement(++i)); - } else if (Element == DIFactory::OpDeref) { + } else if (Element == DIBuilder::OpDeref) { addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); - } else llvm_unreachable("unknown DIFactory Opcode"); + } else llvm_unreachable("unknown DIBuilder Opcode"); } // Now attach the location information to the DIE. @@ -1894,7 +1895,7 @@ void DwarfDebug::constructCompileUnit(const MDNode *N) { DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); addString(Die, dwarf::DW_AT_producer, dwarf::DW_FORM_string, DIUnit.getProducer()); - addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data1, + addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2, DIUnit.getLanguage()); addString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN); // Use DW_AT_entry_pc instead of DW_AT_low_pc/DW_AT_high_pc pair. This diff --git a/contrib/llvm/lib/CodeGen/BranchFolding.cpp b/contrib/llvm/lib/CodeGen/BranchFolding.cpp index cb81aa3..78a8743 100644 --- a/contrib/llvm/lib/CodeGen/BranchFolding.cpp +++ b/contrib/llvm/lib/CodeGen/BranchFolding.cpp @@ -501,10 +501,11 @@ static bool ProfitableToMerge(MachineBasicBlock *MBB1, MachineBasicBlock *SuccBB, MachineBasicBlock *PredBB) { CommonTailLen = ComputeCommonTailLength(MBB1, MBB2, I1, I2); - MachineFunction *MF = MBB1->getParent(); - if (CommonTailLen == 0) return false; + DEBUG(dbgs() << "Common tail length of BB#" << MBB1->getNumber() + << " and BB#" << MBB2->getNumber() << " is " << CommonTailLen + << '\n'); // It's almost always profitable to merge any number of non-terminator // instructions with the block that falls through into the common successor. @@ -541,6 +542,7 @@ static bool ProfitableToMerge(MachineBasicBlock *MBB1, // we don't have to split a block. At worst we will be introducing 1 new // branch instruction, which is likely to be smaller than the 2 // instructions that would be deleted in the merge. + MachineFunction *MF = MBB1->getParent(); if (EffectiveTailLen >= 2 && MF->getFunction()->hasFnAttr(Attribute::OptimizeForSize) && (I1 == MBB1->begin() || I2 == MBB2->begin())) diff --git a/contrib/llvm/lib/CodeGen/InlineSpiller.cpp b/contrib/llvm/lib/CodeGen/InlineSpiller.cpp index a1bd972..38e6c85 100644 --- a/contrib/llvm/lib/CodeGen/InlineSpiller.cpp +++ b/contrib/llvm/lib/CodeGen/InlineSpiller.cpp @@ -102,8 +102,7 @@ Spiller *createInlineSpiller(MachineFunctionPass &pass, } } -/// reMaterializeFor - Attempt to rematerialize edit_->getReg() before MI instead of -/// reloading it. +/// reMaterializeFor - Attempt to rematerialize before MI instead of reloading. bool InlineSpiller::reMaterializeFor(MachineBasicBlock::iterator MI) { SlotIndex UseIdx = lis_.getInstructionIndex(MI).getUseIndex(); VNInfo *OrigVNI = edit_->getParent().getVNInfoAt(UseIdx); @@ -346,7 +345,8 @@ void InlineSpiller::spill(LiveRangeEdit &edit) { && "Trying to spill a stack slot."); DEBUG(dbgs() << "Inline spilling " << mri_.getRegClass(edit.getReg())->getName() - << ':' << edit.getParent() << "\n"); + << ':' << edit.getParent() << "\nFrom original " + << PrintReg(vrm_.getOriginal(edit.getReg())) << '\n'); assert(edit.getParent().isSpillable() && "Attempting to spill already spilled value."); @@ -357,12 +357,20 @@ void InlineSpiller::spill(LiveRangeEdit &edit) { return; rc_ = mri_.getRegClass(edit.getReg()); - stackSlot_ = vrm_.assignVirt2StackSlot(edit_->getReg()); + + // Share a stack slot among all descendants of Orig. + unsigned Orig = vrm_.getOriginal(edit.getReg()); + stackSlot_ = vrm_.getStackSlot(Orig); + if (stackSlot_ == VirtRegMap::NO_STACK_SLOT) + stackSlot_ = vrm_.assignVirt2StackSlot(Orig); + + if (Orig != edit.getReg()) + vrm_.assignVirt2StackSlot(edit.getReg(), stackSlot_); // Update LiveStacks now that we are committed to spilling. LiveInterval &stacklvr = lss_.getOrCreateInterval(stackSlot_, rc_); - assert(stacklvr.empty() && "Just created stack slot not empty"); - stacklvr.getNextValue(SlotIndex(), 0, lss_.getVNInfoAllocator()); + if (!stacklvr.hasAtLeastOneValue()) + stacklvr.getNextValue(SlotIndex(), 0, lss_.getVNInfoAllocator()); stacklvr.MergeRangesInAsValue(edit_->getParent(), stacklvr.getValNumInfo(0)); // Iterate over instructions using register. diff --git a/contrib/llvm/lib/CodeGen/LowerSubregs.cpp b/contrib/llvm/lib/CodeGen/LowerSubregs.cpp index ad1c537..7871ba9 100644 --- a/contrib/llvm/lib/CodeGen/LowerSubregs.cpp +++ b/contrib/llvm/lib/CodeGen/LowerSubregs.cpp @@ -37,7 +37,7 @@ namespace { public: static char ID; // Pass identification, replacement for typeid LowerSubregsInstructionPass() : MachineFunctionPass(ID) {} - + const char *getPassName() const { return "Subregister lowering instruction pass"; } @@ -64,8 +64,8 @@ namespace { char LowerSubregsInstructionPass::ID = 0; } -FunctionPass *llvm::createLowerSubregsPass() { - return new LowerSubregsInstructionPass(); +FunctionPass *llvm::createLowerSubregsPass() { + return new LowerSubregsInstructionPass(); } /// TransferDeadFlag - MI is a pseudo-instruction with DstReg dead, @@ -192,9 +192,9 @@ bool LowerSubregsInstructionPass::LowerCopy(MachineInstr *MI) { /// copies. /// bool LowerSubregsInstructionPass::runOnMachineFunction(MachineFunction &MF) { - DEBUG(dbgs() << "Machine Function\n" + DEBUG(dbgs() << "Machine Function\n" << "********** LOWERING SUBREG INSTRS **********\n" - << "********** Function: " + << "********** Function: " << MF.getFunction()->getName() << '\n'); TRI = MF.getTarget().getRegisterInfo(); TII = MF.getTarget().getInstrInfo(); diff --git a/contrib/llvm/lib/CodeGen/MachineFunction.cpp b/contrib/llvm/lib/CodeGen/MachineFunction.cpp index 8553240..d81e4a1 100644 --- a/contrib/llvm/lib/CodeGen/MachineFunction.cpp +++ b/contrib/llvm/lib/CodeGen/MachineFunction.cpp @@ -396,8 +396,7 @@ void MachineFunction::viewCFGOnly() const /// addLiveIn - Add the specified physical register as a live-in value and /// create a corresponding virtual register for it. unsigned MachineFunction::addLiveIn(unsigned PReg, - const TargetRegisterClass *RC, - DebugLoc DL) { + const TargetRegisterClass *RC) { MachineRegisterInfo &MRI = getRegInfo(); unsigned VReg = MRI.getLiveInVirtReg(PReg); if (VReg) { @@ -406,7 +405,6 @@ unsigned MachineFunction::addLiveIn(unsigned PReg, } VReg = MRI.createVirtualRegister(RC); MRI.addLiveIn(PReg, VReg); - MRI.addLiveInLoc(VReg, DL); return VReg; } @@ -646,6 +644,10 @@ MachineConstantPool::~MachineConstantPool() { for (unsigned i = 0, e = Constants.size(); i != e; ++i) if (Constants[i].isMachineConstantPoolEntry()) delete Constants[i].Val.MachineCPVal; + for (DenseSet<MachineConstantPoolValue*>::iterator I = + MachineCPVsSharingEntries.begin(), E = MachineCPVsSharingEntries.end(); + I != E; ++I) + delete *I; } /// CanShareConstantPoolEntry - Test whether the given two constants @@ -723,8 +725,10 @@ unsigned MachineConstantPool::getConstantPoolIndex(MachineConstantPoolValue *V, // // FIXME, this could be made much more efficient for large constant pools. int Idx = V->getExistingMachineCPValue(this, Alignment); - if (Idx != -1) + if (Idx != -1) { + MachineCPVsSharingEntries.insert(V); return (unsigned)Idx; + } Constants.push_back(MachineConstantPoolEntry(V, Alignment)); return Constants.size()-1; diff --git a/contrib/llvm/lib/CodeGen/MachineRegisterInfo.cpp b/contrib/llvm/lib/CodeGen/MachineRegisterInfo.cpp index b3fb337..7244d5f 100644 --- a/contrib/llvm/lib/CodeGen/MachineRegisterInfo.cpp +++ b/contrib/llvm/lib/CodeGen/MachineRegisterInfo.cpp @@ -210,15 +210,8 @@ MachineRegisterInfo::EmitLiveInCopies(MachineBasicBlock *EntryMBB, LiveIns.erase(LiveIns.begin() + i); --i; --e; } else { - DebugLoc DL; - // If there is a location for this live in then use it. - DenseMap<unsigned, DebugLoc>::iterator DLI = - LiveInLocs.find(LiveIns[i].second); - if (DLI != LiveInLocs.end()) - DL = DLI->second; - // Emit a copy. - BuildMI(*EntryMBB, EntryMBB->begin(), DL, + BuildMI(*EntryMBB, EntryMBB->begin(), DebugLoc(), TII.get(TargetOpcode::COPY), LiveIns[i].second) .addReg(LiveIns[i].first); diff --git a/contrib/llvm/lib/CodeGen/RegAllocBase.h b/contrib/llvm/lib/CodeGen/RegAllocBase.h index 8c7e5f5..5af0ce7 100644 --- a/contrib/llvm/lib/CodeGen/RegAllocBase.h +++ b/contrib/llvm/lib/CodeGen/RegAllocBase.h @@ -39,7 +39,6 @@ #include "llvm/ADT/OwningPtr.h" #include "LiveIntervalUnion.h" -#include <queue> namespace llvm { @@ -58,8 +57,8 @@ class LiveVirtRegQueue; /// be extended to add interesting heuristics. /// /// Register allocators must override the selectOrSplit() method to implement -/// live range splitting. They may also override getPriority() which otherwise -/// defaults to the spill weight computed by CalculateSpillWeights. +/// live range splitting. They must also override enqueue/dequeue to provide an +/// assignment order. class RegAllocBase { LiveIntervalUnion::Allocator UnionAllocator; protected: @@ -120,9 +119,11 @@ protected: // Get a temporary reference to a Spiller instance. virtual Spiller &spiller() = 0; - // getPriority - Calculate the allocation priority for VirtReg. - // Virtual registers with higher priorities are allocated first. - virtual float getPriority(LiveInterval *LI) = 0; + /// enqueue - Add VirtReg to the priority queue of unassigned registers. + virtual void enqueue(LiveInterval *LI) = 0; + + /// dequeue - Return the next unassigned register, or NULL. + virtual LiveInterval *dequeue() = 0; // A RegAlloc pass should override this to provide the allocation heuristics. // Each call must guarantee forward progess by returning an available PhysReg @@ -170,7 +171,7 @@ public: static bool VerifyEnabled; private: - void seedLiveVirtRegs(std::priority_queue<std::pair<float, unsigned> >&); + void seedLiveRegs(); void spillReg(LiveInterval &VirtReg, unsigned PhysReg, SmallVectorImpl<LiveInterval*> &SplitVRegs); diff --git a/contrib/llvm/lib/CodeGen/RegAllocBasic.cpp b/contrib/llvm/lib/CodeGen/RegAllocBasic.cpp index 045c8db..6923908 100644 --- a/contrib/llvm/lib/CodeGen/RegAllocBasic.cpp +++ b/contrib/llvm/lib/CodeGen/RegAllocBasic.cpp @@ -45,6 +45,7 @@ #include "llvm/Support/Timer.h" #include <cstdlib> +#include <queue> using namespace llvm; @@ -65,6 +66,14 @@ const char *RegAllocBase::TimerGroupName = "Register Allocation"; bool RegAllocBase::VerifyEnabled = false; namespace { + struct CompSpillWeight { + bool operator()(LiveInterval *A, LiveInterval *B) const { + return A->weight < B->weight; + } + }; +} + +namespace { /// RABasic provides a minimal implementation of the basic register allocation /// algorithm. It prioritizes live virtual registers by spill weight and spills /// whenever a register is unavailable. This is not practical in production but @@ -82,7 +91,8 @@ class RABasic : public MachineFunctionPass, public RegAllocBase // state std::auto_ptr<Spiller> SpillerInstance; - + std::priority_queue<LiveInterval*, std::vector<LiveInterval*>, + CompSpillWeight> Queue; public: RABasic(); @@ -100,6 +110,18 @@ public: virtual float getPriority(LiveInterval *LI) { return LI->weight; } + virtual void enqueue(LiveInterval *LI) { + Queue.push(LI); + } + + virtual LiveInterval *dequeue() { + if (Queue.empty()) + return 0; + LiveInterval *LI = Queue.top(); + Queue.pop(); + return LI; + } + virtual unsigned selectOrSplit(LiveInterval &VirtReg, SmallVectorImpl<LiveInterval*> &SplitVRegs); @@ -227,18 +249,17 @@ void RegAllocBase::releaseMemory() { PhysReg2LiveUnion.clear(); } -// Visit all the live virtual registers. If they are already assigned to a -// physical register, unify them with the corresponding LiveIntervalUnion, -// otherwise push them on the priority queue for later assignment. -void RegAllocBase:: -seedLiveVirtRegs(std::priority_queue<std::pair<float, unsigned> > &VirtRegQ) { +// Visit all the live registers. If they are already assigned to a physical +// register, unify them with the corresponding LiveIntervalUnion, otherwise push +// them on the priority queue for later assignment. +void RegAllocBase::seedLiveRegs() { for (LiveIntervals::iterator I = LIS->begin(), E = LIS->end(); I != E; ++I) { unsigned RegNum = I->first; LiveInterval &VirtReg = *I->second; if (TargetRegisterInfo::isPhysicalRegister(RegNum)) PhysReg2LiveUnion[RegNum].unify(VirtReg); else - VirtRegQ.push(std::make_pair(getPriority(&VirtReg), RegNum)); + enqueue(&VirtReg); } } @@ -263,38 +284,31 @@ void RegAllocBase::unassign(LiveInterval &VirtReg, unsigned PhysReg) { // Top-level driver to manage the queue of unassigned VirtRegs and call the // selectOrSplit implementation. void RegAllocBase::allocatePhysRegs() { - - // Push each vreg onto a queue or "precolor" by adding it to a physreg union. - std::priority_queue<std::pair<float, unsigned> > VirtRegQ; - seedLiveVirtRegs(VirtRegQ); + seedLiveRegs(); // Continue assigning vregs one at a time to available physical registers. - while (!VirtRegQ.empty()) { - // Pop the highest priority vreg. - LiveInterval &VirtReg = LIS->getInterval(VirtRegQ.top().second); - VirtRegQ.pop(); - + while (LiveInterval *VirtReg = dequeue()) { // selectOrSplit requests the allocator to return an available physical // register if possible and populate a list of new live intervals that // result from splitting. - DEBUG(dbgs() << "\nselectOrSplit " << MRI->getRegClass(VirtReg.reg)->getName() - << ':' << VirtReg << '\n'); + DEBUG(dbgs() << "\nselectOrSplit " + << MRI->getRegClass(VirtReg->reg)->getName() + << ':' << *VirtReg << '\n'); typedef SmallVector<LiveInterval*, 4> VirtRegVec; VirtRegVec SplitVRegs; - unsigned AvailablePhysReg = selectOrSplit(VirtReg, SplitVRegs); + unsigned AvailablePhysReg = selectOrSplit(*VirtReg, SplitVRegs); if (AvailablePhysReg) - assign(VirtReg, AvailablePhysReg); + assign(*VirtReg, AvailablePhysReg); for (VirtRegVec::iterator I = SplitVRegs.begin(), E = SplitVRegs.end(); I != E; ++I) { - LiveInterval* SplitVirtReg = *I; + LiveInterval *SplitVirtReg = *I; if (SplitVirtReg->empty()) continue; DEBUG(dbgs() << "queuing new interval: " << *SplitVirtReg << "\n"); assert(TargetRegisterInfo::isVirtualRegister(SplitVirtReg->reg) && "expect split value in virtual register"); - VirtRegQ.push(std::make_pair(getPriority(SplitVirtReg), - SplitVirtReg->reg)); + enqueue(SplitVirtReg); ++NumNewQueued; } } diff --git a/contrib/llvm/lib/CodeGen/RegAllocGreedy.cpp b/contrib/llvm/lib/CodeGen/RegAllocGreedy.cpp index c1372cd..406485a 100644 --- a/contrib/llvm/lib/CodeGen/RegAllocGreedy.cpp +++ b/contrib/llvm/lib/CodeGen/RegAllocGreedy.cpp @@ -43,6 +43,8 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Timer.h" +#include <queue> + using namespace llvm; STATISTIC(NumGlobalSplits, "Number of split global live ranges"); @@ -71,6 +73,8 @@ class RAGreedy : public MachineFunctionPass, public RegAllocBase { // state std::auto_ptr<Spiller> SpillerInstance; std::auto_ptr<SplitAnalysis> SA; + std::priority_queue<std::pair<unsigned, unsigned> > Queue; + IndexedMap<unsigned, VirtReg2IndexFunctor> Generation; // splitting state. @@ -91,13 +95,10 @@ public: /// RAGreedy analysis usage. virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual void releaseMemory(); - virtual Spiller &spiller() { return *SpillerInstance; } - - virtual float getPriority(LiveInterval *LI); - + virtual void enqueue(LiveInterval *LI); + virtual LiveInterval *dequeue(); virtual unsigned selectOrSplit(LiveInterval&, SmallVectorImpl<LiveInterval*>&); @@ -119,9 +120,12 @@ private: SlotIndex getPrevMappedIndex(const MachineInstr*); void calcPrevSlots(); unsigned nextSplitPoint(unsigned); + bool canEvictInterference(LiveInterval&, unsigned, unsigned, float&); - unsigned tryReassignOrEvict(LiveInterval&, AllocationOrder&, + unsigned tryReassign(LiveInterval&, AllocationOrder&, SmallVectorImpl<LiveInterval*>&); + unsigned tryEvict(LiveInterval&, AllocationOrder&, + SmallVectorImpl<LiveInterval*>&); unsigned tryRegionSplit(LiveInterval&, AllocationOrder&, SmallVectorImpl<LiveInterval*>&); unsigned tryLocalSplit(LiveInterval&, AllocationOrder&, @@ -183,25 +187,42 @@ void RAGreedy::getAnalysisUsage(AnalysisUsage &AU) const { void RAGreedy::releaseMemory() { SpillerInstance.reset(0); + Generation.clear(); RegAllocBase::releaseMemory(); } -float RAGreedy::getPriority(LiveInterval *LI) { - float Priority = LI->weight; - - // Prioritize hinted registers so they are allocated first. - std::pair<unsigned, unsigned> Hint; - if (Hint.first || Hint.second) { - // The hint can be target specific, a virtual register, or a physreg. - Priority *= 2; - - // Prefer physreg hints above anything else. - if (Hint.first == 0 && TargetRegisterInfo::isPhysicalRegister(Hint.second)) - Priority *= 2; - } - return Priority; +void RAGreedy::enqueue(LiveInterval *LI) { + // Prioritize live ranges by size, assigning larger ranges first. + // The queue holds (size, reg) pairs. + const unsigned Size = LI->getSize(); + const unsigned Reg = LI->reg; + assert(TargetRegisterInfo::isVirtualRegister(Reg) && + "Can only enqueue virtual registers"); + const unsigned Hint = VRM->getRegAllocPref(Reg); + unsigned Prio; + + Generation.grow(Reg); + if (++Generation[Reg] == 1) + // 1st generation ranges are handled first, long -> short. + Prio = (1u << 31) + Size; + else + // Repeat offenders are handled second, short -> long + Prio = (1u << 30) - Size; + + // Boost ranges that have a physical register hint. + if (TargetRegisterInfo::isPhysicalRegister(Hint)) + Prio |= (1u << 30); + + Queue.push(std::make_pair(Prio, Reg)); } +LiveInterval *RAGreedy::dequeue() { + if (Queue.empty()) + return 0; + LiveInterval *LI = &LIS->getInterval(Queue.top().second); + Queue.pop(); + return LI; +} //===----------------------------------------------------------------------===// // Register Reassignment @@ -230,8 +251,7 @@ LiveInterval *RAGreedy::getSingleInterference(LiveInterval &VirtReg, if (Q.checkInterference()) { if (Interference) return 0; - Q.collectInterferingVRegs(1); - if (!Q.seenAllInterferences()) + if (Q.collectInterferingVRegs(2) > 1) return 0; Interference = Q.interferingVRegs().front(); } @@ -276,21 +296,14 @@ bool RAGreedy::reassignVReg(LiveInterval &InterferingVReg, return false; } -/// tryReassignOrEvict - Try to reassign a single interferences to a different -/// physreg, or evict a single interference with a lower spill weight. +/// tryReassign - Try to reassign a single interference to a different physreg. /// @param VirtReg Currently unassigned virtual register. /// @param Order Physregs to try. /// @return Physreg to assign VirtReg, or 0. -unsigned RAGreedy::tryReassignOrEvict(LiveInterval &VirtReg, - AllocationOrder &Order, - SmallVectorImpl<LiveInterval*> &NewVRegs){ +unsigned RAGreedy::tryReassign(LiveInterval &VirtReg, AllocationOrder &Order, + SmallVectorImpl<LiveInterval*> &NewVRegs){ NamedRegionTimer T("Reassign", TimerGroupName, TimePassesIsEnabled); - // Keep track of the lightest single interference seen so far. - float BestWeight = VirtReg.weight; - LiveInterval *BestVirt = 0; - unsigned BestPhys = 0; - Order.rewind(); while (unsigned PhysReg = Order.next()) { LiveInterval *InterferingVReg = getSingleInterference(VirtReg, PhysReg); @@ -300,25 +313,92 @@ unsigned RAGreedy::tryReassignOrEvict(LiveInterval &VirtReg, continue; if (reassignVReg(*InterferingVReg, PhysReg)) return PhysReg; + } + return 0; +} + + +//===----------------------------------------------------------------------===// +// Interference eviction +//===----------------------------------------------------------------------===// + +/// canEvict - Return true if all interferences between VirtReg and PhysReg can +/// be evicted. Set maxWeight to the maximal spill weight of an interference. +bool RAGreedy::canEvictInterference(LiveInterval &VirtReg, unsigned PhysReg, + unsigned Size, float &MaxWeight) { + float Weight = 0; + for (const unsigned *AliasI = TRI->getOverlaps(PhysReg); *AliasI; ++AliasI) { + LiveIntervalUnion::Query &Q = query(VirtReg, *AliasI); + // If there is 10 or more interferences, chances are one is smaller. + if (Q.collectInterferingVRegs(10) >= 10) + return false; - // Cannot reassign, is this an eviction candidate? - if (InterferingVReg->weight < BestWeight) { - BestVirt = InterferingVReg; - BestPhys = PhysReg; - BestWeight = InterferingVReg->weight; + // CHeck if any interfering live range is shorter than VirtReg. + for (unsigned i = 0, e = Q.interferingVRegs().size(); i != e; ++i) { + LiveInterval *Intf = Q.interferingVRegs()[i]; + if (TargetRegisterInfo::isPhysicalRegister(Intf->reg)) + return false; + if (Intf->getSize() <= Size) + return false; + Weight = std::max(Weight, Intf->weight); } } + MaxWeight = Weight; + return true; +} + +/// tryEvict - Try to evict all interferences for a physreg. +/// @param VirtReg Currently unassigned virtual register. +/// @param Order Physregs to try. +/// @return Physreg to assign VirtReg, or 0. +unsigned RAGreedy::tryEvict(LiveInterval &VirtReg, + AllocationOrder &Order, + SmallVectorImpl<LiveInterval*> &NewVRegs){ + NamedRegionTimer T("Evict", TimerGroupName, TimePassesIsEnabled); + + // We can only evict interference if all interfering registers are virtual and + // longer than VirtReg. + const unsigned Size = VirtReg.getSize(); + + // Keep track of the lightest single interference seen so far. + float BestWeight = 0; + unsigned BestPhys = 0; - // Nothing reassigned, can we evict a lighter single interference? - if (BestVirt) { - DEBUG(dbgs() << "evicting lighter " << *BestVirt << '\n'); - unassign(*BestVirt, VRM->getPhys(BestVirt->reg)); - ++NumEvicted; - NewVRegs.push_back(BestVirt); - return BestPhys; + Order.rewind(); + while (unsigned PhysReg = Order.next()) { + float Weight = 0; + if (!canEvictInterference(VirtReg, PhysReg, Size, Weight)) + continue; + + // This is an eviction candidate. + DEBUG(dbgs() << "max " << PrintReg(PhysReg, TRI) << " interference = " + << Weight << '\n'); + if (BestPhys && Weight >= BestWeight) + continue; + + // Best so far. + BestPhys = PhysReg; + BestWeight = Weight; + // Stop if the hint can be used. + if (Order.isHint(PhysReg)) + break; } - return 0; + if (!BestPhys) + return 0; + + DEBUG(dbgs() << "evicting " << PrintReg(BestPhys, TRI) << " interference\n"); + for (const unsigned *AliasI = TRI->getOverlaps(BestPhys); *AliasI; ++AliasI) { + LiveIntervalUnion::Query &Q = query(VirtReg, *AliasI); + assert(Q.seenAllInterferences() && "Didn't check all interfererences."); + for (unsigned i = 0, e = Q.interferingVRegs().size(); i != e; ++i) { + LiveInterval *Intf = Q.interferingVRegs()[i]; + unassign(*Intf, VRM->getPhys(Intf->reg)); + ++NumEvicted; + NewVRegs.push_back(Intf); + } + } + return BestPhys; } @@ -426,8 +506,13 @@ float RAGreedy::calcInterferenceInfo(LiveInterval &VirtReg, unsigned PhysReg) { if (!IntI.valid()) break; // Not live in, but before the first use. - if (IntI.start() < BI.FirstUse) + if (IntI.start() < BI.FirstUse) { BC.Entry = SpillPlacement::PrefSpill; + // If the block contains a kill from an earlier split, never split + // again in the same block. + if (!BI.LiveThrough && !SA->isOriginalEndpoint(BI.Kill)) + BC.Entry = SpillPlacement::MustSpill; + } } // Does interference overlap the uses in the entry segment @@ -458,8 +543,12 @@ float RAGreedy::calcInterferenceInfo(LiveInterval &VirtReg, unsigned PhysReg) { IntI.advanceTo(BI.LastUse); if (!IntI.valid()) break; - if (IntI.start() < Stop) + if (IntI.start() < Stop) { BC.Exit = SpillPlacement::PrefSpill; + // Avoid splitting twice in the same block. + if (!BI.LiveThrough && !SA->isOriginalEndpoint(BI.Def)) + BC.Exit = SpillPlacement::MustSpill; + } } } } @@ -1221,12 +1310,22 @@ unsigned RAGreedy::selectOrSplit(LiveInterval &VirtReg, return PhysReg; } - // Try to reassign interferences. - if (unsigned PhysReg = tryReassignOrEvict(VirtReg, Order, NewVRegs)) + if (unsigned PhysReg = tryReassign(VirtReg, Order, NewVRegs)) + return PhysReg; + + if (unsigned PhysReg = tryEvict(VirtReg, Order, NewVRegs)) return PhysReg; assert(NewVRegs.empty() && "Cannot append to existing NewVRegs"); + // The first time we see a live range, don't try to split or spill. + // Wait until the second time, when all smaller ranges have been allocated. + // This gives a better picture of the interference to split around. + if (Generation[VirtReg.reg] == 1) { + NewVRegs.push_back(&VirtReg); + return 0; + } + // Try splitting VirtReg or interferences. unsigned PhysReg = trySplit(VirtReg, Order, NewVRegs); if (PhysReg || !NewVRegs.empty()) diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 9035602..9cc70a3 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -279,8 +279,8 @@ namespace { /// getShiftAmountTy - Returns a type large enough to hold any valid /// shift amount - before type legalization these can be huge. - EVT getShiftAmountTy() { - return LegalTypes ? TLI.getShiftAmountTy() : TLI.getPointerTy(); + EVT getShiftAmountTy(EVT LHSTy) { + return LegalTypes ? TLI.getShiftAmountTy(LHSTy) : TLI.getPointerTy(); } /// isTypeLegal - This method returns true if we are running before type @@ -670,7 +670,7 @@ SDValue DAGCombiner::PromoteOperand(SDValue Op, EVT PVT, bool &Replace) { if (LoadSDNode *LD = dyn_cast<LoadSDNode>(Op)) { EVT MemVT = LD->getMemoryVT(); ISD::LoadExtType ExtType = ISD::isNON_EXTLoad(LD) - ? (TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT) ? ISD::ZEXTLOAD + ? (TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT) ? ISD::ZEXTLOAD : ISD::EXTLOAD) : LD->getExtensionType(); Replace = true; @@ -894,7 +894,7 @@ bool DAGCombiner::PromoteLoad(SDValue Op) { LoadSDNode *LD = cast<LoadSDNode>(N); EVT MemVT = LD->getMemoryVT(); ISD::LoadExtType ExtType = ISD::isNON_EXTLoad(LD) - ? (TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT) ? ISD::ZEXTLOAD + ? (TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT) ? ISD::ZEXTLOAD : ISD::EXTLOAD) : LD->getExtensionType(); SDValue NewLD = DAG.getExtLoad(ExtType, dl, PVT, @@ -1521,7 +1521,7 @@ SDValue DAGCombiner::visitADDE(SDNode *N) { // Since it may not be valid to emit a fold to zero for vector initializers // check if we can before folding. static SDValue tryFoldToZero(DebugLoc DL, const TargetLowering &TLI, EVT VT, - SelectionDAG &DAG, bool LegalOperations) { + SelectionDAG &DAG, bool LegalOperations) { if (!VT.isVector()) { return DAG.getConstant(0, VT); } else if (!LegalOperations || TLI.isOperationLegal(ISD::BUILD_VECTOR, VT)) { @@ -1647,7 +1647,7 @@ SDValue DAGCombiner::visitMUL(SDNode *N) { if (N1C && N1C->getAPIntValue().isPowerOf2()) return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0, DAG.getConstant(N1C->getAPIntValue().logBase2(), - getShiftAmountTy())); + getShiftAmountTy(N0.getValueType()))); // fold (mul x, -(1 << c)) -> -(x << c) or (-x) << c if (N1C && (-N1C->getAPIntValue()).isPowerOf2()) { unsigned Log2Val = (-N1C->getAPIntValue()).logBase2(); @@ -1656,7 +1656,8 @@ SDValue DAGCombiner::visitMUL(SDNode *N) { return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, DAG.getConstant(0, VT), DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0, - DAG.getConstant(Log2Val, getShiftAmountTy()))); + DAG.getConstant(Log2Val, + getShiftAmountTy(N0.getValueType())))); } // (mul (shl X, c1), c2) -> (mul X, c2 << c1) if (N1C && N0.getOpcode() == ISD::SHL && @@ -1753,18 +1754,18 @@ SDValue DAGCombiner::visitSDIV(SDNode *N) { // Splat the sign bit into the register SDValue SGN = DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, N0, DAG.getConstant(VT.getSizeInBits()-1, - getShiftAmountTy())); + getShiftAmountTy(N0.getValueType()))); AddToWorkList(SGN.getNode()); // Add (N0 < 0) ? abs2 - 1 : 0; SDValue SRL = DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, SGN, DAG.getConstant(VT.getSizeInBits() - lg2, - getShiftAmountTy())); + getShiftAmountTy(SGN.getValueType()))); SDValue ADD = DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, N0, SRL); AddToWorkList(SRL.getNode()); AddToWorkList(ADD.getNode()); // Divide by pow2 SDValue SRA = DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, ADD, - DAG.getConstant(lg2, getShiftAmountTy())); + DAG.getConstant(lg2, getShiftAmountTy(ADD.getValueType()))); // If we're dividing by a positive value, we're done. Otherwise, we must // negate the result. @@ -1814,7 +1815,7 @@ SDValue DAGCombiner::visitUDIV(SDNode *N) { if (N1C && N1C->getAPIntValue().isPowerOf2()) return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0, DAG.getConstant(N1C->getAPIntValue().logBase2(), - getShiftAmountTy())); + getShiftAmountTy(N0.getValueType()))); // fold (udiv x, (shl c, y)) -> x >>u (log2(c)+y) iff c is power of 2 if (N1.getOpcode() == ISD::SHL) { if (ConstantSDNode *SHC = dyn_cast<ConstantSDNode>(N1.getOperand(0))) { @@ -1955,7 +1956,7 @@ SDValue DAGCombiner::visitMULHS(SDNode *N) { if (N1C && N1C->getAPIntValue() == 1) return DAG.getNode(ISD::SRA, N->getDebugLoc(), N0.getValueType(), N0, DAG.getConstant(N0.getValueType().getSizeInBits() - 1, - getShiftAmountTy())); + getShiftAmountTy(N0.getValueType()))); // fold (mulhs x, undef) -> 0 if (N0.getOpcode() == ISD::UNDEF || N1.getOpcode() == ISD::UNDEF) return DAG.getConstant(0, VT); @@ -1971,11 +1972,11 @@ SDValue DAGCombiner::visitMULHS(SDNode *N) { N1 = DAG.getNode(ISD::SIGN_EXTEND, DL, NewVT, N1); N1 = DAG.getNode(ISD::MUL, DL, NewVT, N0, N1); N1 = DAG.getNode(ISD::SRL, DL, NewVT, N1, - DAG.getConstant(SimpleSize, getShiftAmountTy())); + DAG.getConstant(SimpleSize, getShiftAmountTy(N1.getValueType()))); return DAG.getNode(ISD::TRUNCATE, DL, VT, N1); } } - + return SDValue(); } @@ -2007,11 +2008,11 @@ SDValue DAGCombiner::visitMULHU(SDNode *N) { N1 = DAG.getNode(ISD::ZERO_EXTEND, DL, NewVT, N1); N1 = DAG.getNode(ISD::MUL, DL, NewVT, N0, N1); N1 = DAG.getNode(ISD::SRL, DL, NewVT, N1, - DAG.getConstant(SimpleSize, getShiftAmountTy())); + DAG.getConstant(SimpleSize, getShiftAmountTy(N1.getValueType()))); return DAG.getNode(ISD::TRUNCATE, DL, VT, N1); } } - + return SDValue(); } @@ -2090,14 +2091,14 @@ SDValue DAGCombiner::visitSMUL_LOHI(SDNode *N) { Lo = DAG.getNode(ISD::MUL, DL, NewVT, Lo, Hi); // Compute the high part as N1. Hi = DAG.getNode(ISD::SRL, DL, NewVT, Lo, - DAG.getConstant(SimpleSize, getShiftAmountTy())); + DAG.getConstant(SimpleSize, getShiftAmountTy(Lo.getValueType()))); Hi = DAG.getNode(ISD::TRUNCATE, DL, VT, Hi); // Compute the low part as N0. Lo = DAG.getNode(ISD::TRUNCATE, DL, VT, Lo); return CombineTo(N, Lo, Hi); } } - + return SDValue(); } @@ -2107,7 +2108,7 @@ SDValue DAGCombiner::visitUMUL_LOHI(SDNode *N) { EVT VT = N->getValueType(0); DebugLoc DL = N->getDebugLoc(); - + // If the type twice as wide is legal, transform the mulhu to a wider multiply // plus a shift. if (VT.isSimple() && !VT.isVector()) { @@ -2120,14 +2121,14 @@ SDValue DAGCombiner::visitUMUL_LOHI(SDNode *N) { Lo = DAG.getNode(ISD::MUL, DL, NewVT, Lo, Hi); // Compute the high part as N1. Hi = DAG.getNode(ISD::SRL, DL, NewVT, Lo, - DAG.getConstant(SimpleSize, getShiftAmountTy())); + DAG.getConstant(SimpleSize, getShiftAmountTy(Lo.getValueType()))); Hi = DAG.getNode(ISD::TRUNCATE, DL, VT, Hi); // Compute the low part as N0. Lo = DAG.getNode(ISD::TRUNCATE, DL, VT, Lo); return CombineTo(N, Lo, Hi); } } - + return SDValue(); } @@ -3004,7 +3005,7 @@ SDValue DAGCombiner::visitSHL(SDNode *N) { N0.getOpcode() == ISD::SIGN_EXTEND) && N0.getOperand(0).getOpcode() == ISD::SHL && isa<ConstantSDNode>(N0.getOperand(0)->getOperand(1))) { - uint64_t c1 = + uint64_t c1 = cast<ConstantSDNode>(N0.getOperand(0)->getOperand(1))->getZExtValue(); uint64_t c2 = N1C->getZExtValue(); EVT InnerShiftVT = N0.getOperand(0).getValueType(); @@ -3133,7 +3134,8 @@ SDValue DAGCombiner::visitSRA(SDNode *N) { TLI.isOperationLegalOrCustom(ISD::TRUNCATE, VT) && TLI.isTruncateFree(VT, TruncVT)) { - SDValue Amt = DAG.getConstant(ShiftAmt, getShiftAmountTy()); + SDValue Amt = DAG.getConstant(ShiftAmt, + getShiftAmountTy(N0.getOperand(0).getValueType())); SDValue Shift = DAG.getNode(ISD::SRL, N0.getDebugLoc(), VT, N0.getOperand(0), Amt); SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), TruncVT, @@ -3180,7 +3182,7 @@ SDValue DAGCombiner::visitSRA(SDNode *N) { LargeShiftAmt->getZExtValue()) { SDValue Amt = DAG.getConstant(LargeShiftAmt->getZExtValue() + N1C->getZExtValue(), - getShiftAmountTy()); + getShiftAmountTy(N0.getOperand(0).getOperand(0).getValueType())); SDValue SRA = DAG.getNode(ISD::SRA, N->getDebugLoc(), LargeVT, N0.getOperand(0).getOperand(0), Amt); return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, SRA); @@ -3245,7 +3247,7 @@ SDValue DAGCombiner::visitSRL(SDNode *N) { if (N1C && N0.getOpcode() == ISD::TRUNCATE && N0.getOperand(0).getOpcode() == ISD::SRL && isa<ConstantSDNode>(N0.getOperand(0)->getOperand(1))) { - uint64_t c1 = + uint64_t c1 = cast<ConstantSDNode>(N0.getOperand(0)->getOperand(1))->getZExtValue(); uint64_t c2 = N1C->getZExtValue(); EVT InnerShiftVT = N0.getOperand(0).getValueType(); @@ -3256,7 +3258,7 @@ SDValue DAGCombiner::visitSRL(SDNode *N) { if (c1 + c2 >= InnerShiftSize) return DAG.getConstant(0, VT); return DAG.getNode(ISD::TRUNCATE, N0->getDebugLoc(), VT, - DAG.getNode(ISD::SRL, N0->getDebugLoc(), InnerShiftVT, + DAG.getNode(ISD::SRL, N0->getDebugLoc(), InnerShiftVT, N0.getOperand(0)->getOperand(0), DAG.getConstant(c1 + c2, ShiftCountVT))); } @@ -3320,7 +3322,7 @@ SDValue DAGCombiner::visitSRL(SDNode *N) { if (ShAmt) { Op = DAG.getNode(ISD::SRL, N0.getDebugLoc(), VT, Op, - DAG.getConstant(ShAmt, getShiftAmountTy())); + DAG.getConstant(ShAmt, getShiftAmountTy(Op.getValueType()))); AddToWorkList(Op.getNode()); } @@ -3685,7 +3687,9 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) { } // fold (sext (load x)) -> (sext (truncate (sextload x))) - if (ISD::isNON_EXTLoad(N0.getNode()) && + // None of the supported targets knows how to perform load and sign extend + // in one instruction. We only perform this transformation on scalars. + if (ISD::isNON_EXTLoad(N0.getNode()) && !VT.isVector() && ((!LegalOperations && !cast<LoadSDNode>(N0)->isVolatile()) || TLI.isLoadExtLegal(ISD::SEXTLOAD, N0.getValueType()))) { bool DoXform = true; @@ -3887,7 +3891,9 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) { } // fold (zext (load x)) -> (zext (truncate (zextload x))) - if (ISD::isNON_EXTLoad(N0.getNode()) && + // None of the supported targets knows how to perform load and vector_zext + // in one instruction. We only perform this transformation on scalar zext. + if (ISD::isNON_EXTLoad(N0.getNode()) && !VT.isVector() && ((!LegalOperations && !cast<LoadSDNode>(N0)->isVolatile()) || TLI.isLoadExtLegal(ISD::ZEXTLOAD, N0.getValueType()))) { bool DoXform = true; @@ -4021,11 +4027,11 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) { } DebugLoc DL = N->getDebugLoc(); - - // Ensure that the shift amount is wide enough for the shifted value. + + // Ensure that the shift amount is wide enough for the shifted value. if (VT.getSizeInBits() >= 256) ShAmt = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i32, ShAmt); - + return DAG.getNode(N0.getOpcode(), DL, VT, DAG.getNode(ISD::ZERO_EXTEND, DL, VT, N0.getOperand(0)), ShAmt); @@ -4094,7 +4100,9 @@ SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) { } // fold (aext (load x)) -> (aext (truncate (extload x))) - if (ISD::isNON_EXTLoad(N0.getNode()) && + // None of the supported targets knows how to perform load and any_ext + // in one instruction. We only perform this transformation on scalars. + if (ISD::isNON_EXTLoad(N0.getNode()) && !VT.isVector() && ((!LegalOperations && !cast<LoadSDNode>(N0)->isVolatile()) || TLI.isLoadExtLegal(ISD::EXTLOAD, N0.getValueType()))) { bool DoXform = true; @@ -4272,12 +4280,12 @@ SDValue DAGCombiner::ReduceLoadWidth(SDNode *N) { return SDValue(); unsigned EVTBits = ExtVT.getSizeInBits(); - + // Do not generate loads of non-round integer types since these can // be expensive (and would be wrong if the type is not byte sized). if (!ExtVT.isRound()) return SDValue(); - + unsigned ShAmt = 0; if (N0.getOpcode() == ISD::SRL && N0.hasOneUse()) { if (ConstantSDNode *N01 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) { @@ -4292,7 +4300,7 @@ SDValue DAGCombiner::ReduceLoadWidth(SDNode *N) { // At this point, we must have a load or else we can't do the transform. if (!isa<LoadSDNode>(N0)) return SDValue(); - + // If the shift amount is larger than the input type then we're not // accessing any of the loaded bytes. If the load was a zextload/extload // then the result of the shift+trunc is zero/undef (handled elsewhere). @@ -4313,18 +4321,18 @@ SDValue DAGCombiner::ReduceLoadWidth(SDNode *N) { N0 = N0.getOperand(0); } } - + // If we haven't found a load, we can't narrow it. Don't transform one with // multiple uses, this would require adding a new load. if (!isa<LoadSDNode>(N0) || !N0.hasOneUse() || // Don't change the width of a volatile load. cast<LoadSDNode>(N0)->isVolatile()) return SDValue(); - + // Verify that we are actually reducing a load width here. if (cast<LoadSDNode>(N0)->getMemoryVT().getSizeInBits() < EVTBits) return SDValue(); - + LoadSDNode *LN0 = cast<LoadSDNode>(N0); EVT PtrType = N0.getOperand(1).getValueType(); @@ -4362,7 +4370,7 @@ SDValue DAGCombiner::ReduceLoadWidth(SDNode *N) { // Shift the result left, if we've swallowed a left shift. SDValue Result = Load; if (ShLeftAmt != 0) { - EVT ShImmTy = getShiftAmountTy(); + EVT ShImmTy = getShiftAmountTy(Result.getValueType()); if (!isUIntN(ShImmTy.getSizeInBits(), ShLeftAmt)) ShImmTy = VT; Result = DAG.getNode(ISD::SHL, N0.getDebugLoc(), VT, @@ -4504,14 +4512,17 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { } // See if we can simplify the input to this truncate through knowledge that - // only the low bits are being used. For example "trunc (or (shl x, 8), y)" - // -> trunc y - SDValue Shorter = - GetDemandedBits(N0, APInt::getLowBitsSet(N0.getValueSizeInBits(), - VT.getSizeInBits())); - if (Shorter.getNode()) - return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, Shorter); - + // only the low bits are being used. + // For example "trunc (or (shl x, 8), y)" // -> trunc y + // Currenly we only perform this optimization on scalars because vectors + // may have different active low bits. + if (!VT.isVector()) { + SDValue Shorter = + GetDemandedBits(N0, APInt::getLowBitsSet(N0.getValueSizeInBits(), + VT.getSizeInBits())); + if (Shorter.getNode()) + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, Shorter); + } // fold (truncate (load x)) -> (smaller load x) // fold (truncate (srl (load x), c)) -> (smaller load (x+c/evtbits)) if (!LegalTypes || TLI.isTypeDesirableForOp(N0.getOpcode(), VT)) { @@ -5975,7 +5986,8 @@ ShrinkLoadReplaceStoreWithStore(const std::pair<unsigned, unsigned> &MaskInfo, // shifted by ByteShift and truncated down to NumBytes. if (ByteShift) IVal = DAG.getNode(ISD::SRL, IVal->getDebugLoc(), IVal.getValueType(), IVal, - DAG.getConstant(ByteShift*8, DC->getShiftAmountTy())); + DAG.getConstant(ByteShift*8, + DC->getShiftAmountTy(IVal.getValueType()))); // Figure out the offset for the store and the alignment of the access. unsigned StOffset; @@ -6390,7 +6402,7 @@ SDValue DAGCombiner::visitINSERT_VECTOR_ELT(SDNode *N) { EVT VT = InVec.getValueType(); - // If we can't generate a legal BUILD_VECTOR, exit + // If we can't generate a legal BUILD_VECTOR, exit if (LegalOperations && !TLI.isOperationLegal(ISD::BUILD_VECTOR, VT)) return SDValue(); @@ -7098,7 +7110,8 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, if (N2C && ((N2C->getAPIntValue() & (N2C->getAPIntValue()-1)) == 0)) { unsigned ShCtV = N2C->getAPIntValue().logBase2(); ShCtV = XType.getSizeInBits()-ShCtV-1; - SDValue ShCt = DAG.getConstant(ShCtV, getShiftAmountTy()); + SDValue ShCt = DAG.getConstant(ShCtV, + getShiftAmountTy(N0.getValueType())); SDValue Shift = DAG.getNode(ISD::SRL, N0.getDebugLoc(), XType, N0, ShCt); AddToWorkList(Shift.getNode()); @@ -7114,7 +7127,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, SDValue Shift = DAG.getNode(ISD::SRA, N0.getDebugLoc(), XType, N0, DAG.getConstant(XType.getSizeInBits()-1, - getShiftAmountTy())); + getShiftAmountTy(N0.getValueType()))); AddToWorkList(Shift.getNode()); if (XType.bitsGT(AType)) { @@ -7142,13 +7155,15 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, // Shift the tested bit over the sign bit. APInt AndMask = ConstAndRHS->getAPIntValue(); SDValue ShlAmt = - DAG.getConstant(AndMask.countLeadingZeros(), getShiftAmountTy()); + DAG.getConstant(AndMask.countLeadingZeros(), + getShiftAmountTy(AndLHS.getValueType())); SDValue Shl = DAG.getNode(ISD::SHL, N0.getDebugLoc(), VT, AndLHS, ShlAmt); // Now arithmetic right shift it all the way over, so the result is either // all-ones, or zero. SDValue ShrAmt = - DAG.getConstant(AndMask.getBitWidth()-1, getShiftAmountTy()); + DAG.getConstant(AndMask.getBitWidth()-1, + getShiftAmountTy(Shl.getValueType())); SDValue Shr = DAG.getNode(ISD::SRA, N0.getDebugLoc(), VT, Shl, ShrAmt); return DAG.getNode(ISD::AND, DL, VT, Shr, N3); @@ -7192,7 +7207,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, // shl setcc result by log2 n2c return DAG.getNode(ISD::SHL, DL, N2.getValueType(), Temp, DAG.getConstant(N2C->getAPIntValue().logBase2(), - getShiftAmountTy())); + getShiftAmountTy(Temp.getValueType()))); } // Check to see if this is the equivalent of setcc @@ -7215,7 +7230,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, SDValue Ctlz = DAG.getNode(ISD::CTLZ, N0.getDebugLoc(), XType, N0); return DAG.getNode(ISD::SRL, DL, XType, Ctlz, DAG.getConstant(Log2_32(XType.getSizeInBits()), - getShiftAmountTy())); + getShiftAmountTy(Ctlz.getValueType()))); } // fold (setgt X, 0) -> (srl (and (-X, ~X), size(X)-1)) if (N1C && N1C->isNullValue() && CC == ISD::SETGT) { @@ -7225,13 +7240,13 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, return DAG.getNode(ISD::SRL, DL, XType, DAG.getNode(ISD::AND, DL, XType, NegN0, NotN0), DAG.getConstant(XType.getSizeInBits()-1, - getShiftAmountTy())); + getShiftAmountTy(XType))); } // fold (setgt X, -1) -> (xor (srl (X, size(X)-1), 1)) if (N1C && N1C->isAllOnesValue() && CC == ISD::SETGT) { SDValue Sign = DAG.getNode(ISD::SRL, N0.getDebugLoc(), XType, N0, DAG.getConstant(XType.getSizeInBits()-1, - getShiftAmountTy())); + getShiftAmountTy(N0.getValueType()))); return DAG.getNode(ISD::XOR, DL, XType, Sign, DAG.getConstant(1, XType)); } } @@ -7258,7 +7273,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, SDValue Shift = DAG.getNode(ISD::SRA, N0.getDebugLoc(), XType, N0, DAG.getConstant(XType.getSizeInBits()-1, - getShiftAmountTy())); + getShiftAmountTy(N0.getValueType()))); SDValue Add = DAG.getNode(ISD::ADD, N0.getDebugLoc(), XType, N0, Shift); AddToWorkList(Shift.getNode()); diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index 98582ba..2ae3286 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -219,6 +219,7 @@ void FunctionLoweringInfo::clear() { CatchInfoFound.clear(); #endif LiveOutRegInfo.clear(); + VisitedBBs.clear(); ArgDbgValues.clear(); ByValArgFrameIndexMap.clear(); RegFixups.clear(); @@ -254,6 +255,123 @@ unsigned FunctionLoweringInfo::CreateRegs(const Type *Ty) { return FirstReg; } +/// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the +/// register is a PHI destination and the PHI's LiveOutInfo is not valid. If +/// the register's LiveOutInfo is for a smaller bit width, it is extended to +/// the larger bit width by zero extension. The bit width must be no smaller +/// than the LiveOutInfo's existing bit width. +const FunctionLoweringInfo::LiveOutInfo * +FunctionLoweringInfo::GetLiveOutRegInfo(unsigned Reg, unsigned BitWidth) { + if (!LiveOutRegInfo.inBounds(Reg)) + return NULL; + + LiveOutInfo *LOI = &LiveOutRegInfo[Reg]; + if (!LOI->IsValid) + return NULL; + + if (BitWidth > LOI->KnownZero.getBitWidth()) { + LOI->NumSignBits = 1; + LOI->KnownZero = LOI->KnownZero.zextOrTrunc(BitWidth); + LOI->KnownOne = LOI->KnownOne.zextOrTrunc(BitWidth); + } + + return LOI; +} + +/// ComputePHILiveOutRegInfo - Compute LiveOutInfo for a PHI's destination +/// register based on the LiveOutInfo of its operands. +void FunctionLoweringInfo::ComputePHILiveOutRegInfo(const PHINode *PN) { + const Type *Ty = PN->getType(); + if (!Ty->isIntegerTy() || Ty->isVectorTy()) + return; + + SmallVector<EVT, 1> ValueVTs; + ComputeValueVTs(TLI, Ty, ValueVTs); + assert(ValueVTs.size() == 1 && + "PHIs with non-vector integer types should have a single VT."); + EVT IntVT = ValueVTs[0]; + + if (TLI.getNumRegisters(PN->getContext(), IntVT) != 1) + return; + IntVT = TLI.getTypeToTransformTo(PN->getContext(), IntVT); + unsigned BitWidth = IntVT.getSizeInBits(); + + unsigned DestReg = ValueMap[PN]; + if (!TargetRegisterInfo::isVirtualRegister(DestReg)) + return; + LiveOutRegInfo.grow(DestReg); + LiveOutInfo &DestLOI = LiveOutRegInfo[DestReg]; + + Value *V = PN->getIncomingValue(0); + if (isa<UndefValue>(V) || isa<ConstantExpr>(V)) { + DestLOI.NumSignBits = 1; + APInt Zero(BitWidth, 0); + DestLOI.KnownZero = Zero; + DestLOI.KnownOne = Zero; + return; + } + + if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) { + APInt Val = CI->getValue().zextOrTrunc(BitWidth); + DestLOI.NumSignBits = Val.getNumSignBits(); + DestLOI.KnownZero = ~Val; + DestLOI.KnownOne = Val; + } else { + assert(ValueMap.count(V) && "V should have been placed in ValueMap when its" + "CopyToReg node was created."); + unsigned SrcReg = ValueMap[V]; + if (!TargetRegisterInfo::isVirtualRegister(SrcReg)) { + DestLOI.IsValid = false; + return; + } + const LiveOutInfo *SrcLOI = GetLiveOutRegInfo(SrcReg, BitWidth); + if (!SrcLOI) { + DestLOI.IsValid = false; + return; + } + DestLOI = *SrcLOI; + } + + assert(DestLOI.KnownZero.getBitWidth() == BitWidth && + DestLOI.KnownOne.getBitWidth() == BitWidth && + "Masks should have the same bit width as the type."); + + for (unsigned i = 1, e = PN->getNumIncomingValues(); i != e; ++i) { + Value *V = PN->getIncomingValue(i); + if (isa<UndefValue>(V) || isa<ConstantExpr>(V)) { + DestLOI.NumSignBits = 1; + APInt Zero(BitWidth, 0); + DestLOI.KnownZero = Zero; + DestLOI.KnownOne = Zero; + return; + } + + if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) { + APInt Val = CI->getValue().zextOrTrunc(BitWidth); + DestLOI.NumSignBits = std::min(DestLOI.NumSignBits, Val.getNumSignBits()); + DestLOI.KnownZero &= ~Val; + DestLOI.KnownOne &= Val; + continue; + } + + assert(ValueMap.count(V) && "V should have been placed in ValueMap when " + "its CopyToReg node was created."); + unsigned SrcReg = ValueMap[V]; + if (!TargetRegisterInfo::isVirtualRegister(SrcReg)) { + DestLOI.IsValid = false; + return; + } + const LiveOutInfo *SrcLOI = GetLiveOutRegInfo(SrcReg, BitWidth); + if (!SrcLOI) { + DestLOI.IsValid = false; + return; + } + DestLOI.NumSignBits = std::min(DestLOI.NumSignBits, SrcLOI->NumSignBits); + DestLOI.KnownZero &= SrcLOI->KnownZero; + DestLOI.KnownOne &= SrcLOI->KnownOne; + } +} + /// setByValArgumentFrameIndex - Record frame index for the byval /// argument. This overrides previous frame index entry for this argument, /// if any. diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 49c862c..f08528f 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -87,7 +87,7 @@ class SelectionDAGLegalize { // If someone requests legalization of the new node, return itself. if (From != To) LegalizedNodes.insert(std::make_pair(To, To)); - + // Transfer SDDbgValues. DAG.TransferDbgValues(From, To); } @@ -498,7 +498,8 @@ SDValue ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG, int IncrementSize = NumBits / 8; // Divide the stored value in two parts. - SDValue ShiftAmount = DAG.getConstant(NumBits, TLI.getShiftAmountTy()); + SDValue ShiftAmount = DAG.getConstant(NumBits, + TLI.getShiftAmountTy(Val.getValueType())); SDValue Lo = Val; SDValue Hi = DAG.getNode(ISD::SRL, dl, VT, Val, ShiftAmount); @@ -645,7 +646,8 @@ SDValue ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG, } // aggregate the two parts - SDValue ShiftAmount = DAG.getConstant(NumBits, TLI.getShiftAmountTy()); + SDValue ShiftAmount = DAG.getConstant(NumBits, + TLI.getShiftAmountTy(Hi.getValueType())); SDValue Result = DAG.getNode(ISD::SHL, dl, VT, Hi, ShiftAmount); Result = DAG.getNode(ISD::OR, dl, VT, Result, Lo); @@ -1264,7 +1266,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // Move the top bits to the right place. Hi = DAG.getNode(ISD::SHL, dl, Hi.getValueType(), Hi, - DAG.getConstant(RoundWidth, TLI.getShiftAmountTy())); + DAG.getConstant(RoundWidth, + TLI.getShiftAmountTy(Hi.getValueType()))); // Join the hi and lo parts. Result = DAG.getNode(ISD::OR, dl, Node->getValueType(0), Lo, Hi); @@ -1293,7 +1296,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // Move the top bits to the right place. Hi = DAG.getNode(ISD::SHL, dl, Hi.getValueType(), Hi, - DAG.getConstant(ExtraWidth, TLI.getShiftAmountTy())); + DAG.getConstant(ExtraWidth, + TLI.getShiftAmountTy(Hi.getValueType()))); // Join the hi and lo parts. Result = DAG.getNode(ISD::OR, dl, Node->getValueType(0), Lo, Hi); @@ -1482,7 +1486,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2, DAG.getIntPtrConstant(IncrementSize)); Hi = DAG.getNode(ISD::SRL, dl, Tmp3.getValueType(), Tmp3, - DAG.getConstant(RoundWidth, TLI.getShiftAmountTy())); + DAG.getConstant(RoundWidth, + TLI.getShiftAmountTy(Tmp3.getValueType()))); Hi = DAG.getTruncStore(Tmp1, dl, Hi, Tmp2, ST->getPointerInfo().getWithOffset(IncrementSize), ExtraVT, isVolatile, isNonTemporal, @@ -1492,7 +1497,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // TRUNCSTORE:i24 X -> TRUNCSTORE:i16 (srl X, 8), TRUNCSTORE@+2:i8 X // Store the top RoundWidth bits. Hi = DAG.getNode(ISD::SRL, dl, Tmp3.getValueType(), Tmp3, - DAG.getConstant(ExtraWidth, TLI.getShiftAmountTy())); + DAG.getConstant(ExtraWidth, + TLI.getShiftAmountTy(Tmp3.getValueType()))); Hi = DAG.getTruncStore(Tmp1, dl, Hi, Tmp2, ST->getPointerInfo(), RoundVT, isVolatile, isNonTemporal, Alignment); @@ -1727,7 +1733,8 @@ SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode* Node) { assert(BitShift < LoadTy.getSizeInBits() && "Pointer advanced wrong?"); if (BitShift) SignBit = DAG.getNode(ISD::SHL, dl, LoadTy, SignBit, - DAG.getConstant(BitShift,TLI.getShiftAmountTy())); + DAG.getConstant(BitShift, + TLI.getShiftAmountTy(SignBit.getValueType()))); } } // Now get the sign bit proper, by seeing whether the value is negative. @@ -2207,7 +2214,8 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned, if (!isSigned) { SDValue Fast = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, Op0); - SDValue ShiftConst = DAG.getConstant(1, TLI.getShiftAmountTy()); + SDValue ShiftConst = + DAG.getConstant(1, TLI.getShiftAmountTy(Op0.getValueType())); SDValue Shr = DAG.getNode(ISD::SRL, dl, MVT::i64, Op0, ShiftConst); SDValue AndConst = DAG.getConstant(1, MVT::i64); SDValue And = DAG.getNode(ISD::AND, dl, MVT::i64, Op0, AndConst); @@ -2226,7 +2234,6 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned, } // Otherwise, implement the fully general conversion. - EVT SHVT = TLI.getShiftAmountTy(); SDValue And = DAG.getNode(ISD::AND, dl, MVT::i64, Op0, DAG.getConstant(UINT64_C(0xfffffffffffff800), MVT::i64)); @@ -2241,6 +2248,7 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned, Op0, DAG.getConstant(UINT64_C(0x0020000000000000), MVT::i64), ISD::SETUGE); SDValue Sel2 = DAG.getNode(ISD::SELECT, dl, MVT::i64, Ge, Sel, Op0); + EVT SHVT = TLI.getShiftAmountTy(Sel2.getValueType()); SDValue Sh = DAG.getNode(ISD::SRL, dl, MVT::i64, Sel2, DAG.getConstant(32, SHVT)); @@ -2387,7 +2395,7 @@ SDValue SelectionDAGLegalize::PromoteLegalFP_TO_INT(SDValue LegalOp, /// SDValue SelectionDAGLegalize::ExpandBSWAP(SDValue Op, DebugLoc dl) { EVT VT = Op.getValueType(); - EVT SHVT = TLI.getShiftAmountTy(); + EVT SHVT = TLI.getShiftAmountTy(VT); SDValue Tmp1, Tmp2, Tmp3, Tmp4, Tmp5, Tmp6, Tmp7, Tmp8; switch (VT.getSimpleVT().SimpleTy) { default: assert(0 && "Unhandled Expand type in BSWAP!"); @@ -2450,7 +2458,7 @@ SDValue SelectionDAGLegalize::ExpandBitCount(unsigned Opc, SDValue Op, default: assert(0 && "Cannot expand this yet!"); case ISD::CTPOP: { EVT VT = Op.getValueType(); - EVT ShVT = TLI.getShiftAmountTy(); + EVT ShVT = TLI.getShiftAmountTy(VT); unsigned Len = VT.getSizeInBits(); assert(VT.isInteger() && Len <= 128 && Len % 8 == 0 && @@ -2487,7 +2495,7 @@ SDValue SelectionDAGLegalize::ExpandBitCount(unsigned Opc, SDValue Op, Op = DAG.getNode(ISD::SRL, dl, VT, DAG.getNode(ISD::MUL, dl, VT, Op, Mask01), DAG.getConstant(Len - 8, ShVT)); - + return Op; } case ISD::CTLZ: { @@ -2501,7 +2509,7 @@ SDValue SelectionDAGLegalize::ExpandBitCount(unsigned Opc, SDValue Op, // // but see also: http://www.hackersdelight.org/HDcode/nlz.cc EVT VT = Op.getValueType(); - EVT ShVT = TLI.getShiftAmountTy(); + EVT ShVT = TLI.getShiftAmountTy(VT); unsigned len = VT.getSizeInBits(); for (unsigned i = 0; (1U << i) <= (len / 2); ++i) { SDValue Tmp3 = DAG.getConstant(1ULL << i, ShVT); @@ -2737,7 +2745,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, // SAR. However, it is doubtful that any exist. EVT ExtraVT = cast<VTSDNode>(Node->getOperand(1))->getVT(); EVT VT = Node->getValueType(0); - EVT ShiftAmountTy = TLI.getShiftAmountTy(); + EVT ShiftAmountTy = TLI.getShiftAmountTy(VT); if (VT.isVector()) ShiftAmountTy = VT; unsigned BitsDiff = VT.getScalarType().getSizeInBits() - @@ -2901,7 +2909,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, // 1 -> Hi Tmp1 = DAG.getNode(ISD::SRL, dl, OpTy, Node->getOperand(0), DAG.getConstant(OpTy.getSizeInBits()/2, - TLI.getShiftAmountTy())); + TLI.getShiftAmountTy(Node->getOperand(0).getValueType()))); Tmp1 = DAG.getNode(ISD::TRUNCATE, dl, Node->getValueType(0), Tmp1); } else { // 0 -> Lo @@ -3260,7 +3268,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, assert(LC != RTLIB::UNKNOWN_LIBCALL && "Cannot expand this operation!"); LHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, LHS); RHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, RHS); - + SDValue Ret = ExpandLibCall(LC, Node, isSigned); BottomHalf = DAG.getNode(ISD::TRUNCATE, dl, VT, Ret); TopHalf = DAG.getNode(ISD::SRL, dl, Ret.getValueType(), Ret, @@ -3268,7 +3276,8 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, TopHalf = DAG.getNode(ISD::TRUNCATE, dl, VT, TopHalf); } if (isSigned) { - Tmp1 = DAG.getConstant(VT.getSizeInBits() - 1, TLI.getShiftAmountTy()); + Tmp1 = DAG.getConstant(VT.getSizeInBits() - 1, + TLI.getShiftAmountTy(BottomHalf.getValueType())); Tmp1 = DAG.getNode(ISD::SRA, dl, VT, BottomHalf, Tmp1); TopHalf = DAG.getSetCC(dl, TLI.getSetCCResultType(VT), TopHalf, Tmp1, ISD::SETNE); @@ -3286,7 +3295,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, Tmp2 = DAG.getNode(ISD::ANY_EXTEND, dl, PairTy, Node->getOperand(1)); Tmp2 = DAG.getNode(ISD::SHL, dl, PairTy, Tmp2, DAG.getConstant(PairTy.getSizeInBits()/2, - TLI.getShiftAmountTy())); + TLI.getShiftAmountTy(PairTy))); Results.push_back(DAG.getNode(ISD::OR, dl, PairTy, Tmp1, Tmp2)); break; } @@ -3464,7 +3473,7 @@ void SelectionDAGLegalize::PromoteNode(SDNode *Node, Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, dl, NVT, Node->getOperand(0)); Tmp1 = DAG.getNode(ISD::BSWAP, dl, NVT, Tmp1); Tmp1 = DAG.getNode(ISD::SRL, dl, NVT, Tmp1, - DAG.getConstant(DiffBits, TLI.getShiftAmountTy())); + DAG.getConstant(DiffBits, TLI.getShiftAmountTy(NVT))); Results.push_back(Tmp1); break; } diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp index 2775212..27a466b 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp @@ -177,25 +177,27 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN(SDNode *N) { // First get the sign bit of second operand. SDValue SignBit = DAG.getNode(ISD::SHL, dl, RVT, DAG.getConstant(1, RVT), DAG.getConstant(RSize - 1, - TLI.getShiftAmountTy())); + TLI.getShiftAmountTy(RVT))); SignBit = DAG.getNode(ISD::AND, dl, RVT, RHS, SignBit); // Shift right or sign-extend it if the two operands have different types. int SizeDiff = RVT.getSizeInBits() - LVT.getSizeInBits(); if (SizeDiff > 0) { SignBit = DAG.getNode(ISD::SRL, dl, RVT, SignBit, - DAG.getConstant(SizeDiff, TLI.getShiftAmountTy())); + DAG.getConstant(SizeDiff, + TLI.getShiftAmountTy(SignBit.getValueType()))); SignBit = DAG.getNode(ISD::TRUNCATE, dl, LVT, SignBit); } else if (SizeDiff < 0) { SignBit = DAG.getNode(ISD::ANY_EXTEND, dl, LVT, SignBit); SignBit = DAG.getNode(ISD::SHL, dl, LVT, SignBit, - DAG.getConstant(-SizeDiff, TLI.getShiftAmountTy())); + DAG.getConstant(-SizeDiff, + TLI.getShiftAmountTy(SignBit.getValueType()))); } // Clear the sign bit of the first operand. SDValue Mask = DAG.getNode(ISD::SHL, dl, LVT, DAG.getConstant(1, LVT), DAG.getConstant(LSize - 1, - TLI.getShiftAmountTy())); + TLI.getShiftAmountTy(LVT))); Mask = DAG.getNode(ISD::SUB, dl, LVT, Mask, DAG.getConstant(1, LVT)); LHS = DAG.getNode(ISD::AND, dl, LVT, LHS, Mask); diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 2fb2f2d..9120288 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -1420,7 +1420,7 @@ SDValue SelectionDAG::getMDNode(const MDNode *MD) { /// the target's desired shift amount type. SDValue SelectionDAG::getShiftAmountOperand(SDValue Op) { EVT OpTy = Op.getValueType(); - MVT ShTy = TLI.getShiftAmountTy(); + MVT ShTy = TLI.getShiftAmountTy(OpTy); if (OpTy == ShTy || OpTy.isVector()) return Op; ISD::NodeType Opcode = OpTy.bitsGT(ShTy) ? ISD::TRUNCATE : ISD::ZERO_EXTEND; @@ -2048,7 +2048,7 @@ void SelectionDAG::ComputeMaskedBits(SDValue Op, const APInt &Mask, return; } break; - + default: // Allow the target to implement this method for its nodes. if (Op.getOpcode() >= ISD::BUILTIN_OP_END) { @@ -2088,12 +2088,7 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, unsigned Depth) const{ case ISD::Constant: { const APInt &Val = cast<ConstantSDNode>(Op)->getAPIntValue(); - // If negative, return # leading ones. - if (Val.isNegative()) - return Val.countLeadingOnes(); - - // Return # leading zeros. - return Val.countLeadingZeros(); + return Val.getNumSignBits(); } case ISD::SIGN_EXTEND: @@ -2297,12 +2292,12 @@ bool SelectionDAG::isBaseWithConstantOffset(SDValue Op) const { if ((Op.getOpcode() != ISD::ADD && Op.getOpcode() != ISD::OR) || !isa<ConstantSDNode>(Op.getOperand(1))) return false; - - if (Op.getOpcode() == ISD::OR && + + if (Op.getOpcode() == ISD::OR && !MaskedValueIsZero(Op.getOperand(0), cast<ConstantSDNode>(Op.getOperand(1))->getAPIntValue())) return false; - + return true; } @@ -2753,7 +2748,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT, // i8, which is easy to fall into in generic code that uses // TLI.getShiftAmount(). assert(N2.getValueType().getSizeInBits() >= - Log2_32_Ceil(N1.getValueType().getSizeInBits()) && + Log2_32_Ceil(N1.getValueType().getSizeInBits()) && "Invalid use of small shift amount with oversized value!"); // Always fold shifts of i1 values so the code generator doesn't need to diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 452f561..48d9bbb 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -641,16 +641,17 @@ SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG, // If the source register was virtual and if we know something about it, // add an assert node. if (!TargetRegisterInfo::isVirtualRegister(Regs[Part+i]) || - !RegisterVT.isInteger() || RegisterVT.isVector() || - !FuncInfo.LiveOutRegInfo.inBounds(Regs[Part+i])) + !RegisterVT.isInteger() || RegisterVT.isVector()) + continue; + + const FunctionLoweringInfo::LiveOutInfo *LOI = + FuncInfo.GetLiveOutRegInfo(Regs[Part+i]); + if (!LOI) continue; - - const FunctionLoweringInfo::LiveOutInfo &LOI = - FuncInfo.LiveOutRegInfo[Regs[Part+i]]; unsigned RegSize = RegisterVT.getSizeInBits(); - unsigned NumSignBits = LOI.NumSignBits; - unsigned NumZeroBits = LOI.KnownZero.countLeadingOnes(); + unsigned NumSignBits = LOI->NumSignBits; + unsigned NumZeroBits = LOI->KnownZero.countLeadingOnes(); // FIXME: We capture more information than the dag can represent. For // now, just use the tightest assertzext/assertsext possible. @@ -908,7 +909,7 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V, Val.getResNo(), Offset, dl, DbgSDNodeOrder); DAG.AddDbgValue(SDV, Val.getNode(), false); } - } else + } else DEBUG(dbgs() << "Dropping debug info for " << DI); DanglingDebugInfoMap[V] = DanglingDebugInfo(); } @@ -1417,7 +1418,7 @@ void SelectionDAGBuilder::visitBr(const BranchInst &I) { // jle foo // if (const BinaryOperator *BOp = dyn_cast<BinaryOperator>(CondVal)) { - if (!TLI.isJumpExpensive() && + if (!TLI.isJumpExpensive() && BOp->hasOneUse() && (BOp->getOpcode() == Instruction::And || BOp->getOpcode() == Instruction::Or)) { @@ -1915,7 +1916,7 @@ bool SelectionDAGBuilder::handleJTSwitchCase(CaseRec& CR, DEBUG(dbgs() << "Lowering jump table\n" << "First entry: " << First << ". Last entry: " << Last << '\n' << "Range: " << Range - << "Size: " << TSize << ". Density: " << Density << "\n\n"); + << ". Size: " << TSize << ". Density: " << Density << "\n\n"); // Get the MachineFunction which holds the current MBB. This is used when // inserting any additional MBBs necessary to represent the switch. @@ -2408,19 +2409,19 @@ void SelectionDAGBuilder::visitBinary(const User &I, unsigned OpCode) { void SelectionDAGBuilder::visitShift(const User &I, unsigned Opcode) { SDValue Op1 = getValue(I.getOperand(0)); SDValue Op2 = getValue(I.getOperand(1)); - - MVT ShiftTy = TLI.getShiftAmountTy(); - + + MVT ShiftTy = TLI.getShiftAmountTy(Op2.getValueType()); + // Coerce the shift amount to the right type if we can. if (!I.getType()->isVectorTy() && Op2.getValueType() != ShiftTy) { unsigned ShiftSize = ShiftTy.getSizeInBits(); unsigned Op2Size = Op2.getValueType().getSizeInBits(); DebugLoc DL = getCurDebugLoc(); - + // If the operand is smaller than the shift count type, promote it. if (ShiftSize > Op2Size) Op2 = DAG.getNode(ISD::ZERO_EXTEND, DL, ShiftTy, Op2); - + // If the operand is larger than the shift count type but the shift // count type has enough bits to represent any shift value, truncate // it now. This is a common case and it exposes the truncate to diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index a1a70c3..8f466d9 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -348,7 +348,7 @@ public: SDValue getControlRoot(); DebugLoc getCurDebugLoc() const { return CurDebugLoc; } - void setCurDebugLoc(DebugLoc dl){ CurDebugLoc = dl; } + unsigned getSDNodeOrder() const { return SDNodeOrder; } void CopyValueToVirtualRegister(const Value *V, unsigned Reg); diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 62ebc81..68ba966 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -49,6 +49,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/Statistic.h" #include <algorithm> using namespace llvm; @@ -479,16 +480,7 @@ void SelectionDAGISel::ComputeLiveOutVRegInfo() { unsigned NumSignBits = CurDAG->ComputeNumSignBits(Src); Mask = APInt::getAllOnesValue(SrcVT.getSizeInBits()); CurDAG->ComputeMaskedBits(Src, Mask, KnownZero, KnownOne); - - // Only install this information if it tells us something. - if (NumSignBits != 1 || KnownZero != 0 || KnownOne != 0) { - FuncInfo->LiveOutRegInfo.grow(DestReg); - FunctionLoweringInfo::LiveOutInfo &LOI = - FuncInfo->LiveOutRegInfo[DestReg]; - LOI.NumSignBits = NumSignBits; - LOI.KnownOne = KnownOne; - LOI.KnownZero = KnownZero; - } + FuncInfo->AddLiveOutRegInfo(DestReg, NumSignBits, KnownZero, KnownOne); } while (!Worklist.empty()); } @@ -832,11 +824,39 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { FastIS = TLI.createFastISel(*FuncInfo); // Iterate over all basic blocks in the function. - for (Function::const_iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) { - const BasicBlock *LLVMBB = &*I; + ReversePostOrderTraversal<const Function*> RPOT(&Fn); + for (ReversePostOrderTraversal<const Function*>::rpo_iterator + I = RPOT.begin(), E = RPOT.end(); I != E; ++I) { + const BasicBlock *LLVMBB = *I; #ifndef NDEBUG CheckLineNumbers(LLVMBB); #endif + + if (OptLevel != CodeGenOpt::None) { + bool AllPredsVisited = true; + for (const_pred_iterator PI = pred_begin(LLVMBB), PE = pred_end(LLVMBB); + PI != PE; ++PI) { + if (!FuncInfo->VisitedBBs.count(*PI)) { + AllPredsVisited = false; + break; + } + } + + if (AllPredsVisited) { + for (BasicBlock::const_iterator I = LLVMBB->begin(), E = LLVMBB->end(); + I != E && isa<PHINode>(I); ++I) { + FuncInfo->ComputePHILiveOutRegInfo(cast<PHINode>(I)); + } + } else { + for (BasicBlock::const_iterator I = LLVMBB->begin(), E = LLVMBB->end(); + I != E && isa<PHINode>(I); ++I) { + FuncInfo->InvalidatePHILiveOutRegInfo(cast<PHINode>(I)); + } + } + + FuncInfo->VisitedBBs.insert(LLVMBB); + } + FuncInfo->MBB = FuncInfo->MBBMap[LLVMBB]; FuncInfo->InsertPt = FuncInfo->MBB->getFirstNonPHI(); @@ -851,17 +871,8 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { PrepareEHLandingPad(); // Lower any arguments needed in this block if this is the entry block. - if (LLVMBB == &Fn.getEntryBlock()) { - for (BasicBlock::const_iterator DBI = LLVMBB->begin(), DBE = LLVMBB->end(); - DBI != DBE; ++DBI) { - if (const DbgInfoIntrinsic *DI = dyn_cast<DbgInfoIntrinsic>(DBI)) { - const DebugLoc DL = DI->getDebugLoc(); - SDB->setCurDebugLoc(DL); - break; - } - } + if (LLVMBB == &Fn.getEntryBlock()) LowerArguments(LLVMBB); - } // Before doing SelectionDAG ISel, see if FastISel has been requested. if (FastIS) { diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 691390e..35b847c 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -563,7 +563,7 @@ TargetLowering::TargetLowering(const TargetMachine &tm, setOperationAction(ISD::TRAP, MVT::Other, Expand); IsLittleEndian = TD->isLittleEndian(); - ShiftAmountTy = PointerTy = MVT::getIntegerVT(8*TD->getPointerSize()); + PointerTy = MVT::getIntegerVT(8*TD->getPointerSize()); memset(RegClassForVT, 0,MVT::LAST_VALUETYPE*sizeof(TargetRegisterClass*)); memset(TargetDAGCombineArray, 0, array_lengthof(TargetDAGCombineArray)); maxStoresPerMemset = maxStoresPerMemcpy = maxStoresPerMemmove = 8; @@ -596,6 +596,10 @@ TargetLowering::~TargetLowering() { delete &TLOF; } +MVT TargetLowering::getShiftAmountTy(EVT LHSTy) const { + return MVT::getIntegerVT(8*TD->getPointerSize()); +} + /// canOpTrap - Returns true if the operation can trap for the value type. /// VT must be a legal type. bool TargetLowering::canOpTrap(unsigned Op, EVT VT) const { @@ -1401,7 +1405,7 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op, BitWidth - InnerVT.getSizeInBits()) & DemandedMask) == 0 && isTypeDesirableForOp(ISD::SHL, InnerVT)) { - EVT ShTy = getShiftAmountTy(); + EVT ShTy = getShiftAmountTy(InnerVT); if (!APInt(BitWidth, ShAmt).isIntN(ShTy.getSizeInBits())) ShTy = InnerVT; SDValue NarrowShl = @@ -2188,7 +2192,7 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, if (ConstantSDNode *AndRHS = dyn_cast<ConstantSDNode>(N0.getOperand(1))) { EVT ShiftTy = DCI.isBeforeLegalize() ? - getPointerTy() : getShiftAmountTy(); + getPointerTy() : getShiftAmountTy(N0.getValueType()); if (Cond == ISD::SETNE && C1 == 0) {// (X & 8) != 0 --> (X & 8) >> 3 // Perform the xform if the AND RHS is a single bit. if (AndRHS->getAPIntValue().isPowerOf2()) { @@ -2359,7 +2363,7 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, // (Z-X) == X --> Z == X<<1 SDValue SH = DAG.getNode(ISD::SHL, dl, N1.getValueType(), N1, - DAG.getConstant(1, getShiftAmountTy())); + DAG.getConstant(1, getShiftAmountTy(N1.getValueType()))); if (!DCI.isCalledByLegalizer()) DCI.AddToWorklist(SH.getNode()); return DAG.getSetCC(dl, VT, N0.getOperand(0), SH, Cond); @@ -2381,7 +2385,7 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, assert(N1.getOpcode() == ISD::SUB && "Unexpected operation!"); // X == (Z-X) --> X<<1 == Z SDValue SH = DAG.getNode(ISD::SHL, dl, N1.getValueType(), N0, - DAG.getConstant(1, getShiftAmountTy())); + DAG.getConstant(1, getShiftAmountTy(N0.getValueType()))); if (!DCI.isCalledByLegalizer()) DCI.AddToWorklist(SH.getNode()); return DAG.getSetCC(dl, VT, SH, N1.getOperand(0), Cond); @@ -2493,7 +2497,7 @@ bool TargetLowering::isGAPlusOffset(SDNode *N, const GlobalValue *&GA, } } } - + return false; } @@ -3141,14 +3145,14 @@ SDValue TargetLowering::BuildSDIV(SDNode *N, SelectionDAG &DAG, // Shift right algebraic if shift value is nonzero if (magics.s > 0) { Q = DAG.getNode(ISD::SRA, dl, VT, Q, - DAG.getConstant(magics.s, getShiftAmountTy())); + DAG.getConstant(magics.s, getShiftAmountTy(Q.getValueType()))); if (Created) Created->push_back(Q.getNode()); } // Extract the sign bit and add it to the quotient SDValue T = DAG.getNode(ISD::SRL, dl, VT, Q, DAG.getConstant(VT.getSizeInBits()-1, - getShiftAmountTy())); + getShiftAmountTy(Q.getValueType()))); if (Created) Created->push_back(T.getNode()); return DAG.getNode(ISD::ADD, dl, VT, Q, T); @@ -3192,19 +3196,19 @@ SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG, assert(magics.s < N1C->getAPIntValue().getBitWidth() && "We shouldn't generate an undefined shift!"); return DAG.getNode(ISD::SRL, dl, VT, Q, - DAG.getConstant(magics.s, getShiftAmountTy())); + DAG.getConstant(magics.s, getShiftAmountTy(Q.getValueType()))); } else { SDValue NPQ = DAG.getNode(ISD::SUB, dl, VT, N->getOperand(0), Q); if (Created) Created->push_back(NPQ.getNode()); NPQ = DAG.getNode(ISD::SRL, dl, VT, NPQ, - DAG.getConstant(1, getShiftAmountTy())); + DAG.getConstant(1, getShiftAmountTy(NPQ.getValueType()))); if (Created) Created->push_back(NPQ.getNode()); NPQ = DAG.getNode(ISD::ADD, dl, VT, NPQ, Q); if (Created) Created->push_back(NPQ.getNode()); return DAG.getNode(ISD::SRL, dl, VT, NPQ, - DAG.getConstant(magics.s-1, getShiftAmountTy())); + DAG.getConstant(magics.s-1, getShiftAmountTy(NPQ.getValueType()))); } } diff --git a/contrib/llvm/lib/CodeGen/SplitKit.cpp b/contrib/llvm/lib/CodeGen/SplitKit.cpp index 5663936..fd5d50b 100644 --- a/contrib/llvm/lib/CodeGen/SplitKit.cpp +++ b/contrib/llvm/lib/CodeGen/SplitKit.cpp @@ -167,6 +167,20 @@ void SplitAnalysis::calcLiveBlockInfo() { } } +bool SplitAnalysis::isOriginalEndpoint(SlotIndex Idx) const { + unsigned OrigReg = VRM.getOriginal(CurLI->reg); + const LiveInterval &Orig = LIS.getInterval(OrigReg); + assert(!Orig.empty() && "Splitting empty interval?"); + LiveInterval::const_iterator I = Orig.find(Idx); + + // Range containing Idx should begin at Idx. + if (I != Orig.end() && I->start <= Idx) + return I->start == Idx; + + // Range does not contain Idx, previous must end at Idx. + return I != Orig.begin() && (--I)->end == Idx; +} + void SplitAnalysis::print(const BlockPtrSet &B, raw_ostream &OS) const { for (BlockPtrSet::const_iterator I = B.begin(), E = B.end(); I != E; ++I) { unsigned count = UsingBlocks.lookup(*I); @@ -947,10 +961,10 @@ void SplitEditor::splitSingleBlocks(const SplitAnalysis::BlockPtrSet &Blocks) { openIntv(); SlotIndex SegStart = enterIntvBefore(BI.FirstUse); - if (BI.LastUse < BI.LastSplitPoint) { + if (!BI.LiveOut || BI.LastUse < BI.LastSplitPoint) { useIntv(SegStart, leaveIntvAfter(BI.LastUse)); } else { - // THe last use os after tha last valid split point. + // The last use is after the last valid split point. SlotIndex SegStop = leaveIntvBefore(BI.LastSplitPoint); useIntv(SegStart, SegStop); overlapIntv(SegStop, BI.LastUse); diff --git a/contrib/llvm/lib/CodeGen/SplitKit.h b/contrib/llvm/lib/CodeGen/SplitKit.h index 5c34afd..e02e629 100644 --- a/contrib/llvm/lib/CodeGen/SplitKit.h +++ b/contrib/llvm/lib/CodeGen/SplitKit.h @@ -125,6 +125,13 @@ public: return UsingBlocks.lookup(MBB); } + /// isOriginalEndpoint - Return true if the original live range was killed or + /// (re-)defined at Idx. Idx should be the 'def' slot for a normal kill/def, + /// and 'use' for an early-clobber def. + /// This can be used to recognize code inserted by earlier live range + /// splitting. + bool isOriginalEndpoint(SlotIndex Idx) const; + typedef SmallPtrSet<const MachineBasicBlock*, 16> BlockPtrSet; // Print a set of blocks with use counts. diff --git a/contrib/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/contrib/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 0b7bd98..fa311dc 100644 --- a/contrib/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/contrib/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -178,6 +178,10 @@ const MCSection *TargetLoweringObjectFileELF::getEHFrameSection() const { static SectionKind getELFKindForNamedSection(StringRef Name, SectionKind K) { + // FIXME: Why is this here? Codegen is should not be in the business + // of figuring section flags. If the user wrote section(".eh_frame"), + // we should just pass that to MC which will defer to the assembly + // or use its default if producing an object file. if (Name.empty() || Name[0] != '.') return K; // Some lame default implementation based on some magic section names. @@ -203,6 +207,9 @@ getELFKindForNamedSection(StringRef Name, SectionKind K) { Name.startswith(".llvm.linkonce.tb.")) return SectionKind::getThreadBSS(); + if (Name == ".eh_frame") + return SectionKind::getDataRel(); + return K; } @@ -441,11 +448,15 @@ void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx, Triple T(((LLVMTargetMachine&)TM).getTargetTriple()); if (T.getOS() == Triple::Darwin) { - unsigned MajNum = T.getDarwinMajorNumber(); - if (MajNum == 7 || MajNum == 8) // 10.3 Panther, 10.4 Tiger + switch (T.getDarwinMajorNumber()) { + case 7: // 10.3 Panther. + case 8: // 10.4 Tiger. CommDirectiveSupportsAlignment = false; - if (MajNum > 9) // 10.6 SnowLeopard - IsFunctionEHSymbolGlobal = false; + break; + case 9: // 10.5 Leopard. + case 10: // 10.6 SnowLeopard. + break; + } } TargetLoweringObjectFile::Initialize(Ctx, TM); @@ -630,7 +641,7 @@ getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const { // Parse the section specifier and create it if valid. StringRef Segment, Section; - unsigned TAA, StubSize; + unsigned TAA = (unsigned)MCSectionMachO::SECTION_ATTRIBUTES, StubSize = 0; std::string ErrorCode = MCSectionMachO::ParseSectionSpecifier(GV->getSection(), Segment, Section, TAA, StubSize); @@ -643,10 +654,19 @@ getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, return DataSection; } + bool TAAWasSet = (TAA != MCSectionMachO::SECTION_ATTRIBUTES); + if (!TAAWasSet) + TAA = 0; // Sensible default if this is a new section. + // Get the section. const MCSectionMachO *S = getContext().getMachOSection(Segment, Section, TAA, StubSize, Kind); + // If TAA wasn't set by ParseSectionSpecifier() above, + // use the value returned by getMachOSection() as a default. + if (!TAAWasSet) + TAA = S->getTypeAndAttributes(); + // Okay, now that we got the section, verify that the TAA & StubSize agree. // If the user declared multiple globals with different section flags, we need // to reject it here. diff --git a/contrib/llvm/lib/CodeGen/VirtRegRewriter.cpp b/contrib/llvm/lib/CodeGen/VirtRegRewriter.cpp index 458a213..ec149dd 100644 --- a/contrib/llvm/lib/CodeGen/VirtRegRewriter.cpp +++ b/contrib/llvm/lib/CodeGen/VirtRegRewriter.cpp @@ -478,7 +478,8 @@ static void ResurrectConfirmedKill(unsigned Reg, const TargetRegisterInfo* TRI, if (!RegKills[KReg]) return; - assert(KillOps[KReg] == KillOp && "invalid superreg kill flags"); + assert(KillOps[KReg]->getParent() == KillOp->getParent() && + "invalid superreg kill flags"); KillOps[KReg] = NULL; RegKills.reset(KReg); @@ -487,7 +488,8 @@ static void ResurrectConfirmedKill(unsigned Reg, const TargetRegisterInfo* TRI, for (const unsigned *SR = TRI->getSubRegisters(KReg); *SR; ++SR) { DEBUG(dbgs() << " Resurrect subreg " << TRI->getName(*SR) << "\n"); - assert(KillOps[*SR] == KillOp && "invalid subreg kill flags"); + assert(KillOps[*SR]->getParent() == KillOp->getParent() && + "invalid subreg kill flags"); KillOps[*SR] = NULL; RegKills.reset(*SR); } diff --git a/contrib/llvm/lib/MC/ELFObjectWriter.cpp b/contrib/llvm/lib/MC/ELFObjectWriter.cpp index 8a00a16..ea1629d 100644 --- a/contrib/llvm/lib/MC/ELFObjectWriter.cpp +++ b/contrib/llvm/lib/MC/ELFObjectWriter.cpp @@ -833,7 +833,11 @@ static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data, return true; const MCSymbol &A = Symbol.AliasedSymbol(); - if (!A.isVariable() && A.isUndefined() && !Data.isCommon()) + if (Symbol.isVariable() && !A.isVariable() && A.isUndefined()) + return false; + + bool IsGlobal = GetBinding(Data) == ELF::STB_GLOBAL; + if (!Symbol.isVariable() && Symbol.isUndefined() && !IsGlobal) return false; if (!Asm.isSymbolLinkerVisible(Symbol) && !Symbol.isUndefined()) @@ -1732,6 +1736,10 @@ unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target, assert(Modifier == MCSymbolRefExpr::VK_None); Type = ELF::R_X86_64_PC16; break; + case FK_PCRel_1: + assert(Modifier == MCSymbolRefExpr::VK_None); + Type = ELF::R_X86_64_PC8; + break; } } else { switch ((unsigned)Fixup.getKind()) { diff --git a/contrib/llvm/lib/MC/MCAsmInfo.cpp b/contrib/llvm/lib/MC/MCAsmInfo.cpp index cc1afbd..8199fb2 100644 --- a/contrib/llvm/lib/MC/MCAsmInfo.cpp +++ b/contrib/llvm/lib/MC/MCAsmInfo.cpp @@ -65,6 +65,7 @@ MCAsmInfo::MCAsmInfo() { WeakDefDirective = 0; LinkOnceDirective = 0; HiddenVisibilityAttr = MCSA_Hidden; + HiddenDeclarationVisibilityAttr = MCSA_Hidden; ProtectedVisibilityAttr = MCSA_Protected; HasLEB128 = false; SupportsDebugInformation = false; diff --git a/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp b/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp index 13776f0..526ad0d 100644 --- a/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp +++ b/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp @@ -45,6 +45,7 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() { HasAggressiveSymbolFolding = false; HiddenVisibilityAttr = MCSA_PrivateExtern; + HiddenDeclarationVisibilityAttr = MCSA_Invalid; // Doesn't support protected visibility. ProtectedVisibilityAttr = MCSA_Global; diff --git a/contrib/llvm/lib/MC/MCDisassembler/EDOperand.cpp b/contrib/llvm/lib/MC/MCDisassembler/EDOperand.cpp index cfeb56f..2b0c73e 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/EDOperand.cpp +++ b/contrib/llvm/lib/MC/MCDisassembler/EDOperand.cpp @@ -152,10 +152,23 @@ int EDOperand::evaluate(uint64_t &result, uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm(); unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg(); int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm(); - //unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg(); - + uint64_t addr = 0; + unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg(); + + if (segmentReg != 0 && Disassembler.Key.Arch == Triple::x86_64) { + unsigned fsID = Disassembler.registerIDWithName("FS"); + unsigned gsID = Disassembler.registerIDWithName("GS"); + + if (segmentReg == fsID || + segmentReg == gsID) { + uint64_t segmentBase; + if (!callback(&segmentBase, segmentReg, arg)) + addr += segmentBase; + } + } + if (baseReg) { uint64_t baseVal; if (callback(&baseVal, baseReg, arg)) @@ -175,7 +188,7 @@ int EDOperand::evaluate(uint64_t &result, result = addr; return 0; } - } + } // switch (operandType) break; case Triple::arm: case Triple::thumb: @@ -203,6 +216,7 @@ int EDOperand::evaluate(uint64_t &result, return 0; } } + break; } return -1; diff --git a/contrib/llvm/lib/MC/MCDisassembler/EDToken.cpp b/contrib/llvm/lib/MC/MCDisassembler/EDToken.cpp index 400e164..de770b4 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/EDToken.cpp +++ b/contrib/llvm/lib/MC/MCDisassembler/EDToken.cpp @@ -194,6 +194,10 @@ int EDToken::tokenize(std::vector<EDToken*> &tokens, tokens.push_back(token); } + // Free any parsed operands. + for (unsigned i = 0, e = parsedOperands.size(); i != e; ++i) + delete parsedOperands[i]; + return 0; } diff --git a/contrib/llvm/lib/MC/MCObjectStreamer.cpp b/contrib/llvm/lib/MC/MCObjectStreamer.cpp index 0358266..e67d9b0 100644 --- a/contrib/llvm/lib/MC/MCObjectStreamer.cpp +++ b/contrib/llvm/lib/MC/MCObjectStreamer.cpp @@ -242,7 +242,23 @@ void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, void MCObjectStreamer::EmitValueToOffset(const MCExpr *Offset, unsigned char Value) { - new MCOrgFragment(*Offset, Value, getCurrentSectionData()); + int64_t Res; + if (Offset->EvaluateAsAbsolute(Res, getAssembler())) { + new MCOrgFragment(*Offset, Value, getCurrentSectionData()); + return; + } + + MCSymbol *CurrentPos = getContext().CreateTempSymbol(); + EmitLabel(CurrentPos); + MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; + const MCExpr *Ref = + MCSymbolRefExpr::Create(CurrentPos, Variant, getContext()); + const MCExpr *Delta = + MCBinaryExpr::Create(MCBinaryExpr::Sub, Offset, Ref, getContext()); + + if (!Delta->EvaluateAsAbsolute(Res, getAssembler())) + report_fatal_error("expected assembly-time absolute expression"); + EmitFill(Res, Value, 0); } void MCObjectStreamer::Finish() { diff --git a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp index c6d0da6..a84917f 100644 --- a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp @@ -603,6 +603,8 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { Lex(); // Eat the '('. return ParseParenExpr(Res, EndLoc); case AsmToken::LBrac: + if (!PlatformParser->HasBracketExpressions()) + return TokError("brackets expression not supported on this target"); Lex(); // Eat the '['. return ParseBracketExpr(Res, EndLoc); case AsmToken::Minus: diff --git a/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp index bfaf36a..dcf689a 100644 --- a/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp @@ -30,9 +30,12 @@ class ELFAsmParser : public MCAsmParserExtension { bool ParseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags, SectionKind Kind); + bool SeenIdent; public: - ELFAsmParser() {} + ELFAsmParser() : SeenIdent(false) { + BracketExpressionsSupported = true; + } virtual void Initialize(MCAsmParser &Parser) { // Call the base implementation. @@ -456,13 +459,12 @@ bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) { SectionKind::getReadOnly(), 1, ""); - static bool First = true; - getStreamer().PushSection(); getStreamer().SwitchSection(Comment); - if (First) + if (!SeenIdent) { getStreamer().EmitIntValue(0, 1); - First = false; + SeenIdent = true; + } getStreamer().EmitBytes(Data, 0); getStreamer().EmitIntValue(0, 1); getStreamer().PopSection(); diff --git a/contrib/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp b/contrib/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp index c30d306..3f25a14 100644 --- a/contrib/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp +++ b/contrib/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp @@ -10,7 +10,8 @@ #include "llvm/MC/MCParser/MCAsmParserExtension.h" using namespace llvm; -MCAsmParserExtension::MCAsmParserExtension() { +MCAsmParserExtension::MCAsmParserExtension() : + BracketExpressionsSupported(false) { } MCAsmParserExtension::~MCAsmParserExtension() { diff --git a/contrib/llvm/lib/MC/MCSectionMachO.cpp b/contrib/llvm/lib/MC/MCSectionMachO.cpp index b897c0b..577e93a 100644 --- a/contrib/llvm/lib/MC/MCSectionMachO.cpp +++ b/contrib/llvm/lib/MC/MCSectionMachO.cpp @@ -101,16 +101,18 @@ void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI, return; } - OS << ','; - unsigned SectionType = TAA & MCSectionMachO::SECTION_TYPE; assert(SectionType <= MCSectionMachO::LAST_KNOWN_SECTION_TYPE && "Invalid SectionType specified!"); - if (SectionTypeDescriptors[SectionType].AssemblerName) + if (SectionTypeDescriptors[SectionType].AssemblerName) { + OS << ','; OS << SectionTypeDescriptors[SectionType].AssemblerName; - else - OS << "<<" << SectionTypeDescriptors[SectionType].EnumName << ">>"; + } else { + // If we have no name for the attribute, stop here. + OS << '\n'; + return; + } // If we don't have any attributes, we're done. unsigned SectionAttrs = TAA & MCSectionMachO::SECTION_ATTRIBUTES; @@ -125,7 +127,9 @@ void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI, // Check each attribute to see if we have it. char Separator = ','; - for (unsigned i = 0; SectionAttrDescriptors[i].AttrFlag; ++i) { + for (unsigned i = 0; + SectionAttrs != 0 && SectionAttrDescriptors[i].AttrFlag; + ++i) { // Check to see if we have this attribute. if ((SectionAttrDescriptors[i].AttrFlag & SectionAttrs) == 0) continue; @@ -207,7 +211,6 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In. "between 1 and 16 characters"; // If there is no comma after the section, we're done. - TAA = 0; StubSize = 0; if (Comma.second.empty()) return ""; diff --git a/contrib/llvm/lib/MC/MCStreamer.cpp b/contrib/llvm/lib/MC/MCStreamer.cpp index 3dcdba1..4b302c8 100644 --- a/contrib/llvm/lib/MC/MCStreamer.cpp +++ b/contrib/llvm/lib/MC/MCStreamer.cpp @@ -20,8 +20,8 @@ using namespace llvm; MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx) { - PrevSectionStack.push_back(NULL); - CurSectionStack.push_back(NULL); + const MCSection *section = NULL; + SectionStack.push_back(std::make_pair(section, section)); } MCStreamer::~MCStreamer() { diff --git a/contrib/llvm/lib/Support/APInt.cpp b/contrib/llvm/lib/Support/APInt.cpp index 7703342..08f36d2 100644 --- a/contrib/llvm/lib/Support/APInt.cpp +++ b/contrib/llvm/lib/Support/APInt.cpp @@ -1505,7 +1505,7 @@ APInt::ms APInt::magic() const { r2 = r2 - ad; } delta = ad - r2; - } while (q1.ule(delta) || (q1 == delta && r1 == 0)); + } while (q1.ult(delta) || (q1 == delta && r1 == 0)); mag.m = q2 + 1; if (d.isNegative()) mag.m = -mag.m; // resulting magic number diff --git a/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h b/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h index 1fb8872..7e2183d 100644 --- a/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h @@ -155,10 +155,11 @@ namespace ARMII { //===------------------------------------------------------------------===// // Code domain. DomainShift = 18, - DomainMask = 3 << DomainShift, + DomainMask = 7 << DomainShift, DomainGeneral = 0 << DomainShift, DomainVFP = 1 << DomainShift, DomainNEON = 2 << DomainShift, + DomainNEONA8 = 4 << DomainShift, //===------------------------------------------------------------------===// // Field shifts - such shifts are used to set field while generating diff --git a/contrib/llvm/lib/Target/ARM/ARMFastISel.cpp b/contrib/llvm/lib/Target/ARM/ARMFastISel.cpp index 9f29530..26f48b3 100644 --- a/contrib/llvm/lib/Target/ARM/ARMFastISel.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMFastISel.cpp @@ -172,6 +172,7 @@ class ARMFastISel : public FastISel { unsigned ARMMaterializeGV(const GlobalValue *GV, EVT VT); unsigned ARMMoveToFPReg(EVT VT, unsigned SrcReg); unsigned ARMMoveToIntReg(EVT VT, unsigned SrcReg); + unsigned ARMSelectCallOp(const GlobalValue *GV); // Call handling routines. private: @@ -1633,6 +1634,25 @@ bool ARMFastISel::SelectRet(const Instruction *I) { return true; } +unsigned ARMFastISel::ARMSelectCallOp(const GlobalValue *GV) { + + // Depend our opcode for thumb on whether or not we're targeting an + // externally callable function. For libcalls we'll just pass a NULL GV + // in here. + bool isExternal = false; + if (!GV || GV->hasExternalLinkage()) isExternal = true; + + // Darwin needs the r9 versions of the opcodes. + bool isDarwin = Subtarget->isTargetDarwin(); + if (isThumb && isExternal) { + return isDarwin ? ARM::tBLXi_r9 : ARM::tBLXi; + } else if (isThumb) { + return isDarwin ? ARM::tBLr9 : ARM::tBL; + } else { + return isDarwin ? ARM::BLr9 : ARM::BL; + } +} + // A quick function that will emit a call for a named libcall in F with the // vector of passed arguments for the Instruction in I. We can assume that we // can emit a call for any libcall we can produce. This is an abridged version @@ -1694,20 +1714,17 @@ bool ARMFastISel::ARMEmitLibcall(const Instruction *I, RTLIB::Libcall Call) { // Issue the call, BLXr9 for darwin, BLX otherwise. This uses V5 ops. // TODO: Turn this into the table of arm call ops. MachineInstrBuilder MIB; - unsigned CallOpc; - if(isThumb) { - CallOpc = Subtarget->isTargetDarwin() ? ARM::tBLXi_r9 : ARM::tBLXi; + unsigned CallOpc = ARMSelectCallOp(NULL); + if(isThumb) // Explicitly adding the predicate here. MIB = AddDefaultPred(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(CallOpc))) .addExternalSymbol(TLI.getLibcallName(Call)); - } else { - CallOpc = Subtarget->isTargetDarwin() ? ARM::BLr9 : ARM::BL; + else // Explicitly adding the predicate here. MIB = AddDefaultPred(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(CallOpc)) .addExternalSymbol(TLI.getLibcallName(Call))); - } // Add implicit physical register uses to the call. for (unsigned i = 0, e = RegArgs.size(); i != e; ++i) @@ -1813,21 +1830,18 @@ bool ARMFastISel::SelectCall(const Instruction *I) { // Issue the call, BLXr9 for darwin, BLX otherwise. This uses V5 ops. // TODO: Turn this into the table of arm call ops. MachineInstrBuilder MIB; - unsigned CallOpc; + unsigned CallOpc = ARMSelectCallOp(GV); // Explicitly adding the predicate here. - if(isThumb) { - CallOpc = Subtarget->isTargetDarwin() ? ARM::tBLXi_r9 : ARM::tBLXi; + if(isThumb) // Explicitly adding the predicate here. MIB = AddDefaultPred(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(CallOpc))) .addGlobalAddress(GV, 0, 0); - } else { - CallOpc = Subtarget->isTargetDarwin() ? ARM::BLr9 : ARM::BL; + else // Explicitly adding the predicate here. MIB = AddDefaultPred(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(CallOpc)) .addGlobalAddress(GV, 0, 0)); - } // Add implicit physical register uses to the call. for (unsigned i = 0, e = RegArgs.size(); i != e; ++i) diff --git a/contrib/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/contrib/llvm/lib/Target/ARM/ARMFrameLowering.cpp index f42c6db..68c33f0 100644 --- a/contrib/llvm/lib/Target/ARM/ARMFrameLowering.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMFrameLowering.cpp @@ -215,7 +215,13 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset); // Move past area 3. - if (DPRCSSize > 0) MBBI++; + if (DPRCSSize > 0) { + MBBI++; + // Since vpush register list cannot have gaps, there may be multiple vpush + // instructions in the prologue. + while (MBBI->getOpcode() == ARM::VSTMDDB_UPD) + MBBI++; + } NumBytes = DPRCSOffset; if (NumBytes) { @@ -370,7 +376,13 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF, emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes); // Increment past our save areas. - if (AFI->getDPRCalleeSavedAreaSize()) MBBI++; + if (AFI->getDPRCalleeSavedAreaSize()) { + MBBI++; + // Since vpop register list cannot have gaps, there may be multiple vpop + // instructions in the epilogue. + while (MBBI->getOpcode() == ARM::VLDMDIA_UPD) + MBBI++; + } if (AFI->getGPRCalleeSavedArea2Size()) MBBI++; if (AFI->getGPRCalleeSavedArea1Size()) MBBI++; } diff --git a/contrib/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp b/contrib/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp index 676b01e..e97ce50 100644 --- a/contrib/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp @@ -21,17 +21,14 @@ static bool hasRAWHazard(MachineInstr *DefMI, MachineInstr *MI, // FIXME: Detect integer instructions properly. const TargetInstrDesc &TID = MI->getDesc(); unsigned Domain = TID.TSFlags & ARMII::DomainMask; - if (Domain == ARMII::DomainVFP) { - unsigned Opcode = MI->getOpcode(); - if (Opcode == ARM::VSTRS || Opcode == ARM::VSTRD || - Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD) - return false; - } else if (Domain == ARMII::DomainNEON) { - if (MI->getDesc().mayStore() || MI->getDesc().mayLoad()) - return false; - } else + if (TID.mayStore()) return false; - return MI->readsRegister(DefMI->getOperand(0).getReg(), &TRI); + unsigned Opcode = TID.getOpcode(); + if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD) + return false; + if ((Domain & ARMII::DomainVFP) || (Domain & ARMII::DomainNEON)) + return MI->readsRegister(DefMI->getOperand(0).getReg(), &TRI); + return false; } ScheduleHazardRecognizer::HazardType diff --git a/contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp b/contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp index a506cff..f0d5a7d 100644 --- a/contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -126,6 +126,7 @@ public: bool SelectAddrMode5(SDValue N, SDValue &Base, SDValue &Offset); bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align); + bool SelectAddrMode6Offset(SDNode *Op, SDValue N, SDValue &Offset); bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label); @@ -886,6 +887,20 @@ bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr, return true; } +bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N, + SDValue &Offset) { + LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op); + ISD::MemIndexedMode AM = LdSt->getAddressingMode(); + if (AM != ISD::POST_INC) + return false; + Offset = N; + if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) { + if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits()) + Offset = CurDAG->getRegister(0, MVT::i32); + } + return true; +} + bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label) { if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) { diff --git a/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp b/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp index 1835ec0..ab9f9e1 100644 --- a/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -2236,7 +2236,7 @@ ARMTargetLowering::GetF64FormalArgument(CCValAssign &VA, CCValAssign &NextVA, RC = ARM::GPRRegisterClass; // Transform the arguments stored in physical registers into virtual ones. - unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC, dl); + unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC); SDValue ArgValue = DAG.getCopyFromReg(Root, dl, Reg, MVT::i32); SDValue ArgValue2; @@ -2250,7 +2250,7 @@ ARMTargetLowering::GetF64FormalArgument(CCValAssign &VA, CCValAssign &NextVA, MachinePointerInfo::getFixedStack(FI), false, false, 0); } else { - Reg = MF.addLiveIn(NextVA.getLocReg(), RC, dl); + Reg = MF.addLiveIn(NextVA.getLocReg(), RC); ArgValue2 = DAG.getCopyFromReg(Root, dl, Reg, MVT::i32); } @@ -2331,7 +2331,7 @@ ARMTargetLowering::LowerFormalArguments(SDValue Chain, llvm_unreachable("RegVT not supported by FORMAL_ARGUMENTS Lowering"); // Transform the arguments in physical registers into virtual ones. - unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC, dl); + unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC); ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT); } @@ -2408,7 +2408,7 @@ ARMTargetLowering::LowerFormalArguments(SDValue Chain, else RC = ARM::GPRRegisterClass; - unsigned VReg = MF.addLiveIn(GPRArgRegs[NumGPRs], RC, dl); + unsigned VReg = MF.addLiveIn(GPRArgRegs[NumGPRs], RC); SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, @@ -2838,8 +2838,51 @@ SDValue ARMTargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const { DebugLoc dl = Op.getDebugLoc(); EVT VT = Op.getValueType(); EVT SrcVT = Tmp1.getValueType(); - bool F2IisFast = Subtarget->isCortexA9() || - Tmp0.getOpcode() == ISD::BITCAST || Tmp0.getOpcode() == ARMISD::VMOVDRR; + bool InGPR = Tmp0.getOpcode() == ISD::BITCAST || + Tmp0.getOpcode() == ARMISD::VMOVDRR; + bool UseNEON = !InGPR && Subtarget->hasNEON(); + + if (UseNEON) { + // Use VBSL to copy the sign bit. + unsigned EncodedVal = ARM_AM::createNEONModImm(0x6, 0x80); + SDValue Mask = DAG.getNode(ARMISD::VMOVIMM, dl, MVT::v2i32, + DAG.getTargetConstant(EncodedVal, MVT::i32)); + EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64; + if (VT == MVT::f64) + Mask = DAG.getNode(ARMISD::VSHL, dl, OpVT, + DAG.getNode(ISD::BITCAST, dl, OpVT, Mask), + DAG.getConstant(32, MVT::i32)); + else /*if (VT == MVT::f32)*/ + Tmp0 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v2f32, Tmp0); + if (SrcVT == MVT::f32) { + Tmp1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v2f32, Tmp1); + if (VT == MVT::f64) + Tmp1 = DAG.getNode(ARMISD::VSHL, dl, OpVT, + DAG.getNode(ISD::BITCAST, dl, OpVT, Tmp1), + DAG.getConstant(32, MVT::i32)); + } + Tmp0 = DAG.getNode(ISD::BITCAST, dl, OpVT, Tmp0); + Tmp1 = DAG.getNode(ISD::BITCAST, dl, OpVT, Tmp1); + + SDValue AllOnes = DAG.getTargetConstant(ARM_AM::createNEONModImm(0xe, 0xff), + MVT::i32); + AllOnes = DAG.getNode(ARMISD::VMOVIMM, dl, MVT::v8i8, AllOnes); + SDValue MaskNot = DAG.getNode(ISD::XOR, dl, OpVT, Mask, + DAG.getNode(ISD::BITCAST, dl, OpVT, AllOnes)); + + SDValue Res = DAG.getNode(ISD::OR, dl, OpVT, + DAG.getNode(ISD::AND, dl, OpVT, Tmp1, Mask), + DAG.getNode(ISD::AND, dl, OpVT, Tmp0, MaskNot)); + if (SrcVT == MVT::f32) { + Res = DAG.getNode(ISD::BITCAST, dl, MVT::v2f32, Res); + Res = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f32, Res, + DAG.getConstant(0, MVT::i32)); + } else { + Res = DAG.getNode(ISD::BITCAST, dl, MVT::f64, Res); + } + + return Res; + } // Bitcast operand 1 to i32. if (SrcVT == MVT::f64) @@ -2847,37 +2890,24 @@ SDValue ARMTargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const { &Tmp1, 1).getValue(1); Tmp1 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Tmp1); - // If float to int conversion isn't going to be super expensive, then simply - // or in the signbit. - if (F2IisFast) { - SDValue Mask1 = DAG.getConstant(0x80000000, MVT::i32); - SDValue Mask2 = DAG.getConstant(0x7fffffff, MVT::i32); - Tmp1 = DAG.getNode(ISD::AND, dl, MVT::i32, Tmp1, Mask1); - if (VT == MVT::f32) { - Tmp0 = DAG.getNode(ISD::AND, dl, MVT::i32, - DAG.getNode(ISD::BITCAST, dl, MVT::i32, Tmp0), Mask2); - return DAG.getNode(ISD::BITCAST, dl, MVT::f32, - DAG.getNode(ISD::OR, dl, MVT::i32, Tmp0, Tmp1)); - } - - // f64: Or the high part with signbit and then combine two parts. - Tmp0 = DAG.getNode(ARMISD::VMOVRRD, dl, DAG.getVTList(MVT::i32, MVT::i32), - &Tmp0, 1); - SDValue Lo = Tmp0.getValue(0); - SDValue Hi = DAG.getNode(ISD::AND, dl, MVT::i32, Tmp0.getValue(1), Mask2); - Hi = DAG.getNode(ISD::OR, dl, MVT::i32, Hi, Tmp1); - return DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, Lo, Hi); + // Or in the signbit with integer operations. + SDValue Mask1 = DAG.getConstant(0x80000000, MVT::i32); + SDValue Mask2 = DAG.getConstant(0x7fffffff, MVT::i32); + Tmp1 = DAG.getNode(ISD::AND, dl, MVT::i32, Tmp1, Mask1); + if (VT == MVT::f32) { + Tmp0 = DAG.getNode(ISD::AND, dl, MVT::i32, + DAG.getNode(ISD::BITCAST, dl, MVT::i32, Tmp0), Mask2); + return DAG.getNode(ISD::BITCAST, dl, MVT::f32, + DAG.getNode(ISD::OR, dl, MVT::i32, Tmp0, Tmp1)); } - // Remove the signbit of operand 0. - Tmp0 = DAG.getNode(ISD::FABS, dl, VT, Tmp0); - - // If operand 1 signbit is one, then negate operand 0. - SDValue ARMcc; - SDValue Cmp = getARMCmp(Tmp1, DAG.getConstant(0, MVT::i32), - ISD::SETLT, ARMcc, DAG, dl); - SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32); - return DAG.getNode(ARMISD::CNEG, dl, VT, Tmp0, Tmp0, ARMcc, CCR, Cmp); + // f64: Or the high part with signbit and then combine two parts. + Tmp0 = DAG.getNode(ARMISD::VMOVRRD, dl, DAG.getVTList(MVT::i32, MVT::i32), + &Tmp0, 1); + SDValue Lo = Tmp0.getValue(0); + SDValue Hi = DAG.getNode(ISD::AND, dl, MVT::i32, Tmp0.getValue(1), Mask2); + Hi = DAG.getNode(ISD::OR, dl, MVT::i32, Hi, Tmp1); + return DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, Lo, Hi); } SDValue ARMTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const{ @@ -2897,7 +2927,7 @@ SDValue ARMTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const{ } // Return LR, which contains the return address. Mark it an implicit live-in. - unsigned Reg = MF.addLiveIn(ARM::LR, getRegClassFor(MVT::i32), dl); + unsigned Reg = MF.addLiveIn(ARM::LR, getRegClassFor(MVT::i32)); return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, VT); } diff --git a/contrib/llvm/lib/Target/ARM/ARMInstrFormats.td b/contrib/llvm/lib/Target/ARM/ARMInstrFormats.td index 765cba4..359ac45 100644 --- a/contrib/llvm/lib/Target/ARM/ARMInstrFormats.td +++ b/contrib/llvm/lib/Target/ARM/ARMInstrFormats.td @@ -127,13 +127,14 @@ def IndexModePost : IndexMode<2>; def IndexModeUpd : IndexMode<3>; // Instruction execution domain. -class Domain<bits<2> val> { - bits<2> Value = val; +class Domain<bits<3> val> { + bits<3> Value = val; } def GenericDomain : Domain<0>; def VFPDomain : Domain<1>; // Instructions in VFP domain only def NeonDomain : Domain<2>; // Instructions in Neon domain only def VFPNeonDomain : Domain<3>; // Instructions in both VFP & Neon domains +def VFPNeonA8Domain : Domain<5>; // Instructions in VFP & Neon under A8 //===----------------------------------------------------------------------===// // ARM special operands. @@ -249,7 +250,7 @@ class InstTemplate<AddrMode am, SizeFlagVal sz, IndexMode im, let TSFlags{15-10} = Form; let TSFlags{16} = isUnaryDataProc; let TSFlags{17} = canXformTo16Bit; - let TSFlags{19-18} = D.Value; + let TSFlags{20-18} = D.Value; let Constraints = cstr; let Itinerary = itin; diff --git a/contrib/llvm/lib/Target/ARM/ARMInstrInfo.td b/contrib/llvm/lib/Target/ARM/ARMInstrInfo.td index c827ce3d..6e3fe2e 100644 --- a/contrib/llvm/lib/Target/ARM/ARMInstrInfo.td +++ b/contrib/llvm/lib/Target/ARM/ARMInstrInfo.td @@ -561,7 +561,9 @@ def addrmode6 : Operand<i32>, let EncoderMethod = "getAddrMode6AddressOpValue"; } -def am6offset : Operand<i32> { +def am6offset : Operand<i32>, + ComplexPattern<i32, 1, "SelectAddrMode6Offset", + [], [SDNPWantRoot]> { let PrintMethod = "printAddrMode6OffsetOperand"; let MIOperandInfo = (ops GPR); let EncoderMethod = "getAddrMode6OffsetOpValue"; diff --git a/contrib/llvm/lib/Target/ARM/ARMInstrNEON.td b/contrib/llvm/lib/Target/ARM/ARMInstrNEON.td index 1e2e550..dc3d63e 100644 --- a/contrib/llvm/lib/Target/ARM/ARMInstrNEON.td +++ b/contrib/llvm/lib/Target/ARM/ARMInstrNEON.td @@ -1402,31 +1402,42 @@ def : Pat<(store (extractelt (v2f32 DPR:$src), imm:$lane), addrmode6:$addr), def : Pat<(store (extractelt (v4f32 QPR:$src), imm:$lane), addrmode6:$addr), (VST1LNq32Pseudo addrmode6:$addr, QPR:$src, imm:$lane)>; -let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in { - // ...with address register writeback: -class VST1LNWB<bits<4> op11_8, bits<4> op7_4, string Dt> +class VST1LNWB<bits<4> op11_8, bits<4> op7_4, string Dt, ValueType Ty, + PatFrag StoreOp, SDNode ExtractOp> : NLdStLn<1, 0b00, op11_8, op7_4, (outs GPR:$wb), (ins addrmode6:$Rn, am6offset:$Rm, DPR:$Vd, nohash_imm:$lane), IIC_VST1lnu, "vst1", Dt, "\\{$Vd[$lane]\\}, $Rn$Rm", - "$Rn.addr = $wb", []>; + "$Rn.addr = $wb", + [(set GPR:$wb, (StoreOp (ExtractOp (Ty DPR:$Vd), imm:$lane), + addrmode6:$Rn, am6offset:$Rm))]>; +class VST1QLNWBPseudo<ValueType Ty, PatFrag StoreOp, SDNode ExtractOp> + : VSTQLNWBPseudo<IIC_VST1lnu> { + let Pattern = [(set GPR:$wb, (StoreOp (ExtractOp (Ty QPR:$src), imm:$lane), + addrmode6:$addr, am6offset:$offset))]; +} -def VST1LNd8_UPD : VST1LNWB<0b0000, {?,?,?,0}, "8"> { +def VST1LNd8_UPD : VST1LNWB<0b0000, {?,?,?,0}, "8", v8i8, post_truncsti8, + NEONvgetlaneu> { let Inst{7-5} = lane{2-0}; } -def VST1LNd16_UPD : VST1LNWB<0b0100, {?,?,0,?}, "16"> { +def VST1LNd16_UPD : VST1LNWB<0b0100, {?,?,0,?}, "16", v4i16, post_truncsti16, + NEONvgetlaneu> { let Inst{7-6} = lane{1-0}; let Inst{4} = Rn{5}; } -def VST1LNd32_UPD : VST1LNWB<0b1000, {?,0,?,?}, "32"> { +def VST1LNd32_UPD : VST1LNWB<0b1000, {?,0,?,?}, "32", v2i32, post_store, + extractelt> { let Inst{7} = lane{0}; let Inst{5-4} = Rn{5-4}; } -def VST1LNq8Pseudo_UPD : VSTQLNWBPseudo<IIC_VST1lnu>; -def VST1LNq16Pseudo_UPD : VSTQLNWBPseudo<IIC_VST1lnu>; -def VST1LNq32Pseudo_UPD : VSTQLNWBPseudo<IIC_VST1lnu>; +def VST1LNq8Pseudo_UPD : VST1QLNWBPseudo<v16i8, post_truncsti8, NEONvgetlaneu>; +def VST1LNq16Pseudo_UPD : VST1QLNWBPseudo<v8i16, post_truncsti16,NEONvgetlaneu>; +def VST1LNq32Pseudo_UPD : VST1QLNWBPseudo<v4i32, post_store, extractelt>; + +let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in { // VST2LN : Vector Store (single 2-element structure from one lane) class VST2LN<bits<4> op11_8, bits<4> op7_4, string Dt> diff --git a/contrib/llvm/lib/Target/ARM/ARMInstrVFP.td b/contrib/llvm/lib/Target/ARM/ARMInstrVFP.td index 920c5c9..2990283 100644 --- a/contrib/llvm/lib/Target/ARM/ARMInstrVFP.td +++ b/contrib/llvm/lib/Target/ARM/ARMInstrVFP.td @@ -197,9 +197,9 @@ def VADDS : ASbIn<0b11100, 0b11, 0, 0, (outs SPR:$Sd), (ins SPR:$Sn, SPR:$Sm), IIC_fpALU32, "vadd", ".f32\t$Sd, $Sn, $Sm", [(set SPR:$Sd, (fadd SPR:$Sn, SPR:$Sm))]> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } def VSUBD : ADbI<0b11100, 0b11, 1, 0, @@ -211,9 +211,9 @@ def VSUBS : ASbIn<0b11100, 0b11, 1, 0, (outs SPR:$Sd), (ins SPR:$Sn, SPR:$Sm), IIC_fpALU32, "vsub", ".f32\t$Sd, $Sn, $Sm", [(set SPR:$Sd, (fsub SPR:$Sn, SPR:$Sm))]> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } def VDIVD : ADbI<0b11101, 0b00, 0, 0, @@ -235,9 +235,9 @@ def VMULS : ASbIn<0b11100, 0b10, 0, 0, (outs SPR:$Sd), (ins SPR:$Sn, SPR:$Sm), IIC_fpMUL32, "vmul", ".f32\t$Sd, $Sn, $Sm", [(set SPR:$Sd, (fmul SPR:$Sn, SPR:$Sm))]> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } def VNMULD : ADbI<0b11100, 0b10, 1, 0, @@ -249,9 +249,9 @@ def VNMULS : ASbI<0b11100, 0b10, 1, 0, (outs SPR:$Sd), (ins SPR:$Sn, SPR:$Sm), IIC_fpMUL32, "vnmul", ".f32\t$Sd, $Sn, $Sm", [(set SPR:$Sd, (fneg (fmul SPR:$Sn, SPR:$Sm)))]> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } // Match reassociated forms only if not sign dependent rounding. @@ -271,9 +271,9 @@ def VCMPES : ASuI<0b11101, 0b11, 0b0100, 0b11, 0, (outs), (ins SPR:$Sd, SPR:$Sm), IIC_fpCMP32, "vcmpe", ".f32\t$Sd, $Sm", [(arm_cmpfp SPR:$Sd, SPR:$Sm)]> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } // FIXME: Verify encoding after integrated assembler is working. @@ -286,9 +286,9 @@ def VCMPS : ASuI<0b11101, 0b11, 0b0100, 0b01, 0, (outs), (ins SPR:$Sd, SPR:$Sm), IIC_fpCMP32, "vcmp", ".f32\t$Sd, $Sm", [/* For disassembly only; pattern left blank */]> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } } // Defs = [FPSCR] @@ -305,9 +305,9 @@ def VABSS : ASuIn<0b11101, 0b11, 0b0000, 0b11, 0, (outs SPR:$Sd), (ins SPR:$Sm), IIC_fpUNA32, "vabs", ".f32\t$Sd, $Sm", [(set SPR:$Sd, (fabs SPR:$Sm))]> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } let Defs = [FPSCR] in { @@ -326,9 +326,9 @@ def VCMPEZS : ASuI<0b11101, 0b11, 0b0101, 0b11, 0, let Inst{3-0} = 0b0000; let Inst{5} = 0; - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } // FIXME: Verify encoding after integrated assembler is working. @@ -347,9 +347,9 @@ def VCMPZS : ASuI<0b11101, 0b11, 0b0101, 0b01, 0, let Inst{3-0} = 0b0000; let Inst{5} = 0; - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } } // Defs = [FPSCR] @@ -423,9 +423,9 @@ def VNEGS : ASuIn<0b11101, 0b11, 0b0001, 0b01, 0, (outs SPR:$Sd), (ins SPR:$Sm), IIC_fpUNA32, "vneg", ".f32\t$Sd, $Sm", [(set SPR:$Sd, (fneg SPR:$Sm))]> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } def VSQRTD : ADuI<0b11101, 0b11, 0b0001, 0b11, 0, @@ -598,9 +598,9 @@ def VSITOS : AVConv1InSs_Encode<0b11101, 0b11, 0b1000, 0b1010, [(set SPR:$Sd, (arm_sitof SPR:$Sm))]> { let Inst{7} = 1; // s32 - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } def VUITOD : AVConv1IDs_Encode<0b11101, 0b11, 0b1000, 0b1011, @@ -616,9 +616,9 @@ def VUITOS : AVConv1InSs_Encode<0b11101, 0b11, 0b1000, 0b1010, [(set SPR:$Sd, (arm_uitof SPR:$Sm))]> { let Inst{7} = 0; // u32 - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } // FP -> Int: @@ -671,9 +671,9 @@ def VTOSIZS : AVConv1InsS_Encode<0b11101, 0b11, 0b1101, 0b1010, [(set SPR:$Sd, (arm_ftosi SPR:$Sm))]> { let Inst{7} = 1; // Z bit - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } def VTOUIZD : AVConv1IsD_Encode<0b11101, 0b11, 0b1100, 0b1011, @@ -689,9 +689,9 @@ def VTOUIZS : AVConv1InsS_Encode<0b11101, 0b11, 0b1100, 0b1010, [(set SPR:$Sd, (arm_ftoui SPR:$Sm))]> { let Inst{7} = 1; // Z bit - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } // And the Z bit '0' variants, i.e. use the rounding mode specified by FPSCR. @@ -743,36 +743,36 @@ def VTOSHS : AVConv1XI<0b11101, 0b11, 0b1110, 0b1010, 0, (outs SPR:$dst), (ins SPR:$a, i32imm:$fbits), IIC_fpCVTSI, "vcvt", ".s16.f32\t$dst, $a, $fbits", [/* For disassembly only; pattern left blank */]> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } def VTOUHS : AVConv1XI<0b11101, 0b11, 0b1111, 0b1010, 0, (outs SPR:$dst), (ins SPR:$a, i32imm:$fbits), IIC_fpCVTSI, "vcvt", ".u16.f32\t$dst, $a, $fbits", [/* For disassembly only; pattern left blank */]> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } def VTOSLS : AVConv1XI<0b11101, 0b11, 0b1110, 0b1010, 1, (outs SPR:$dst), (ins SPR:$a, i32imm:$fbits), IIC_fpCVTSI, "vcvt", ".s32.f32\t$dst, $a, $fbits", [/* For disassembly only; pattern left blank */]> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } def VTOULS : AVConv1XI<0b11101, 0b11, 0b1111, 0b1010, 1, (outs SPR:$dst), (ins SPR:$a, i32imm:$fbits), IIC_fpCVTSI, "vcvt", ".u32.f32\t$dst, $a, $fbits", [/* For disassembly only; pattern left blank */]> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } def VTOSHD : AVConv1XI<0b11101, 0b11, 0b1110, 0b1011, 0, @@ -801,36 +801,36 @@ def VSHTOS : AVConv1XI<0b11101, 0b11, 0b1010, 0b1010, 0, (outs SPR:$dst), (ins SPR:$a, i32imm:$fbits), IIC_fpCVTIS, "vcvt", ".f32.s16\t$dst, $a, $fbits", [/* For disassembly only; pattern left blank */]> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } def VUHTOS : AVConv1XI<0b11101, 0b11, 0b1011, 0b1010, 0, (outs SPR:$dst), (ins SPR:$a, i32imm:$fbits), IIC_fpCVTIS, "vcvt", ".f32.u16\t$dst, $a, $fbits", [/* For disassembly only; pattern left blank */]> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } def VSLTOS : AVConv1XI<0b11101, 0b11, 0b1010, 0b1010, 1, (outs SPR:$dst), (ins SPR:$a, i32imm:$fbits), IIC_fpCVTIS, "vcvt", ".f32.s32\t$dst, $a, $fbits", [/* For disassembly only; pattern left blank */]> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } def VULTOS : AVConv1XI<0b11101, 0b11, 0b1011, 0b1010, 1, (outs SPR:$dst), (ins SPR:$a, i32imm:$fbits), IIC_fpCVTIS, "vcvt", ".f32.u32\t$dst, $a, $fbits", [/* For disassembly only; pattern left blank */]> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } def VSHTOD : AVConv1XI<0b11101, 0b11, 0b1010, 0b1011, 0, @@ -874,9 +874,9 @@ def VMLAS : ASbIn<0b11100, 0b00, 0, 0, SPR:$Sdin))]>, RegConstraint<"$Sdin = $Sd">, Requires<[HasVFP2,DontUseNEONForFP,UseFPVMLx]> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } def : Pat<(fadd_mlx DPR:$dstin, (fmul_su DPR:$a, (f64 DPR:$b))), @@ -901,9 +901,9 @@ def VMLSS : ASbIn<0b11100, 0b00, 1, 0, SPR:$Sdin))]>, RegConstraint<"$Sdin = $Sd">, Requires<[HasVFP2,DontUseNEONForFP,UseFPVMLx]> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } def : Pat<(fsub_mlx DPR:$dstin, (fmul_su DPR:$a, (f64 DPR:$b))), @@ -928,9 +928,9 @@ def VNMLAS : ASbI<0b11100, 0b01, 1, 0, SPR:$Sdin))]>, RegConstraint<"$Sdin = $Sd">, Requires<[HasVFP2,DontUseNEONForFP,UseFPVMLx]> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } def : Pat<(fsub_mlx (fneg (fmul_su DPR:$a, (f64 DPR:$b))), DPR:$dstin), @@ -954,9 +954,9 @@ def VNMLSS : ASbI<0b11100, 0b01, 0, 0, [(set SPR:$Sd, (fsub_mlx (fmul_su SPR:$Sn, SPR:$Sm), SPR:$Sdin))]>, RegConstraint<"$Sdin = $Sd">, Requires<[HasVFP2,DontUseNEONForFP,UseFPVMLx]> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } def : Pat<(fsub_mlx (fmul_su DPR:$a, (f64 DPR:$b)), DPR:$dstin), @@ -995,9 +995,9 @@ def VNEGScc : ASuI<0b11101, 0b11, 0b0001, 0b01, 0, IIC_fpUNA32, "vneg", ".f32\t$Sd, $Sm", [/*(set SPR:$Sd, (ARMcneg SPR:$Sn, SPR:$Sm, imm:$cc))*/]>, RegConstraint<"$Sn = $Sd"> { - // Some single precision VFP instructions may be executed on both NEON and VFP - // pipelines. - let D = VFPNeonDomain; + // Some single precision VFP instructions may be executed on both NEON and + // VFP pipelines on A8. + let D = VFPNeonA8Domain; } } // neverHasSideEffects diff --git a/contrib/llvm/lib/Target/ARM/ARMSubtarget.cpp b/contrib/llvm/lib/Target/ARM/ARMSubtarget.cpp index 0bd740c..1465984 100644 --- a/contrib/llvm/lib/Target/ARM/ARMSubtarget.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMSubtarget.cpp @@ -171,7 +171,9 @@ ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV, // Materializable GVs (in JIT lazy compilation mode) do not require an extra // load from stub. - bool isDecl = GV->isDeclaration() && !GV->isMaterializable(); + bool isDecl = GV->hasAvailableExternallyLinkage(); + if (GV->isDeclaration() && !GV->isMaterializable()) + isDecl = true; if (!isTargetDarwin()) { // Extra load is needed for all externally visible. diff --git a/contrib/llvm/lib/Target/ARM/MLxExpansionPass.cpp b/contrib/llvm/lib/Target/ARM/MLxExpansionPass.cpp index f9e86eb..9a27e2f 100644 --- a/contrib/llvm/lib/Target/ARM/MLxExpansionPass.cpp +++ b/contrib/llvm/lib/Target/ARM/MLxExpansionPass.cpp @@ -132,22 +132,16 @@ unsigned MLxExpansion::getDefReg(MachineInstr *MI) const { } bool MLxExpansion::hasRAWHazard(unsigned Reg, MachineInstr *MI) const { - const TargetInstrDesc &TID = MI->getDesc(); // FIXME: Detect integer instructions properly. + const TargetInstrDesc &TID = MI->getDesc(); unsigned Domain = TID.TSFlags & ARMII::DomainMask; - if (Domain == ARMII::DomainVFP) { - unsigned Opcode = TID.getOpcode(); - if (Opcode == ARM::VSTRS || Opcode == ARM::VSTRD || - Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD) - return false; - } else if (Domain == ARMII::DomainNEON) { - if (TID.mayStore() || TID.mayLoad()) - return false; - } else { + if (TID.mayStore()) return false; - } - - return MI->readsRegister(Reg, TRI); + unsigned Opcode = TID.getOpcode(); + if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD) + return false; + if ((Domain & ARMII::DomainVFP) || (Domain & ARMII::DomainNEON)) + return MI->readsRegister(Reg, TRI); return false; } diff --git a/contrib/llvm/lib/Target/ARM/NEONMoveFix.cpp b/contrib/llvm/lib/Target/ARM/NEONMoveFix.cpp index 97e54bf..965665c 100644 --- a/contrib/llvm/lib/Target/ARM/NEONMoveFix.cpp +++ b/contrib/llvm/lib/Target/ARM/NEONMoveFix.cpp @@ -35,6 +35,7 @@ namespace { private: const TargetRegisterInfo *TRI; const ARMBaseInstrInfo *TII; + bool isA8; typedef DenseMap<unsigned, const MachineInstr*> RegMap; @@ -43,6 +44,11 @@ namespace { char NEONMoveFixPass::ID = 0; } +static bool inNEONDomain(unsigned Domain, bool isA8) { + return (Domain & ARMII::DomainNEON) || + (isA8 && (Domain & ARMII::DomainNEONA8)); +} + bool NEONMoveFixPass::InsertMoves(MachineBasicBlock &MBB) { RegMap Defs; bool Modified = false; @@ -70,7 +76,7 @@ bool NEONMoveFixPass::InsertMoves(MachineBasicBlock &MBB) { Domain = ARMII::DomainNEON; } - if (Domain & ARMII::DomainNEON) { + if (inNEONDomain(Domain, isA8)) { // Convert VMOVD to VMOVDneon unsigned DestReg = MI->getOperand(0).getReg(); @@ -123,6 +129,7 @@ bool NEONMoveFixPass::runOnMachineFunction(MachineFunction &Fn) { TRI = TM.getRegisterInfo(); TII = static_cast<const ARMBaseInstrInfo*>(TM.getInstrInfo()); + isA8 = TM.getSubtarget<ARMSubtarget>().isCortexA8(); bool Modified = false; for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; diff --git a/contrib/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp b/contrib/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp index 2f67257..9b1073b 100644 --- a/contrib/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp +++ b/contrib/llvm/lib/Target/ARM/Thumb2InstrInfo.cpp @@ -95,6 +95,12 @@ Thumb2InstrInfo::ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail, bool Thumb2InstrInfo::isLegalToSplitMBBAt(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const { + while (MBBI->isDebugValue()) { + ++MBBI; + if (MBBI == MBB.end()) + return false; + } + unsigned PredReg = 0; return llvm::getITInstrPredicate(MBBI, PredReg) == ARMCC::AL; } diff --git a/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.cpp b/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.cpp index 9137d65..c4f43ab 100644 --- a/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.cpp +++ b/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.cpp @@ -48,7 +48,6 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM, new TargetLoweringObjectFileELF()) { // Set up the TargetLowering object. //I am having problems with shr n i8 1 - setShiftAmountType(MVT::i64); setBooleanContents(ZeroOrOneBooleanContent); addRegisterClass(MVT::i64, Alpha::GPRCRegisterClass); diff --git a/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.h b/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.h index b429e9f..cb98f92 100644 --- a/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.h +++ b/contrib/llvm/lib/Target/Alpha/AlphaISelLowering.h @@ -31,25 +31,25 @@ namespace llvm { /// GPRelHi/GPRelLo - These represent the high and low 16-bit /// parts of a global address respectively. - GPRelHi, GPRelLo, + GPRelHi, GPRelLo, /// RetLit - Literal Relocation of a Global RelLit, /// GlobalRetAddr - used to restore the return address GlobalRetAddr, - + /// CALL - Normal call. CALL, /// DIVCALL - used for special library calls for div and rem DivCall, - + /// return flag operand RET_FLAG, /// CHAIN = COND_BRANCH CHAIN, OPC, (G|F)PRC, DESTBB [, INFLAG] - This - /// corresponds to the COND_BRANCH pseudo instruction. + /// corresponds to the COND_BRANCH pseudo instruction. /// *PRC is the input register to compare to zero, /// OPC is the branch opcode to use (e.g. Alpha::BEQ), /// DESTBB is the destination block to branch to, and INFLAG is @@ -62,7 +62,9 @@ namespace llvm { class AlphaTargetLowering : public TargetLowering { public: explicit AlphaTargetLowering(TargetMachine &TM); - + + virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i64; } + /// getSetCCResultType - Get the SETCC result ValueType virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const; @@ -92,7 +94,7 @@ namespace llvm { ConstraintWeight getSingleConstraintMatchWeight( AsmOperandInfo &info, const char *constraint) const; - std::vector<unsigned> + std::vector<unsigned> getRegClassForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.cpp b/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.cpp index dd27d0a..7c80eec 100644 --- a/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.cpp +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.cpp @@ -41,7 +41,6 @@ using namespace llvm; BlackfinTargetLowering::BlackfinTargetLowering(TargetMachine &TM) : TargetLowering(TM, new TargetLoweringObjectFileELF()) { - setShiftAmountType(MVT::i16); setBooleanContents(ZeroOrOneBooleanContent); setStackPointerRegisterToSaveRestore(BF::SP); setIntDivIsCheap(false); diff --git a/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.h b/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.h index 15a745f..102c830 100644 --- a/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.h +++ b/contrib/llvm/lib/Target/Blackfin/BlackfinISelLowering.h @@ -32,6 +32,7 @@ namespace llvm { class BlackfinTargetLowering : public TargetLowering { public: BlackfinTargetLowering(TargetMachine &TM); + virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i16; } virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const; virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; virtual void ReplaceNodeResults(SDNode *N, diff --git a/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.cpp b/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.cpp index e6511d0..743a4d7 100644 --- a/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.cpp +++ b/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.cpp @@ -435,7 +435,6 @@ SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM) setOperationAction(ISD::FDIV, MVT::v4f32, Legal); - setShiftAmountType(MVT::i32); setBooleanContents(ZeroOrNegativeOneBooleanContent); setStackPointerRegisterToSaveRestore(SPU::R1); @@ -1219,7 +1218,7 @@ SPUTargetLowering::LowerFormalArguments(SDValue Chain, FuncInfo->setVarArgsFrameIndex( MFI->CreateFixedObject(StackSlotSize, ArgOffset, true)); SDValue FIN = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT); - unsigned VReg = MF.addLiveIn(ArgRegs[ArgRegIdx], &SPU::R32CRegClass, dl); + unsigned VReg = MF.addLiveIn(ArgRegs[ArgRegIdx], &SPU::R32CRegClass); SDValue ArgVal = DAG.getRegister(VReg, MVT::v16i8); SDValue Store = DAG.getStore(Chain, dl, ArgVal, FIN, MachinePointerInfo(), false, false, 0); @@ -2190,7 +2189,7 @@ static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc, { SDValue N0 = Op.getOperand(0); // Everything has at least one operand DebugLoc dl = Op.getDebugLoc(); - EVT ShiftVT = TLI.getShiftAmountTy(); + EVT ShiftVT = TLI.getShiftAmountTy(N0.getValueType()); assert(Op.getValueType() == MVT::i8); switch (Opc) { @@ -3112,7 +3111,7 @@ SPUTargetLowering::getSingleConstraintMatchWeight( switch (*constraint) { default: weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); - break;
+ break; //FIXME: Seems like the supported constraint letters were just copied // from PPC, as the following doesn't correspond to the GCC docs. // I'm leaving it so until someone adds the corresponding lowering support. diff --git a/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.h b/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.h index 95d44af..dd48d7b 100644 --- a/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.h +++ b/contrib/llvm/lib/Target/CellSPU/SPUISelLowering.h @@ -109,6 +109,8 @@ namespace llvm { /// getSetCCResultType - Return the ValueType for ISD::SETCC virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const; + virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i32; } + //! Custom lowering hooks virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; @@ -179,9 +181,9 @@ namespace llvm { virtual bool isLegalICmpImmediate(int64_t Imm) const; - virtual bool isLegalAddressingMode(const AddrMode &AM, + virtual bool isLegalAddressingMode(const AddrMode &AM, const Type *Ty) const; - + /// After allocating this many registers, the allocator should feel /// register pressure. The value is a somewhat random guess, based on the /// number of non callee saved registers in the C calling convention. diff --git a/contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.cpp b/contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.cpp index 2f40bfc..f39826b 100644 --- a/contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.cpp +++ b/contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.cpp @@ -907,7 +907,7 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, // Transform the arguments stored on // physical registers into virtual ones - unsigned Reg = MF.addLiveIn(ArgRegEnd, RC, dl); + unsigned Reg = MF.addLiveIn(ArgRegEnd, RC); SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT); // If this is an 8 or 16-bit value, it has been passed promoted @@ -973,7 +973,7 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, for (; Start <= End; ++Start, ++StackLoc) { unsigned Reg = MBlazeRegisterInfo::getRegisterFromNumbering(Start); - unsigned LiveReg = MF.addLiveIn(Reg, RC, dl); + unsigned LiveReg = MF.addLiveIn(Reg, RC); SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, LiveReg, MVT::i32); int FI = MFI->CreateFixedObject(4, 0, true); diff --git a/contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp b/contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp index 30ef4f5..a95d59c 100644 --- a/contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp +++ b/contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.cpp @@ -77,10 +77,6 @@ MSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) : // Division is expensive setIntDivIsCheap(false); - // Even if we have only 1 bit shift here, we can perform - // shifts of the whole bitwidth 1 bit per step. - setShiftAmountType(MVT::i8); - setStackPointerRegisterToSaveRestore(MSP430::SPW); setBooleanContents(ZeroOrOneBooleanContent); setSchedulingPreference(Sched::Latency); @@ -330,7 +326,7 @@ MSP430TargetLowering::LowerCCCArguments(SDValue Chain, // Arguments passed in registers EVT RegVT = VA.getLocVT(); switch (RegVT.getSimpleVT().SimpleTy) { - default: + default: { #ifndef NDEBUG errs() << "LowerFormalArguments Unhandled argument type: " diff --git a/contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.h b/contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.h index 673c543..19c9eac 100644 --- a/contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.h +++ b/contrib/llvm/lib/Target/MSP430/MSP430ISelLowering.h @@ -73,6 +73,8 @@ namespace llvm { public: explicit MSP430TargetLowering(MSP430TargetMachine &TM); + virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i8; } + /// LowerOperation - Provide custom lowering hooks for some operations. virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; diff --git a/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 8f623b8..70d00e4 100644 --- a/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -362,7 +362,6 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM) setOperationAction(ISD::BUILD_VECTOR, MVT::v4f32, Custom); } - setShiftAmountType(MVT::i32); setBooleanContents(ZeroOrOneBooleanContent); if (TM.getSubtarget<PPCSubtarget>().isPPC64()) { @@ -1597,7 +1596,7 @@ PPCTargetLowering::LowerFormalArguments_SVR4( } // Transform the arguments stored in physical registers into virtual ones. - unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC, dl); + unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC); SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, ValVT); InVals.push_back(ArgValue); @@ -1689,7 +1688,7 @@ PPCTargetLowering::LowerFormalArguments_SVR4( // Get an existing live-in vreg, or add a new one. unsigned VReg = MF.getRegInfo().getLiveInVirtReg(GPArgRegs[GPRIndex]); if (!VReg) - VReg = MF.addLiveIn(GPArgRegs[GPRIndex], &PPC::GPRCRegClass, dl); + VReg = MF.addLiveIn(GPArgRegs[GPRIndex], &PPC::GPRCRegClass); SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT); SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, @@ -1708,7 +1707,7 @@ PPCTargetLowering::LowerFormalArguments_SVR4( // Get an existing live-in vreg, or add a new one. unsigned VReg = MF.getRegInfo().getLiveInVirtReg(FPArgRegs[FPRIndex]); if (!VReg) - VReg = MF.addLiveIn(FPArgRegs[FPRIndex], &PPC::F8RCRegClass, dl); + VReg = MF.addLiveIn(FPArgRegs[FPRIndex], &PPC::F8RCRegClass); SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::f64); SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, @@ -1872,7 +1871,7 @@ PPCTargetLowering::LowerFormalArguments_Darwin( InVals.push_back(FIN); if (ObjSize==1 || ObjSize==2) { if (GPR_idx != Num_GPR_Regs) { - unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass, dl); + unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT); SDValue Store = DAG.getTruncStore(Val.getValue(1), dl, Val, FIN, MachinePointerInfo(), @@ -1891,7 +1890,7 @@ PPCTargetLowering::LowerFormalArguments_Darwin( // to memory. ArgVal will be address of the beginning of // the object. if (GPR_idx != Num_GPR_Regs) { - unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass, dl); + unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); int FI = MFI->CreateFixedObject(PtrByteSize, ArgOffset, true); SDValue FIN = DAG.getFrameIndex(FI, PtrVT); SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT); @@ -1914,7 +1913,7 @@ PPCTargetLowering::LowerFormalArguments_Darwin( case MVT::i32: if (!isPPC64) { if (GPR_idx != Num_GPR_Regs) { - unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass, dl); + unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); ++GPR_idx; } else { @@ -1928,7 +1927,7 @@ PPCTargetLowering::LowerFormalArguments_Darwin( // FALLTHROUGH case MVT::i64: // PPC64 if (GPR_idx != Num_GPR_Regs) { - unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass, dl); + unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass); ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i64); if (ObjectVT == MVT::i32) { @@ -1966,9 +1965,9 @@ PPCTargetLowering::LowerFormalArguments_Darwin( unsigned VReg; if (ObjectVT == MVT::f32) - VReg = MF.addLiveIn(FPR[FPR_idx], &PPC::F4RCRegClass, dl); + VReg = MF.addLiveIn(FPR[FPR_idx], &PPC::F4RCRegClass); else - VReg = MF.addLiveIn(FPR[FPR_idx], &PPC::F8RCRegClass, dl); + VReg = MF.addLiveIn(FPR[FPR_idx], &PPC::F8RCRegClass); ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, ObjectVT); ++FPR_idx; @@ -1986,7 +1985,7 @@ PPCTargetLowering::LowerFormalArguments_Darwin( // Note that vector arguments in registers don't reserve stack space, // except in varargs functions. if (VR_idx != Num_VR_Regs) { - unsigned VReg = MF.addLiveIn(VR[VR_idx], &PPC::VRRCRegClass, dl); + unsigned VReg = MF.addLiveIn(VR[VR_idx], &PPC::VRRCRegClass); ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, ObjectVT); if (isVarArg) { while ((ArgOffset % 16) != 0) { @@ -2064,9 +2063,9 @@ PPCTargetLowering::LowerFormalArguments_Darwin( unsigned VReg; if (isPPC64) - VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass, dl); + VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass); else - VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass, dl); + VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT); SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, diff --git a/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.h b/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.h index 80cab75..33daae9 100644 --- a/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/contrib/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -29,36 +29,36 @@ namespace llvm { /// FSEL - Traditional three-operand fsel node. /// FSEL, - + /// FCFID - The FCFID instruction, taking an f64 operand and producing /// and f64 value containing the FP representation of the integer that /// was temporarily in the f64 operand. FCFID, - - /// FCTI[D,W]Z - The FCTIDZ and FCTIWZ instructions, taking an f32 or f64 + + /// FCTI[D,W]Z - The FCTIDZ and FCTIWZ instructions, taking an f32 or f64 /// operand, producing an f64 value containing the integer representation /// of that FP value. FCTIDZ, FCTIWZ, - + /// STFIWX - The STFIWX instruction. The first operand is an input token /// chain, then an f64 value to store, then an address to store it to. STFIWX, - + // VMADDFP, VNMSUBFP - The VMADDFP and VNMSUBFP instructions, taking // three v4f32 operands and producing a v4f32 result. VMADDFP, VNMSUBFP, - + /// VPERM - The PPC VPERM Instruction. /// VPERM, - + /// Hi/Lo - These represent the high and low 16-bit parts of a global /// address respectively. These nodes have two operands, the first of /// which must be a TargetGlobalAddress, and the second of which must be a /// Constant. Selected naively, these turn into 'lis G+C' and 'li G+C', /// though these are usually folded into other nodes. Hi, Lo, - + TOC_ENTRY, /// The following three target-specific nodes are used for calls through @@ -80,37 +80,37 @@ namespace llvm { /// This instruction is lowered in PPCRegisterInfo::eliminateFrameIndex to /// compute an allocation on the stack. DYNALLOC, - + /// GlobalBaseReg - On Darwin, this node represents the result of the mflr /// at function entry, used for PIC code. GlobalBaseReg, - + /// These nodes represent the 32-bit PPC shifts that operate on 6-bit /// shift amounts. These nodes are generated by the multi-precision shift /// code. SRL, SRA, SHL, - + /// EXTSW_32 - This is the EXTSW instruction for use with "32-bit" /// registers. EXTSW_32, /// CALL - A direct function call. CALL_Darwin, CALL_SVR4, - + /// NOP - Special NOP which follows 64-bit SVR4 calls. NOP, /// CHAIN,FLAG = MTCTR(VAL, CHAIN[, INFLAG]) - Directly corresponds to a /// MTCTR instruction. MTCTR, - + /// CHAIN,FLAG = BCTRL(CHAIN, INFLAG) - Directly corresponds to a /// BCTRL instruction. BCTRL_Darwin, BCTRL_SVR4, - + /// Return with a flag operand, matched by 'blr' RET_FLAG, - + /// R32 = MFCR(CRREG, INFLAG) - Represents the MFCRpseud/MFOCRF /// instructions. This copies the bits corresponding to the specified /// CRREG into the resultant GPR. Bits corresponding to other CR regs @@ -122,20 +122,20 @@ namespace llvm { /// encoding for the OPC field to identify the compare. For example, 838 /// is VCMPGTSH. VCMP, - + /// RESVEC, OUTFLAG = VCMPo(LHS, RHS, OPC) - Represents one of the - /// altivec VCMP*o instructions. For lack of better number, we use the + /// altivec VCMP*o instructions. For lack of better number, we use the /// opcode number encoding for the OPC field to identify the compare. For /// example, 838 is VCMPGTSH. VCMPo, - + /// CHAIN = COND_BRANCH CHAIN, CRRC, OPC, DESTBB [, INFLAG] - This /// corresponds to the COND_BRANCH pseudo instruction. CRRC is the /// condition register to branch on, OPC is the branch opcode to use (e.g. /// PPC::BLE), DESTBB is the destination block to branch to, and INFLAG is /// an optional input flag argument. COND_BRANCH, - + // The following 5 instructions are used only as part of the // long double-to-int conversion sequence. @@ -150,7 +150,7 @@ namespace llvm { MTFSB1, /// F8RC, OUTFLAG = FADDRTZ F8RC, F8RC, INFLAG - This is an FADD done with - /// rounding towards zero. It has flags added so it won't move past the + /// rounding towards zero. It has flags added so it won't move past the /// FPSCR-setting instructions. FADDRTZ, @@ -174,14 +174,14 @@ namespace llvm { /// STD_32 - This is the STD instruction for use with "32-bit" registers. STD_32 = ISD::FIRST_TARGET_MEMORY_OPCODE, - - /// CHAIN = STBRX CHAIN, GPRC, Ptr, Type - This is a + + /// CHAIN = STBRX CHAIN, GPRC, Ptr, Type - This is a /// byte-swapping store instruction. It byte-swaps the low "Type" bits of /// the GPRC input, then stores it through Ptr. Type can be either i16 or /// i32. - STBRX, - - /// GPRC, CHAIN = LBRX CHAIN, Ptr, Type - This is a + STBRX, + + /// GPRC, CHAIN = LBRX CHAIN, Ptr, Type - This is a /// byte-swapping load instruction. It loads "Type" bits, byte swaps it, /// then puts it in the bottom bits of the GPRC. TYPE can be either i16 /// or i32. @@ -194,7 +194,7 @@ namespace llvm { /// isVPKUHUMShuffleMask - Return true if this is the shuffle mask for a /// VPKUHUM instruction. bool isVPKUHUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary); - + /// isVPKUWUMShuffleMask - Return true if this is the shuffle mask for a /// VPKUWUM instruction. bool isVPKUWUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary); @@ -208,16 +208,16 @@ namespace llvm { /// a VRGH* instruction with the specified unit size (1,2 or 4 bytes). bool isVMRGHShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, bool isUnary); - + /// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift /// amount, otherwise return -1. int isVSLDOIShuffleMask(SDNode *N, bool isUnary); - + /// isSplatShuffleMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a splat of a single element that is suitable for input to /// VSPLTB/VSPLTH/VSPLTW. bool isSplatShuffleMask(ShuffleVectorSDNode *N, unsigned EltSize); - + /// isAllNegativeZeroVector - Returns true if all elements of build_vector /// are -0.0. bool isAllNegativeZeroVector(SDNode *N); @@ -225,24 +225,26 @@ namespace llvm { /// getVSPLTImmediate - Return the appropriate VSPLT* immediate to splat the /// specified isSplatShuffleMask VECTOR_SHUFFLE mask. unsigned getVSPLTImmediate(SDNode *N, unsigned EltSize); - + /// get_VSPLTI_elt - If this is a build_vector of constants which can be /// formed by using a vspltis[bhw] instruction of the specified element /// size, return the constant being splatted. The ByteSize field indicates /// the number of bytes of each element [124] -> [bhw]. SDValue get_VSPLTI_elt(SDNode *N, unsigned ByteSize, SelectionDAG &DAG); } - + class PPCTargetLowering : public TargetLowering { const PPCSubtarget &PPCSubTarget; public: explicit PPCTargetLowering(PPCTargetMachine &TM); - + /// getTargetNodeName() - This method returns the name of a target specific /// DAG node. virtual const char *getTargetNodeName(unsigned Opcode) const; + virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i32; } + /// getSetCCResultType - Return the ISD::SETCC ValueType virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const; @@ -253,19 +255,19 @@ namespace llvm { SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const; - + /// SelectAddressRegReg - Given the specified addressed, check to see if it /// can be represented as an indexed [r+r] operation. Returns false if it /// can be more efficiently represented with [r+imm]. bool SelectAddressRegReg(SDValue N, SDValue &Base, SDValue &Index, SelectionDAG &DAG) const; - + /// SelectAddressRegImm - Returns true if the address N can be represented /// by a base register plus a signed 16-bit displacement [r+imm], and if it /// is not better represented as reg+reg. bool SelectAddressRegImm(SDValue N, SDValue &Disp, SDValue &Base, SelectionDAG &DAG) const; - + /// SelectAddressRegRegOnly - Given the specified addressed, force it to be /// represented as an indexed [r+r] operation. bool SelectAddressRegRegOnly(SDValue N, SDValue &Base, SDValue &Index, @@ -277,7 +279,7 @@ namespace llvm { bool SelectAddressRegImmShift(SDValue N, SDValue &Disp, SDValue &Base, SelectionDAG &DAG) const; - + /// LowerOperation - Provide custom lowering hooks for some operations. /// virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; @@ -289,10 +291,10 @@ namespace llvm { SelectionDAG &DAG) const; virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; - + virtual void computeMaskedBitsForTargetNode(const SDValue Op, const APInt &Mask, - APInt &KnownZero, + APInt &KnownZero, APInt &KnownOne, const SelectionDAG &DAG, unsigned Depth = 0) const; @@ -300,13 +302,13 @@ namespace llvm { virtual MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const; - MachineBasicBlock *EmitAtomicBinary(MachineInstr *MI, + MachineBasicBlock *EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *MBB, bool is64Bit, unsigned BinOpcode) const; - MachineBasicBlock *EmitPartwordAtomicBinary(MachineInstr *MI, - MachineBasicBlock *MBB, + MachineBasicBlock *EmitPartwordAtomicBinary(MachineInstr *MI, + MachineBasicBlock *MBB, bool is8bit, unsigned Opcode) const; - + ConstraintType getConstraintType(const std::string &Constraint) const; /// Examine constraint string and operand type and determine a weight value. @@ -314,7 +316,7 @@ namespace llvm { ConstraintWeight getSingleConstraintMatchWeight( AsmOperandInfo &info, const char *constraint) const; - std::pair<unsigned, const TargetRegisterClass*> + std::pair<unsigned, const TargetRegisterClass*> getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; @@ -329,11 +331,11 @@ namespace llvm { char ConstraintLetter, std::vector<SDValue> &Ops, SelectionDAG &DAG) const; - + /// isLegalAddressingMode - Return true if the addressing mode represented /// by AM is legal for this target, for a load/store of the specified type. virtual bool isLegalAddressingMode(const AddrMode &AM, const Type *Ty)const; - + /// isLegalAddressImmediate - Return true if the integer value can be used /// as the offset of the target addressing mode for load / store of the /// given type. @@ -344,7 +346,7 @@ namespace llvm { virtual bool isLegalAddressImmediate(GlobalValue *GV) const; virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; - + /// getOptimalMemOpType - Returns the target specific optimal type for load /// and store operations as a result of memset, memcpy, and memmove /// lowering. If DstAlign is zero that means it's safe to destination diff --git a/contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp b/contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp index ee29275..4b12852 100644 --- a/contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp +++ b/contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp @@ -79,6 +79,7 @@ namespace { MachineBasicBlock::iterator findDelayInstr(MachineBasicBlock &MBB, MachineBasicBlock::iterator slot); + bool needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize); }; char Filler::ID = 0; @@ -91,6 +92,7 @@ FunctionPass *llvm::createSparcDelaySlotFillerPass(TargetMachine &tm) { return new Filler(tm); } + /// runOnMachineBasicBlock - Fill in delay slots for the given basic block. /// We assume there is only one delay slot per delayed instruction. /// @@ -112,6 +114,13 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { BuildMI(MBB, ++J, I->getDebugLoc(), TII->get(SP::NOP)); else MBB.splice(++J, &MBB, D); + unsigned structSize = 0; + if (needsUnimp(I, structSize)) { + MachineBasicBlock::iterator J = I; + ++J; //skip the delay filler. + BuildMI(MBB, ++J, I->getDebugLoc(), + TII->get(SP::UNIMP)).addImm(structSize); + } } return Changed; } @@ -287,6 +296,28 @@ bool Filler::isDelayFiller(MachineBasicBlock &MBB, { if (candidate == MBB.begin()) return false; + if (candidate->getOpcode() == SP::UNIMP) + return true; const TargetInstrDesc &prevdesc = (--candidate)->getDesc(); return prevdesc.hasDelaySlot(); } + +bool Filler::needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize) +{ + if (!I->getDesc().isCall()) + return false; + + unsigned structSizeOpNum = 0; + switch (I->getOpcode()) { + default: llvm_unreachable("Unknown call opcode."); + case SP::CALL: structSizeOpNum = 1; break; + case SP::JMPLrr: + case SP::JMPLri: structSizeOpNum = 2; break; + } + + const MachineOperand &MO = I->getOperand(structSizeOpNum); + if (!MO.isImm()) + return false; + StructSize = MO.getImm(); + return true; +} diff --git a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp index 196b87d..70574c3 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -16,7 +16,9 @@ #include "SparcISelLowering.h" #include "SparcTargetMachine.h" #include "SparcMachineFunctionInfo.h" +#include "llvm/DerivedTypes.h" #include "llvm/Function.h" +#include "llvm/Module.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -116,6 +118,8 @@ SparcTargetLowering::LowerReturn(SDValue Chain, // Guarantee that all emitted copies are stuck together with flags. Flag = Chain.getValue(1); } + + unsigned RetAddrOffset = 8; //Call Inst + Delay Slot // If the function returns a struct, copy the SRetReturnReg to I0 if (MF.getFunction()->hasStructRetAttr()) { SparcMachineFunctionInfo *SFI = MF.getInfo<SparcMachineFunctionInfo>(); @@ -127,11 +131,16 @@ SparcTargetLowering::LowerReturn(SDValue Chain, Flag = Chain.getValue(1); if (MF.getRegInfo().liveout_empty()) MF.getRegInfo().addLiveOut(SP::I0); + RetAddrOffset = 12; // CallInst + Delay Slot + Unimp } + SDValue RetAddrOffsetNode = DAG.getConstant(RetAddrOffset, MVT::i32); + if (Flag.getNode()) - return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain, Flag); - return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain); + return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain, + RetAddrOffsetNode, Flag); + return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain, + RetAddrOffsetNode); } /// LowerFormalArguments - V8 uses a very simple ABI, where all values are @@ -194,7 +203,7 @@ SparcTargetLowering::LowerFormalArguments(SDValue Chain, false, false, 0); } else { unsigned loReg = MF.addLiveIn(NextVA.getLocReg(), - &SP::IntRegsRegClass, dl); + &SP::IntRegsRegClass); LoVal = DAG.getCopyFromReg(Chain, dl, loReg, MVT::i32); } SDValue WholeValue = @@ -393,6 +402,7 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee, SmallVector<SDValue, 8> MemOpChains; const unsigned StackOffset = 92; + bool hasStructRetAttr = false; // Walk the register/memloc assignments, inserting copies/loads. for (unsigned i = 0, realArgIdx = 0, byvalArgIdx = 0, e = ArgLocs.size(); i != e; @@ -433,6 +443,7 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee, MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo(), false, false, 0)); + hasStructRetAttr = true; continue; } @@ -546,6 +557,8 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee, InFlag = Chain.getValue(1); } + unsigned SRetArgSize = (hasStructRetAttr)? getSRetArgSize(DAG, Callee):0; + // If the callee is a GlobalAddress node (quite common, every direct call is) // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. // Likewise ExternalSymbol -> TargetExternalSymbol. @@ -559,6 +572,8 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee, SmallVector<SDValue, 8> Ops; Ops.push_back(Chain); Ops.push_back(Callee); + if (hasStructRetAttr) + Ops.push_back(DAG.getTargetConstant(SRetArgSize, MVT::i32)); for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { unsigned Reg = RegsToPass[i].first; if (Reg >= SP::I0 && Reg <= SP::I7) @@ -600,7 +615,29 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee, return Chain; } +unsigned +SparcTargetLowering::getSRetArgSize(SelectionDAG &DAG, SDValue Callee) const +{ + const Function *CalleeFn = 0; + if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { + CalleeFn = dyn_cast<Function>(G->getGlobal()); + } else if (ExternalSymbolSDNode *E = + dyn_cast<ExternalSymbolSDNode>(Callee)) { + const Function *Fn = DAG.getMachineFunction().getFunction(); + const Module *M = Fn->getParent(); + CalleeFn = M->getFunction(E->getSymbol()); + } + + if (!CalleeFn) + return 0; + assert(CalleeFn->hasStructRetAttr() && + "Callee does not have the StructRet attribute."); + + const PointerType *Ty = cast<PointerType>(CalleeFn->arg_begin()->getType()); + const Type *ElementTy = Ty->getElementType(); + return getTargetData()->getTypeAllocSize(ElementTy); +} //===----------------------------------------------------------------------===// // TargetLowering Implementation diff --git a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.h b/contrib/llvm/lib/Target/Sparc/SparcISelLowering.h index 849e401..7d02df8 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.h +++ b/contrib/llvm/lib/Target/Sparc/SparcISelLowering.h @@ -101,6 +101,8 @@ namespace llvm { SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const; + + unsigned getSRetArgSize(SelectionDAG &DAG, SDValue Callee) const; }; } // end namespace llvm diff --git a/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td b/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td index 1072323..cf5c48f 100644 --- a/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td +++ b/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td @@ -124,7 +124,8 @@ def call : SDNode<"SPISD::CALL", SDT_SPCall, [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, SDNPVariadic]>; -def retflag : SDNode<"SPISD::RET_FLAG", SDTNone, +def SDT_SPRet : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; +def retflag : SDNode<"SPISD::RET_FLAG", SDT_SPRet, [SDNPHasChain, SDNPOptInGlue]>; def flushw : SDNode<"SPISD::FLUSHW", SDTNone, @@ -132,7 +133,7 @@ def flushw : SDNode<"SPISD::FLUSHW", SDTNone, def getPCX : Operand<i32> { let PrintMethod = "printGetPCX"; -} +} //===----------------------------------------------------------------------===// // SPARC Flag Conditions @@ -232,6 +233,9 @@ let hasSideEffects = 1, mayStore = 1 in { [(flushw)]>; } +def UNIMP : F2_1<0b000, (outs), (ins i32imm:$val), + "unimp $val", []>; + // FpMOVD/FpNEGD/FpABSD - These are lowered to single-precision ops by the // fpmover pass. let Predicates = [HasNoV9] in { // Only emit these in V8 mode. @@ -292,11 +296,13 @@ let usesCustomInserter = 1, Uses = [FCC] in { // Section A.3 - Synthetic Instructions, p. 85 // special cases of JMPL: let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1 in { - let rd = O7.Num, rs1 = G0.Num, simm13 = 8 in - def RETL: F3_2<2, 0b111000, (outs), (ins), "retl", [(retflag)]>; + let rd = O7.Num, rs1 = G0.Num in + def RETL: F3_2<2, 0b111000, (outs), (ins i32imm:$val), + "jmp %o7+$val", [(retflag simm13:$val)]>; - let rd = I7.Num, rs1 = G0.Num, simm13 = 8 in - def RET: F3_2<2, 0b111000, (outs), (ins), "ret", []>; + let rd = I7.Num, rs1 = G0.Num in + def RET: F3_2<2, 0b111000, (outs), (ins i32imm:$val), + "jmp %i7+$val", []>; } // Section B.1 - Load Integer Instructions, p. 90 diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index d694f2e..90939c3 100644 --- a/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -59,9 +59,6 @@ SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) : // Compute derived properties from the register classes computeRegisterProperties(); - // Set shifts properties - setShiftAmountType(MVT::i64); - // Provide all sorts of operation actions setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.h index 51d2df3..3019242 100644 --- a/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.h +++ b/contrib/llvm/lib/Target/SystemZ/SystemZISelLowering.h @@ -57,6 +57,8 @@ namespace llvm { public: explicit SystemZTargetLowering(SystemZTargetMachine &TM); + virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i64; } + /// LowerOperation - Provide custom lowering hooks for some operations. virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; diff --git a/contrib/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/contrib/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp index 1cac07a..8fe549b 100644 --- a/contrib/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/contrib/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -775,6 +775,19 @@ ParseInstruction(StringRef Name, SMLoc NameLoc, delete &Op; } } + // Same hack for "in[bwl]? (%dx), %al" -> "inb %dx, %al". + if ((Name == "inb" || Name == "inw" || Name == "inl" || Name == "in") && + Operands.size() == 3) { + X86Operand &Op = *(X86Operand*)Operands.begin()[1]; + if (Op.isMem() && Op.Mem.SegReg == 0 && + isa<MCConstantExpr>(Op.Mem.Disp) && + cast<MCConstantExpr>(Op.Mem.Disp)->getValue() == 0 && + Op.Mem.BaseReg == MatchRegisterName("dx") && Op.Mem.IndexReg == 0) { + SMLoc Loc = Op.getEndLoc(); + Operands.begin()[1] = X86Operand::CreateReg(Op.Mem.BaseReg, Loc, Loc); + delete &Op; + } + } // FIXME: Hack to handle recognize s{hr,ar,hl} $1, <op>. Canonicalize to // "shift <op>". diff --git a/contrib/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp b/contrib/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp index 691e2d7..f777756 100644 --- a/contrib/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp +++ b/contrib/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp @@ -168,16 +168,16 @@ static void translateImmediate(MCInst &mcInst, uint64_t immediate, switch (insn.displacementSize) { default: break; - case 8: + case 1: type = TYPE_MOFFS8; break; - case 16: + case 2: type = TYPE_MOFFS16; break; - case 32: + case 4: type = TYPE_MOFFS32; break; - case 64: + case 8: type = TYPE_MOFFS64; break; } diff --git a/contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h b/contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h index 4f4fbcd..d0dc8b5 100644 --- a/contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h +++ b/contrib/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h @@ -399,7 +399,7 @@ struct InternalInstruction { /* The segment override type */ SegmentOverride segmentOverride; - /* Sizes of various critical pieces of data */ + /* Sizes of various critical pieces of data, in bytes */ uint8_t registerSize; uint8_t addressSize; uint8_t displacementSize; diff --git a/contrib/llvm/lib/Target/X86/X86FastISel.cpp b/contrib/llvm/lib/Target/X86/X86FastISel.cpp index 9d42ac2..6fa9284 100644 --- a/contrib/llvm/lib/Target/X86/X86FastISel.cpp +++ b/contrib/llvm/lib/Target/X86/X86FastISel.cpp @@ -597,9 +597,13 @@ bool X86FastISel::X86SelectCallAddress(const Value *V, X86AddressMode &AM) { (AM.Base.Reg != 0 || AM.IndexReg != 0)) return false; - // Can't handle TLS or DLLImport. + // Can't handle DLLImport. + if (GV->hasDLLImportLinkage()) + return false; + + // Can't handle TLS. if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) - if (GVar->isThreadLocal() || GVar->hasDLLImportLinkage()) + if (GVar->isThreadLocal()) return false; // Okay, we've committed to selecting this global. Set up the basic address. diff --git a/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp b/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp index 27024b4..2f49dbc 100644 --- a/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -45,7 +45,6 @@ #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/VectorExtras.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" @@ -56,10 +55,6 @@ using namespace dwarf; STATISTIC(NumTailCalls, "Number of tail calls"); -static cl::opt<bool> -Disable256Bit("disable-256bit", cl::Hidden, - cl::desc("Disable use of 256-bit vectors")); - // Forward declarations. static SDValue getMOVL(SelectionDAG &DAG, DebugLoc dl, EVT VT, SDValue V1, SDValue V2); @@ -225,7 +220,6 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) static MVT IntVTs[] = { MVT::i8, MVT::i16, MVT::i32, MVT::i64 }; // X86 is weird, it always uses i8 for shift amounts and setcc results. - setShiftAmountType(MVT::i8); setBooleanContents(ZeroOrOneBooleanContent); setSchedulingPreference(Sched::RegPressure); setStackPointerRegisterToSaveRestore(X86StackPtr); @@ -1713,7 +1707,7 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain, else llvm_unreachable("Unknown argument type!"); - unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC, dl); + unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC); ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT); // If this is an 8 or 16-bit value, it is really passed promoted to 32 @@ -1845,7 +1839,7 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain, SDValue FIN = DAG.getNode(ISD::ADD, dl, getPointerTy(), RSFIN, DAG.getIntPtrConstant(Offset)); unsigned VReg = MF.addLiveIn(GPR64ArgRegs[NumIntRegs], - X86::GR64RegisterClass, dl); + X86::GR64RegisterClass); SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i64); SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, @@ -1861,7 +1855,7 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain, SmallVector<SDValue, 11> SaveXMMOps; SaveXMMOps.push_back(Chain); - unsigned AL = MF.addLiveIn(X86::AL, X86::GR8RegisterClass, dl); + unsigned AL = MF.addLiveIn(X86::AL, X86::GR8RegisterClass); SDValue ALVal = DAG.getCopyFromReg(DAG.getEntryNode(), dl, AL, MVT::i8); SaveXMMOps.push_back(ALVal); @@ -1872,7 +1866,7 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain, for (; NumXMMRegs != TotalNumXMMRegs; ++NumXMMRegs) { unsigned VReg = MF.addLiveIn(XMMArgRegs64Bit[NumXMMRegs], - X86::VR128RegisterClass, dl); + X86::VR128RegisterClass); SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::v4f32); SaveXMMOps.push_back(Val); } @@ -2693,6 +2687,10 @@ static bool isTargetShuffle(unsigned Opcode) { case X86ISD::MOVSD: case X86ISD::UNPCKLPS: case X86ISD::UNPCKLPD: + case X86ISD::VUNPCKLPS: + case X86ISD::VUNPCKLPD: + case X86ISD::VUNPCKLPSY: + case X86ISD::VUNPCKLPDY: case X86ISD::PUNPCKLWD: case X86ISD::PUNPCKLBW: case X86ISD::PUNPCKLDQ: @@ -2760,6 +2758,10 @@ static SDValue getTargetShuffleNode(unsigned Opc, DebugLoc dl, EVT VT, case X86ISD::MOVSD: case X86ISD::UNPCKLPS: case X86ISD::UNPCKLPD: + case X86ISD::VUNPCKLPS: + case X86ISD::VUNPCKLPD: + case X86ISD::VUNPCKLPSY: + case X86ISD::VUNPCKLPDY: case X86ISD::PUNPCKLWD: case X86ISD::PUNPCKLBW: case X86ISD::PUNPCKLDQ: @@ -4178,7 +4180,8 @@ static SDValue getVShift(bool isLeft, EVT VT, SDValue SrcOp, SrcOp = DAG.getNode(ISD::BITCAST, dl, ShVT, SrcOp); return DAG.getNode(ISD::BITCAST, dl, VT, DAG.getNode(Opc, dl, ShVT, SrcOp, - DAG.getConstant(NumBits, TLI.getShiftAmountTy()))); + DAG.getConstant(NumBits, + TLI.getShiftAmountTy(SrcOp.getValueType())))); } SDValue @@ -4327,16 +4330,15 @@ X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const { // For AVX-length vectors, build the individual 128-bit pieces and // use shuffles to put them in place. - if (VT.getSizeInBits() > 256 && - Subtarget->hasAVX() && - !Disable256Bit && + if (VT.getSizeInBits() > 256 && + Subtarget->hasAVX() && !ISD::isBuildVectorAllZeros(Op.getNode())) { SmallVector<SDValue, 8> V; V.resize(NumElems); for (unsigned i = 0; i < NumElems; ++i) { V[i] = Op.getOperand(i); } - + EVT HVT = EVT::getVectorVT(*DAG.getContext(), ExtVT, NumElems/2); // Build the lower subvector. @@ -5044,7 +5046,8 @@ SDValue LowerVECTOR_SHUFFLEv16i8(ShuffleVectorSDNode *SVOp, DAG.getIntPtrConstant(Elt1 / 2)); if ((Elt1 & 1) == 0) InsElt = DAG.getNode(ISD::SHL, dl, MVT::i16, InsElt, - DAG.getConstant(8, TLI.getShiftAmountTy())); + DAG.getConstant(8, + TLI.getShiftAmountTy(InsElt.getValueType()))); else if (Elt0 >= 0) InsElt = DAG.getNode(ISD::AND, dl, MVT::i16, InsElt, DAG.getConstant(0xFF00, MVT::i16)); @@ -5058,7 +5061,8 @@ SDValue LowerVECTOR_SHUFFLEv16i8(ShuffleVectorSDNode *SVOp, Elt0Src, DAG.getIntPtrConstant(Elt0 / 2)); if ((Elt0 & 1) != 0) InsElt0 = DAG.getNode(ISD::SRL, dl, MVT::i16, InsElt0, - DAG.getConstant(8, TLI.getShiftAmountTy())); + DAG.getConstant(8, + TLI.getShiftAmountTy(InsElt0.getValueType()))); else if (Elt1 >= 0) InsElt0 = DAG.getNode(ISD::AND, dl, MVT::i16, InsElt0, DAG.getConstant(0x00FF, MVT::i16)); @@ -5475,7 +5479,7 @@ SDValue getMOVLP(SDValue &Op, DebugLoc &dl, SelectionDAG &DAG, bool HasSSE2) { // Both of them can't be memory operations though. if (MayFoldVectorLoad(V1) && MayFoldVectorLoad(V2)) CanFoldLoad = false; - + if (CanFoldLoad) { if (HasSSE2 && NumElems == 2) return getTargetShuffleNode(X86ISD::MOVLPD, dl, VT, V1, V2, DAG); @@ -6088,7 +6092,7 @@ X86TargetLowering::LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const { SDValue ScaledN2 = N2; if (Upper) ScaledN2 = DAG.getNode(ISD::SUB, dl, N2.getValueType(), N2, - DAG.getConstant(NumElems / + DAG.getConstant(NumElems / (VT.getSizeInBits() / 128), N2.getValueType())); Op = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, SubN0.getValueType(), SubN0, @@ -9327,6 +9331,10 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { case X86ISD::MOVSS: return "X86ISD::MOVSS"; case X86ISD::UNPCKLPS: return "X86ISD::UNPCKLPS"; case X86ISD::UNPCKLPD: return "X86ISD::UNPCKLPD"; + case X86ISD::VUNPCKLPS: return "X86ISD::VUNPCKLPS"; + case X86ISD::VUNPCKLPD: return "X86ISD::VUNPCKLPD"; + case X86ISD::VUNPCKLPSY: return "X86ISD::VUNPCKLPSY"; + case X86ISD::VUNPCKLPDY: return "X86ISD::VUNPCKLPDY"; case X86ISD::UNPCKHPS: return "X86ISD::UNPCKHPS"; case X86ISD::UNPCKHPD: return "X86ISD::UNPCKHPD"; case X86ISD::PUNPCKLBW: return "X86ISD::PUNPCKLBW"; @@ -11984,6 +11992,10 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N, case X86ISD::PUNPCKLQDQ: case X86ISD::UNPCKLPS: case X86ISD::UNPCKLPD: + case X86ISD::VUNPCKLPS: + case X86ISD::VUNPCKLPD: + case X86ISD::VUNPCKLPSY: + case X86ISD::VUNPCKLPDY: case X86ISD::MOVHLPS: case X86ISD::MOVLHPS: case X86ISD::PSHUFD: diff --git a/contrib/llvm/lib/Target/X86/X86ISelLowering.h b/contrib/llvm/lib/Target/X86/X86ISelLowering.h index 419da37..6ec4a7d 100644 --- a/contrib/llvm/lib/Target/X86/X86ISelLowering.h +++ b/contrib/llvm/lib/Target/X86/X86ISelLowering.h @@ -159,16 +159,16 @@ namespace llvm { /// PSHUFB - Shuffle 16 8-bit values within a vector. PSHUFB, - + /// PANDN - and with not'd value. PANDN, - + /// PSIGNB/W/D - Copy integer sign. - PSIGNB, PSIGNW, PSIGND, - + PSIGNB, PSIGNW, PSIGND, + /// PBLENDVB - Variable blend PBLENDVB, - + /// FMAX, FMIN - Floating point max and min. /// FMAX, FMIN, @@ -212,7 +212,7 @@ namespace llvm { // ADD, SUB, SMUL, etc. - Arithmetic operations with FLAGS results. ADD, SUB, ADC, SBB, SMUL, INC, DEC, OR, XOR, AND, - + UMUL, // LOW, HI, FLAGS = umul LHS, RHS // MUL_IMM - X86 specific multiply by immediate. @@ -248,6 +248,10 @@ namespace llvm { MOVSS, UNPCKLPS, UNPCKLPD, + VUNPCKLPS, + VUNPCKLPD, + VUNPCKLPSY, + VUNPCKLPDY, UNPCKHPS, UNPCKHPD, PUNPCKLBW, @@ -463,6 +467,8 @@ namespace llvm { virtual unsigned getJumpTableEncoding() const; + virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i8; } + virtual const MCExpr * LowerCustomJumpTableEntry(const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, unsigned uid, diff --git a/contrib/llvm/lib/Target/X86/X86InstrFormats.td b/contrib/llvm/lib/Target/X86/X86InstrFormats.td index 344c14c..0660072 100644 --- a/contrib/llvm/lib/Target/X86/X86InstrFormats.td +++ b/contrib/llvm/lib/Target/X86/X86InstrFormats.td @@ -41,6 +41,8 @@ def MRM_F8 : Format<41>; def MRM_F9 : Format<42>; def RawFrmImm8 : Format<43>; def RawFrmImm16 : Format<44>; +def MRM_D0 : Format<45>; +def MRM_D1 : Format<46>; // ImmType - This specifies the immediate type used by an instruction. This is // part of the ad-hoc solution used to emit machine instruction encodings by our diff --git a/contrib/llvm/lib/Target/X86/X86InstrInfo.cpp b/contrib/llvm/lib/Target/X86/X86InstrInfo.cpp index ceb1b65..76a9b12 100644 --- a/contrib/llvm/lib/Target/X86/X86InstrInfo.cpp +++ b/contrib/llvm/lib/Target/X86/X86InstrInfo.cpp @@ -369,8 +369,6 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm) { X86::IMUL32rri8, X86::IMUL32rmi8, 0 }, { X86::IMUL64rri32, X86::IMUL64rmi32, 0 }, { X86::IMUL64rri8, X86::IMUL64rmi8, 0 }, - { X86::Int_CMPSDrr, X86::Int_CMPSDrm, 0 }, - { X86::Int_CMPSSrr, X86::Int_CMPSSrm, 0 }, { X86::Int_COMISDrr, X86::Int_COMISDrm, 0 }, { X86::Int_COMISSrr, X86::Int_COMISSrm, 0 }, { X86::Int_CVTDQ2PDrr, X86::Int_CVTDQ2PDrm, 16 }, @@ -568,6 +566,8 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm) { X86::IMUL16rr, X86::IMUL16rm, 0 }, { X86::IMUL32rr, X86::IMUL32rm, 0 }, { X86::IMUL64rr, X86::IMUL64rm, 0 }, + { X86::Int_CMPSDrr, X86::Int_CMPSDrm, 0 }, + { X86::Int_CMPSSrr, X86::Int_CMPSSrm, 0 }, { X86::MAXPDrr, X86::MAXPDrm, 16 }, { X86::MAXPDrr_Int, X86::MAXPDrm_Int, 16 }, { X86::MAXPSrr, X86::MAXPSrm, 16 }, diff --git a/contrib/llvm/lib/Target/X86/X86InstrInfo.h b/contrib/llvm/lib/Target/X86/X86InstrInfo.h index 1d44207..fcb5a25 100644 --- a/contrib/llvm/lib/Target/X86/X86InstrInfo.h +++ b/contrib/llvm/lib/Target/X86/X86InstrInfo.h @@ -311,6 +311,8 @@ namespace X86II { MRM_F0 = 40, MRM_F8 = 41, MRM_F9 = 42, + MRM_D0 = 45, + MRM_D1 = 46, /// RawFrmImm8 - This is used for the ENTER instruction, which has two /// immediates, the first of which is a 16-bit immediate (specified by @@ -577,6 +579,8 @@ namespace X86II { case X86II::MRM_F0: case X86II::MRM_F8: case X86II::MRM_F9: + case X86II::MRM_D0: + case X86II::MRM_D1: return -1; } } diff --git a/contrib/llvm/lib/Target/X86/X86InstrInfo.td b/contrib/llvm/lib/Target/X86/X86InstrInfo.td index 87dc4be..f832a7c 100644 --- a/contrib/llvm/lib/Target/X86/X86InstrInfo.td +++ b/contrib/llvm/lib/Target/X86/X86InstrInfo.td @@ -1296,6 +1296,9 @@ def : MnemonicAlias<"lret", "lretl">; def : MnemonicAlias<"leavel", "leave">, Requires<[In32BitMode]>; def : MnemonicAlias<"leaveq", "leave">, Requires<[In64BitMode]>; +def : MnemonicAlias<"loopz", "loope">; +def : MnemonicAlias<"loopnz", "loopne">; + def : MnemonicAlias<"pop", "popl">, Requires<[In32BitMode]>; def : MnemonicAlias<"pop", "popq">, Requires<[In64BitMode]>; def : MnemonicAlias<"popf", "popfl">, Requires<[In32BitMode]>; diff --git a/contrib/llvm/lib/Target/X86/X86InstrSystem.td b/contrib/llvm/lib/Target/X86/X86InstrSystem.td index 1a58ba0..6a24d14 100644 --- a/contrib/llvm/lib/Target/X86/X86InstrSystem.td +++ b/contrib/llvm/lib/Target/X86/X86InstrSystem.td @@ -388,3 +388,8 @@ def CPUID : I<0xA2, RawFrm, (outs), (ins), "cpuid", []>, TB; def INVD : I<0x08, RawFrm, (outs), (ins), "invd", []>, TB; def WBINVD : I<0x09, RawFrm, (outs), (ins), "wbinvd", []>, TB; +let Defs = [RDX, RAX], Uses = [RCX] in + def XGETBV : I<0x01, MRM_D0, (outs), (ins), "xgetbv", []>, TB; + +let Uses = [RDX, RAX, RCX] in + def XSETBV : I<0x01, MRM_D1, (outs), (ins), "xsetbv", []>, TB; diff --git a/contrib/llvm/lib/Target/X86/X86MCCodeEmitter.cpp b/contrib/llvm/lib/Target/X86/X86MCCodeEmitter.cpp index e6dc74e..0e3b571 100644 --- a/contrib/llvm/lib/Target/X86/X86MCCodeEmitter.cpp +++ b/contrib/llvm/lib/Target/X86/X86MCCodeEmitter.cpp @@ -979,6 +979,14 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, EmitByte(BaseOpcode, CurByte, OS); EmitByte(0xF9, CurByte, OS); break; + case X86II::MRM_D0: + EmitByte(BaseOpcode, CurByte, OS); + EmitByte(0xD0, CurByte, OS); + break; + case X86II::MRM_D1: + EmitByte(BaseOpcode, CurByte, OS); + EmitByte(0xD1, CurByte, OS); + break; } // If there is a remaining operand, it must be a trailing immediate. Emit it diff --git a/contrib/llvm/lib/Target/X86/X86Subtarget.cpp b/contrib/llvm/lib/Target/X86/X86Subtarget.cpp index de76856..1ee7312 100644 --- a/contrib/llvm/lib/Target/X86/X86Subtarget.cpp +++ b/contrib/llvm/lib/Target/X86/X86Subtarget.cpp @@ -342,9 +342,10 @@ X86Subtarget::X86Subtarget(const std::string &TT, const std::string &FS, assert((!Is64Bit || HasX86_64) && "64-bit code requested on a subtarget that doesn't support it!"); - // Stack alignment is 16 bytes on Darwin and Linux (both 32 and 64 bit) and - // for all 64-bit targets. - if (isTargetDarwin() || isTargetLinux() || Is64Bit) + // Stack alignment is 16 bytes on Darwin, FreeBSD, Linux and Solaris (both + // 32 and 64 bit) and for all 64-bit targets. + if (isTargetDarwin() || isTargetFreeBSD() || isTargetLinux() || + isTargetSolaris() || Is64Bit) stackAlignment = 16; if (StackAlignment) diff --git a/contrib/llvm/lib/Target/X86/X86Subtarget.h b/contrib/llvm/lib/Target/X86/X86Subtarget.h index 8a119b4..0a62a02 100644 --- a/contrib/llvm/lib/Target/X86/X86Subtarget.h +++ b/contrib/llvm/lib/Target/X86/X86Subtarget.h @@ -166,6 +166,8 @@ public: bool hasVectorUAMem() const { return HasVectorUAMem; } bool isTargetDarwin() const { return TargetTriple.getOS() == Triple::Darwin; } + bool isTargetFreeBSD() const { return TargetTriple.getOS() == Triple::FreeBSD; } + bool isTargetSolaris() const { return TargetTriple.getOS() == Triple::Solaris; } // ELF is a reasonably sane default and the only other X86 targets we // support are Darwin and Windows. Just use "not those". diff --git a/contrib/llvm/lib/Target/XCore/XCoreISelLowering.cpp b/contrib/llvm/lib/Target/XCore/XCoreISelLowering.cpp index 828d6f9..4817787 100644 --- a/contrib/llvm/lib/Target/XCore/XCoreISelLowering.cpp +++ b/contrib/llvm/lib/Target/XCore/XCoreISelLowering.cpp @@ -42,9 +42,9 @@ using namespace llvm; const char *XCoreTargetLowering:: -getTargetNodeName(unsigned Opcode) const +getTargetNodeName(unsigned Opcode) const { - switch (Opcode) + switch (Opcode) { case XCoreISD::BL : return "XCoreISD::BL"; case XCoreISD::PCRelativeWrapper : return "XCoreISD::PCRelativeWrapper"; @@ -77,7 +77,6 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM) // Division is expensive setIntDivIsCheap(false); - setShiftAmountType(MVT::i32); setStackPointerRegisterToSaveRestore(XCore::SP); setSchedulingPreference(Sched::RegPressure); @@ -95,7 +94,7 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM) // Stop the combiner recombining select and set_cc setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); - + // 64bit setOperationAction(ISD::ADD, MVT::i64, Custom); setOperationAction(ISD::SUB, MVT::i64, Custom); @@ -106,14 +105,14 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM) setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); - + // Bit Manipulation setOperationAction(ISD::CTPOP, MVT::i32, Expand); setOperationAction(ISD::ROTL , MVT::i32, Expand); setOperationAction(ISD::ROTR , MVT::i32, Expand); - + setOperationAction(ISD::TRAP, MVT::Other, Legal); - + // Jump tables. setOperationAction(ISD::BR_JT, MVT::Other, Custom); @@ -122,7 +121,7 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM) // Thread Local Storage setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); - + // Conversion of i64 -> double produces constantpool nodes setOperationAction(ISD::ConstantPool, MVT::i32, Custom); @@ -143,7 +142,7 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM) setOperationAction(ISD::VACOPY, MVT::Other, Expand); setOperationAction(ISD::VAARG, MVT::Other, Custom); setOperationAction(ISD::VASTART, MVT::Other, Custom); - + // Dynamic stack setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); @@ -163,7 +162,7 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM) SDValue XCoreTargetLowering:: LowerOperation(SDValue Op, SelectionDAG &DAG) const { - switch (Op.getOpcode()) + switch (Op.getOpcode()) { case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); @@ -414,7 +413,7 @@ LowerLOAD(SDValue Op, SelectionDAG &DAG) const { SDValue Chain = LD->getChain(); SDValue BasePtr = LD->getBasePtr(); DebugLoc DL = Op.getDebugLoc(); - + SDValue Base; int64_t Offset; if (!LD->isVolatile() && @@ -437,10 +436,10 @@ LowerLOAD(SDValue Op, SelectionDAG &DAG) const { SDValue HighOffset = DAG.getConstant((Offset & ~0x3) + 4, MVT::i32); SDValue LowShift = DAG.getConstant((Offset & 0x3) * 8, MVT::i32); SDValue HighShift = DAG.getConstant(32 - (Offset & 0x3) * 8, MVT::i32); - + SDValue LowAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base, LowOffset); SDValue HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base, HighOffset); - + SDValue Low = DAG.getLoad(getPointerTy(), DL, Chain, LowAddr, MachinePointerInfo(), false, false, 0); SDValue High = DAG.getLoad(getPointerTy(), DL, Chain, @@ -453,7 +452,7 @@ LowerLOAD(SDValue Op, SelectionDAG &DAG) const { SDValue Ops[] = { Result, Chain }; return DAG.getMergeValues(Ops, 2, DL); } - + if (LD->getAlignment() == 2) { SDValue Low = DAG.getExtLoad(ISD::ZEXTLOAD, DL, MVT::i32, Chain, BasePtr, LD->getPointerInfo(), MVT::i16, @@ -473,16 +472,16 @@ LowerLOAD(SDValue Op, SelectionDAG &DAG) const { SDValue Ops[] = { Result, Chain }; return DAG.getMergeValues(Ops, 2, DL); } - + // Lower to a call to __misaligned_load(BasePtr). const Type *IntPtrTy = getTargetData()->getIntPtrType(*DAG.getContext()); TargetLowering::ArgListTy Args; TargetLowering::ArgListEntry Entry; - + Entry.Ty = IntPtrTy; Entry.Node = BasePtr; Args.push_back(Entry); - + std::pair<SDValue, SDValue> CallResult = LowerCallTo(Chain, IntPtrTy, false, false, false, false, 0, CallingConv::C, false, @@ -515,7 +514,7 @@ LowerSTORE(SDValue Op, SelectionDAG &DAG) const SDValue BasePtr = ST->getBasePtr(); SDValue Value = ST->getValue(); DebugLoc dl = Op.getDebugLoc(); - + if (ST->getAlignment() == 2) { SDValue Low = Value; SDValue High = DAG.getNode(ISD::SRL, dl, MVT::i32, Value, @@ -532,19 +531,19 @@ LowerSTORE(SDValue Op, SelectionDAG &DAG) const ST->isNonTemporal(), 2); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, StoreLow, StoreHigh); } - + // Lower to a call to __misaligned_store(BasePtr, Value). const Type *IntPtrTy = getTargetData()->getIntPtrType(*DAG.getContext()); TargetLowering::ArgListTy Args; TargetLowering::ArgListEntry Entry; - + Entry.Ty = IntPtrTy; Entry.Node = BasePtr; Args.push_back(Entry); - + Entry.Node = Value; Args.push_back(Entry); - + std::pair<SDValue, SDValue> CallResult = LowerCallTo(Chain, Type::getVoidTy(*DAG.getContext()), false, false, false, false, 0, CallingConv::C, false, @@ -722,7 +721,7 @@ ExpandADDSUB(SDNode *N, SelectionDAG &DAG) const } DebugLoc dl = N->getDebugLoc(); - + // Extract components SDValue LHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, N->getOperand(0), DAG.getConstant(0, MVT::i32)); @@ -732,7 +731,7 @@ ExpandADDSUB(SDNode *N, SelectionDAG &DAG) const N->getOperand(1), DAG.getConstant(0, MVT::i32)); SDValue RHSH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, N->getOperand(1), DAG.getConstant(1, MVT::i32)); - + // Expand unsigned Opcode = (N->getOpcode() == ISD::ADD) ? XCoreISD::LADD : XCoreISD::LSUB; @@ -740,7 +739,7 @@ ExpandADDSUB(SDNode *N, SelectionDAG &DAG) const SDValue Carry = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32), LHSL, RHSL, Zero); SDValue Lo(Carry.getNode(), 1); - + SDValue Ignored = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32), LHSH, RHSH, Carry); SDValue Hi(Ignored.getNode(), 1); @@ -761,8 +760,8 @@ LowerVAARG(SDValue Op, SelectionDAG &DAG) const Node->getOperand(1), MachinePointerInfo(V), false, false, 0); // Increment the pointer, VAList, to the next vararg - SDValue Tmp3 = DAG.getNode(ISD::ADD, dl, getPointerTy(), VAList, - DAG.getConstant(VT.getSizeInBits(), + SDValue Tmp3 = DAG.getNode(ISD::ADD, dl, getPointerTy(), VAList, + DAG.getConstant(VT.getSizeInBits(), getPointerTy())); // Store the incremented VAList to the legalized pointer Tmp3 = DAG.getStore(VAList.getValue(1), dl, Tmp3, Node->getOperand(1), @@ -781,20 +780,20 @@ LowerVASTART(SDValue Op, SelectionDAG &DAG) const MachineFunction &MF = DAG.getMachineFunction(); XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); SDValue Addr = DAG.getFrameIndex(XFI->getVarArgsFrameIndex(), MVT::i32); - return DAG.getStore(Op.getOperand(0), dl, Addr, Op.getOperand(1), + return DAG.getStore(Op.getOperand(0), dl, Addr, Op.getOperand(1), MachinePointerInfo(), false, false, 0); } SDValue XCoreTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { DebugLoc dl = Op.getDebugLoc(); - // Depths > 0 not supported yet! + // Depths > 0 not supported yet! if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0) return SDValue(); - + MachineFunction &MF = DAG.getMachineFunction(); const TargetRegisterInfo *RegInfo = getTargetMachine().getRegisterInfo(); - return DAG.getCopyFromReg(DAG.getEntryNode(), dl, + return DAG.getCopyFromReg(DAG.getEntryNode(), dl, RegInfo->getFrameRegister(MF), MVT::i32); } @@ -919,7 +918,7 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, // Get a count of how many bytes are to be pushed on the stack. unsigned NumBytes = CCInfo.getNextStackOffset(); - Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes, + Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes, getPointerTy(), true)); SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass; @@ -944,8 +943,8 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); break; } - - // Arguments that can be passed on register must be kept at + + // Arguments that can be passed on register must be kept at // RegsToPass vector if (VA.isRegLoc()) { RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); @@ -954,7 +953,7 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, int Offset = VA.getLocMemOffset(); - MemOpChains.push_back(DAG.getNode(XCoreISD::STWSP, dl, MVT::Other, + MemOpChains.push_back(DAG.getNode(XCoreISD::STWSP, dl, MVT::Other, Chain, Arg, DAG.getConstant(Offset/4, MVT::i32))); } @@ -963,16 +962,16 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, // Transform all store nodes into one single node because // all store nodes are independent of each other. if (!MemOpChains.empty()) - Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &MemOpChains[0], MemOpChains.size()); - // Build a sequence of copy-to-reg nodes chained together with token + // Build a sequence of copy-to-reg nodes chained together with token // chain and flag operands which copy the outgoing args into registers. // The InFlag in necessary since all emited instructions must be // stuck together. SDValue InFlag; for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { - Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, + Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, RegsToPass[i].second, InFlag); InFlag = Chain.getValue(1); } @@ -986,7 +985,7 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32); // XCoreBranchLink = #chain, #target_address, #opt_in_flags... - // = Chain, Callee, Reg#1, Reg#2, ... + // = Chain, Callee, Reg#1, Reg#2, ... // // Returns a chain & a flag for retval copy to use. SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); @@ -994,7 +993,7 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, Ops.push_back(Chain); Ops.push_back(Callee); - // Add argument registers to the end of the list so that they are + // Add argument registers to the end of the list so that they are // known live into the call. for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) Ops.push_back(DAG.getRegister(RegsToPass[i].first, @@ -1098,11 +1097,11 @@ XCoreTargetLowering::LowerCCCArguments(SDValue Chain, unsigned StackSlotSize = XCoreFrameLowering::stackSlotSize(); unsigned LRSaveSize = StackSlotSize; - + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; - + if (VA.isRegLoc()) { // Arguments passed in registers EVT RegVT = VA.getLocVT(); @@ -1139,12 +1138,12 @@ XCoreTargetLowering::LowerCCCArguments(SDValue Chain, // Create the SelectionDAG nodes corresponding to a load //from this parameter SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); - InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, + InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, MachinePointerInfo::getFixedStack(FI), false, false, 0)); } } - + if (isVarArg) { /* Argument registers */ static const unsigned ArgRegs[] = { @@ -1186,7 +1185,7 @@ XCoreTargetLowering::LowerCCCArguments(SDValue Chain, true)); } } - + return Chain; } @@ -1222,7 +1221,7 @@ XCoreTargetLowering::LowerReturn(SDValue Chain, // Analize return values. CCInfo.AnalyzeReturn(Outs, RetCC_XCore); - // If this is the first return lowered for this function, add + // If this is the first return lowered for this function, add // the regs to the liveout set for the function. if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { for (unsigned i = 0; i != RVLocs.size(); ++i) @@ -1237,7 +1236,7 @@ XCoreTargetLowering::LowerReturn(SDValue Chain, CCValAssign &VA = RVLocs[i]; assert(VA.isRegLoc() && "Can only return in registers!"); - Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag); // guarantee that all emitted copies are @@ -1265,7 +1264,7 @@ XCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, DebugLoc dl = MI->getDebugLoc(); assert((MI->getOpcode() == XCore::SELECT_CC) && "Unexpected instr type to insert"); - + // To "insert" a SELECT_CC instruction, we actually have to insert the diamond // control-flow pattern. The incoming instruction knows the destination vreg // to set, the condition code register to branch on, the true/false values to @@ -1273,7 +1272,7 @@ XCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, const BasicBlock *LLVM_BB = BB->getBasicBlock(); MachineFunction::iterator It = BB; ++It; - + // thisMBB: // ... // TrueVal = ... @@ -1296,7 +1295,7 @@ XCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, // Next, add the true and fallthrough blocks as its successors. BB->addSuccessor(copy0MBB); BB->addSuccessor(sinkMBB); - + BuildMI(BB, dl, TII.get(XCore::BRFT_lru6)) .addReg(MI->getOperand(1).getReg()).addMBB(sinkMBB); @@ -1304,10 +1303,10 @@ XCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, // %FalseValue = ... // # fallthrough to sinkMBB BB = copy0MBB; - + // Update machine-CFG edges BB->addSuccessor(sinkMBB); - + // sinkMBB: // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] // ... @@ -1316,7 +1315,7 @@ XCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, TII.get(XCore::PHI), MI->getOperand(0).getReg()) .addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB) .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB); - + MI->eraseFromParent(); // The pseudo instruction is gone now. return BB; } @@ -1354,7 +1353,7 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N, // fold (ladd x, 0, y) -> 0, add x, y iff carry is unused and y has only the // low bit set - if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 0)) { + if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 0)) { APInt KnownZero, KnownOne; APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), VT.getSizeInBits() - 1); @@ -1377,7 +1376,7 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N, EVT VT = N0.getValueType(); // fold (lsub 0, 0, x) -> x, -x iff x has only the low bit set - if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) { + if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) { APInt KnownZero, KnownOne; APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), VT.getSizeInBits() - 1); @@ -1393,7 +1392,7 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N, // fold (lsub x, 0, y) -> 0, sub x, y iff borrow is unused and y has only the // low bit set - if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 0)) { + if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 0)) { APInt KnownZero, KnownOne; APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), VT.getSizeInBits() - 1); @@ -1557,7 +1556,7 @@ static inline bool isImmUs4(int64_t val) /// isLegalAddressingMode - Return true if the addressing mode represented /// by AM is legal for this target, for a load/store of the specified type. bool -XCoreTargetLowering::isLegalAddressingMode(const AddrMode &AM, +XCoreTargetLowering::isLegalAddressingMode(const AddrMode &AM, const Type *Ty) const { if (Ty->getTypeID() == Type::VoidTyID) return AM.Scale == 0 && isImmUs(AM.BaseOffs) && isImmUs4(AM.BaseOffs); @@ -1568,7 +1567,7 @@ XCoreTargetLowering::isLegalAddressingMode(const AddrMode &AM, return Size >= 4 && !AM.HasBaseReg && AM.Scale == 0 && AM.BaseOffs%4 == 0; } - + switch (Size) { case 1: // reg + imm @@ -1593,7 +1592,7 @@ XCoreTargetLowering::isLegalAddressingMode(const AddrMode &AM, // reg + reg<<2 return AM.Scale == 4 && AM.BaseOffs == 0; } - + return false; } @@ -1603,7 +1602,7 @@ XCoreTargetLowering::isLegalAddressingMode(const AddrMode &AM, std::vector<unsigned> XCoreTargetLowering:: getRegClassForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const + EVT VT) const { if (Constraint.size() != 1) return std::vector<unsigned>(); @@ -1611,9 +1610,9 @@ getRegClassForInlineAsmConstraint(const std::string &Constraint, switch (Constraint[0]) { default : break; case 'r': - return make_vector<unsigned>(XCore::R0, XCore::R1, XCore::R2, - XCore::R3, XCore::R4, XCore::R5, - XCore::R6, XCore::R7, XCore::R8, + return make_vector<unsigned>(XCore::R0, XCore::R1, XCore::R2, + XCore::R3, XCore::R4, XCore::R5, + XCore::R6, XCore::R7, XCore::R8, XCore::R9, XCore::R10, XCore::R11, 0); break; } diff --git a/contrib/llvm/lib/Target/XCore/XCoreISelLowering.h b/contrib/llvm/lib/Target/XCore/XCoreISelLowering.h index 7e5dd2e..bb3f2cc 100644 --- a/contrib/llvm/lib/Target/XCore/XCoreISelLowering.h +++ b/contrib/llvm/lib/Target/XCore/XCoreISelLowering.h @@ -20,11 +20,11 @@ #include "XCore.h" namespace llvm { - + // Forward delcarations class XCoreSubtarget; class XCoreTargetMachine; - + namespace XCoreISD { enum NodeType { // Start the numbering where the builtin ops and target ops leave off. @@ -38,16 +38,16 @@ namespace llvm { // dp relative address DPRelativeWrapper, - + // cp relative address CPRelativeWrapper, - + // Store word to stack STWSP, // Corresponds to retsp instruction RETSP, - + // Corresponds to LADD instruction LADD, @@ -74,13 +74,14 @@ namespace llvm { //===--------------------------------------------------------------------===// // TargetLowering Implementation //===--------------------------------------------------------------------===// - class XCoreTargetLowering : public TargetLowering + class XCoreTargetLowering : public TargetLowering { public: explicit XCoreTargetLowering(XCoreTargetMachine &TM); virtual unsigned getJumpTableEncoding() const; + virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i32; } /// LowerOperation - Provide custom lowering hooks for some operations. virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; @@ -91,10 +92,10 @@ namespace llvm { virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results, SelectionDAG &DAG) const; - /// getTargetNodeName - This method returns the name of a target specific + /// getTargetNodeName - This method returns the name of a target specific // DAG node. virtual const char *getTargetNodeName(unsigned Opcode) const; - + virtual MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const; @@ -108,7 +109,7 @@ namespace llvm { private: const XCoreTargetMachine &TM; const XCoreSubtarget &Subtarget; - + // Lower Operand helpers SDValue LowerCCCArguments(SDValue Chain, CallingConv::ID CallConv, @@ -148,12 +149,12 @@ namespace llvm { SDValue LowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerTRAMPOLINE(SDValue Op, SelectionDAG &DAG) const; - + // Inline asm support std::vector<unsigned> getRegClassForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; - + // Expand specifics SDValue TryExpandADDWithMul(SDNode *Op, SelectionDAG &DAG) const; SDValue ExpandADDSUB(SDNode *Op, SelectionDAG &DAG) const; diff --git a/contrib/llvm/lib/Target/XCore/XCoreInstrInfo.td b/contrib/llvm/lib/Target/XCore/XCoreInstrInfo.td index 38cc734..ecdd4cb 100644 --- a/contrib/llvm/lib/Target/XCore/XCoreInstrInfo.td +++ b/contrib/llvm/lib/Target/XCore/XCoreInstrInfo.td @@ -727,7 +727,7 @@ def NEG : _F2R<(outs GRRegs:$dst), (ins GRRegs:$b), "neg $dst, $b", [(set GRRegs:$dst, (ineg GRRegs:$b))]>; -// TODO setd, eet, eef, getts, setpt, outshr, inshr, testwct, tinitpc, tinitdp, +// TODO setd, eet, eef, testwct, tinitpc, tinitdp, // tinitsp, tinitcp, tsetmr, sext (reg), zext (reg) let Constraints = "$src1 = $dst" in { let neverHasSideEffects = 1 in @@ -758,6 +758,14 @@ def GETR_rus : _FRUS<(outs GRRegs:$dst), (ins i32imm:$type), "getr $dst, $type", [(set GRRegs:$dst, (int_xcore_getr immUs:$type))]>; +def GETTS_2r : _F2R<(outs GRRegs:$dst), (ins GRRegs:$r), + "getts $dst, res[$r]", + [(set GRRegs:$dst, (int_xcore_getts GRRegs:$r))]>; + +def SETPT_2r : _F2R<(outs), (ins GRRegs:$r, GRRegs:$val), + "setpt res[$r], $val", + [(int_xcore_setpt GRRegs:$r, GRRegs:$val)]>; + def OUTCT_2r : _F2R<(outs), (ins GRRegs:$r, GRRegs:$val), "outct res[$r], $val", [(int_xcore_outct GRRegs:$r, GRRegs:$val)]>; @@ -774,6 +782,11 @@ def OUT_2r : _F2R<(outs), (ins GRRegs:$r, GRRegs:$val), "out res[$r], $val", [(int_xcore_out GRRegs:$r, GRRegs:$val)]>; +let Constraints = "$src = $dst" in +def OUTSHR_2r : _F2R<(outs GRRegs:$dst), (ins GRRegs:$r, GRRegs:$src), + "outshr res[$r], $src", + [(set GRRegs:$dst, (int_xcore_outshr GRRegs:$r, GRRegs:$src))]>; + def INCT_2r : _F2R<(outs GRRegs:$dst), (ins GRRegs:$r), "inct $dst, res[$r]", [(set GRRegs:$dst, (int_xcore_inct GRRegs:$r))]>; @@ -786,6 +799,11 @@ def IN_2r : _F2R<(outs GRRegs:$dst), (ins GRRegs:$r), "in $dst, res[$r]", [(set GRRegs:$dst, (int_xcore_in GRRegs:$r))]>; +let Constraints = "$src = $dst" in +def INSHR_2r : _F2R<(outs GRRegs:$dst), (ins GRRegs:$r, GRRegs:$src), + "inshr $dst, res[$r]", + [(set GRRegs:$dst, (int_xcore_inshr GRRegs:$r, GRRegs:$src))]>; + def CHKCT_2r : _F2R<(outs), (ins GRRegs:$r, GRRegs:$val), "chkct res[$r], $val", [(int_xcore_chkct GRRegs:$r, GRRegs:$val)]>; @@ -799,7 +817,7 @@ def SETD_2r : _F2R<(outs), (ins GRRegs:$r, GRRegs:$val), [(int_xcore_setd GRRegs:$r, GRRegs:$val)]>; // Two operand long -// TODO settw, setclk, setrdy, setpsc, endin, peek, +// TODO setclk, setrdy, setpsc, endin, peek, // getd, testlcl, tinitlr, getps, setps def BITREV_l2r : _FL2R<(outs GRRegs:$dst), (ins GRRegs:$src), "bitrev $dst, $src", @@ -813,13 +831,17 @@ def CLZ_l2r : _FL2R<(outs GRRegs:$dst), (ins GRRegs:$src), "clz $dst, $src", [(set GRRegs:$dst, (ctlz GRRegs:$src))]>; -def SETC_l2r : _FRU6<(outs), (ins GRRegs:$r, GRRegs:$val), +def SETC_l2r : _FL2R<(outs), (ins GRRegs:$r, GRRegs:$val), "setc res[$r], $val", [(int_xcore_setc GRRegs:$r, GRRegs:$val)]>; +def SETTW_l2r : _FL2R<(outs), (ins GRRegs:$r, GRRegs:$val), + "settw res[$r], $val", + [(int_xcore_settw GRRegs:$r, GRRegs:$val)]>; + // One operand short -// TODO edu, eeu, waitet, waitef, tstart, msync, mjoin, syncr, clrtp -// setdp, setcp, setv, setev, kcall +// TODO edu, eeu, waitet, waitef, tstart, msync, mjoin, clrtp +// setdp, setcp, setev, kcall // dgetreg let isBranch=1, isIndirectBranch=1, isTerminator=1, isBarrier = 1 in def BAU_1r : _F1R<(outs), (ins GRRegs:$addr), @@ -859,20 +881,41 @@ def BLA_1r : _F1R<(outs), (ins GRRegs:$addr, variable_ops), [(XCoreBranchLink GRRegs:$addr)]>; } +def SYNCR_1r : _F1R<(outs), (ins GRRegs:$r), + "syncr res[$r]", + [(int_xcore_syncr GRRegs:$r)]>; + def FREER_1r : _F1R<(outs), (ins GRRegs:$r), "freer res[$r]", [(int_xcore_freer GRRegs:$r)]>; +let Uses=[R11] in +def SETV_1r : _F1R<(outs), (ins GRRegs:$r), + "setv res[$r], r11", + [(int_xcore_setv GRRegs:$r, R11)]>; + +def EEU_1r : _F1R<(outs), (ins GRRegs:$r), + "eeu res[$r]", + [(int_xcore_eeu GRRegs:$r)]>; + // Zero operand short -// TODO waiteu, clre, ssync, freet, ldspc, stspc, ldssr, stssr, ldsed, stsed, +// TODO ssync, freet, ldspc, stspc, ldssr, stssr, ldsed, stsed, // stet, geted, getet, getkep, getksp, setkep, getid, kret, dcall, dret, // dentsp, drestsp +def CLRE_0R : _F0R<(outs), (ins), "clre", [(int_xcore_clre)]>; + let Defs = [R11] in def GETID_0R : _F0R<(outs), (ins), "get r11, id", [(set R11, (int_xcore_getid))]>; +let isBranch=1, isIndirectBranch=1, isTerminator=1, isBarrier = 1, + hasSideEffects = 1 in +def WAITEU_0R : _F0R<(outs), (ins), + "waiteu", + [(brind (int_xcore_waitevent))]>; + //===----------------------------------------------------------------------===// // Non-Instruction Patterns //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/contrib/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index b6b6b84..7986d1a 100644 --- a/contrib/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1897,6 +1897,39 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { return BinaryOperator::CreateNot(And); } + // Canonicalize xor to the RHS. + if (match(Op0, m_Xor(m_Value(), m_Value()))) + std::swap(Op0, Op1); + + // A | ( A ^ B) -> A | B + // A | (~A ^ B) -> A | ~B + if (match(Op1, m_Xor(m_Value(A), m_Value(B)))) { + if (Op0 == A || Op0 == B) + return BinaryOperator::CreateOr(A, B); + + if (Op1->hasOneUse() && match(A, m_Not(m_Specific(Op0)))) { + Value *Not = Builder->CreateNot(B, B->getName()+".not"); + return BinaryOperator::CreateOr(Not, Op0); + } + if (Op1->hasOneUse() && match(B, m_Not(m_Specific(Op0)))) { + Value *Not = Builder->CreateNot(A, A->getName()+".not"); + return BinaryOperator::CreateOr(Not, Op0); + } + } + + // A | ~(A | B) -> A | ~B + // A | ~(A ^ B) -> A | ~B + if (match(Op1, m_Not(m_Value(A)))) + if (BinaryOperator *B = dyn_cast<BinaryOperator>(A)) + if ((Op0 == B->getOperand(0) || Op0 == B->getOperand(1)) && + Op1->hasOneUse() && (B->getOpcode() == Instruction::Or || + B->getOpcode() == Instruction::Xor)) { + Value *NotOp = Op0 == B->getOperand(0) ? B->getOperand(1) : + B->getOperand(0); + Value *Not = Builder->CreateNot(NotOp, NotOp->getName()+".not"); + return BinaryOperator::CreateOr(Not, Op0); + } + if (ICmpInst *RHS = dyn_cast<ICmpInst>(I.getOperand(1))) if (ICmpInst *LHS = dyn_cast<ICmpInst>(I.getOperand(0))) if (Value *Res = FoldOrOfICmps(LHS, RHS)) diff --git a/contrib/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/contrib/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index 8449f7b..0e46450 100644 --- a/contrib/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/contrib/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -953,10 +953,19 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { if (Callee->isDeclaration() && !isConvertible) return false; } - if (FT->getNumParams() < NumActualArgs && !FT->isVarArg() && - Callee->isDeclaration()) - return false; // Do not delete arguments unless we have a function body. - + if (Callee->isDeclaration()) { + // Do not delete arguments unless we have a function body. + if (FT->getNumParams() < NumActualArgs && !FT->isVarArg()) + return false; + + // If the callee is just a declaration, don't change the varargsness of the + // call. We don't want to introduce a varargs call where one doesn't + // already exist. + const PointerType *APTy = cast<PointerType>(CS.getCalledValue()->getType()); + if (FT->isVarArg()!=cast<FunctionType>(APTy->getElementType())->isVarArg()) + return false; + } + if (FT->getNumParams() < NumActualArgs && FT->isVarArg() && !CallerPAL.isEmpty()) // In this case we have more arguments than the new function type, but we @@ -970,8 +979,9 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { return false; } + // Okay, we decided that this is a safe thing to do: go ahead and start - // inserting cast instructions as necessary... + // inserting cast instructions as necessary. std::vector<Value*> Args; Args.reserve(NumActualArgs); SmallVector<AttributeWithIndex, 8> attrVec; diff --git a/contrib/llvm/lib/Transforms/Scalar/LoopDeletion.cpp b/contrib/llvm/lib/Transforms/Scalar/LoopDeletion.cpp index 6d1d344..753a558 100644 --- a/contrib/llvm/lib/Transforms/Scalar/LoopDeletion.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/LoopDeletion.cpp @@ -78,7 +78,6 @@ bool LoopDeletion::IsLoopDead(Loop* L, SmallVector<BasicBlock*, 4>& exitingBlocks, SmallVector<BasicBlock*, 4>& exitBlocks, bool &Changed, BasicBlock *Preheader) { - BasicBlock* exitingBlock = exitingBlocks[0]; BasicBlock* exitBlock = exitBlocks[0]; // Make sure that all PHI entries coming from the loop are loop invariant. @@ -88,11 +87,21 @@ bool LoopDeletion::IsLoopDead(Loop* L, // of the loop. BasicBlock::iterator BI = exitBlock->begin(); while (PHINode* P = dyn_cast<PHINode>(BI)) { - Value* incoming = P->getIncomingValueForBlock(exitingBlock); + Value* incoming = P->getIncomingValueForBlock(exitingBlocks[0]); + + // Make sure all exiting blocks produce the same incoming value for the exit + // block. If there are different incoming values for different exiting + // blocks, then it is impossible to statically determine which value should + // be used. + for (unsigned i = 1; i < exitingBlocks.size(); ++i) { + if (incoming != P->getIncomingValueForBlock(exitingBlocks[i])) + return false; + } + if (Instruction* I = dyn_cast<Instruction>(incoming)) if (!L->makeLoopInvariant(I, Changed, Preheader->getTerminator())) return false; - + ++BI; } @@ -147,10 +156,6 @@ bool LoopDeletion::runOnLoop(Loop* L, LPPassManager& LPM) { if (exitBlocks.size() != 1) return false; - // Loops with multiple exits are too complicated to handle correctly. - if (exitingBlocks.size() != 1) - return false; - // Finally, we have to check that the loop really is dead. bool Changed = false; if (!IsLoopDead(L, exitingBlocks, exitBlocks, Changed, preheader)) @@ -166,7 +171,6 @@ bool LoopDeletion::runOnLoop(Loop* L, LPPassManager& LPM) { // Now that we know the removal is safe, remove the loop by changing the // branch from the preheader to go to the single exit block. BasicBlock* exitBlock = exitBlocks[0]; - BasicBlock* exitingBlock = exitingBlocks[0]; // Because we're deleting a large chunk of code at once, the sequence in which // we remove things is very important to avoid invalidation issues. Don't @@ -183,9 +187,12 @@ bool LoopDeletion::runOnLoop(Loop* L, LPPassManager& LPM) { // Rewrite phis in the exit block to get their inputs from // the preheader instead of the exiting block. + BasicBlock* exitingBlock = exitingBlocks[0]; BasicBlock::iterator BI = exitBlock->begin(); while (PHINode* P = dyn_cast<PHINode>(BI)) { P->replaceUsesOfWith(exitingBlock, preheader); + for (unsigned i = 1; i < exitingBlocks.size(); ++i) + P->removeIncomingValue(exitingBlocks[i]); ++BI; } diff --git a/contrib/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/contrib/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp index d7fa149..f8ce214 100644 --- a/contrib/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp @@ -31,6 +31,11 @@ // void foo(_Complex float *P) // for (i) { __real__(*P) = 0; __imag__(*P) = 0; } // +// We should enhance this to handle negative strides through memory. +// Alternatively (and perhaps better) we could rely on an earlier pass to force +// forward iteration through memory, which is generally better for cache +// behavior. Negative strides *do* happen for memset/memcpy loops. +// // This could recognize common matrix multiplies and dot product idioms and // replace them with calls to BLAS (if linked in??). // @@ -272,10 +277,17 @@ bool LoopIdiomRecognize::processLoopStore(StoreInst *SI, const SCEV *BECount) { unsigned StoreSize = (unsigned)SizeInBits >> 3; const SCEVConstant *Stride = dyn_cast<SCEVConstant>(StoreEv->getOperand(1)); - // TODO: Could also handle negative stride here someday, that will require the - // validity check in mayLoopAccessLocation to be updated though. - if (Stride == 0 || StoreSize != Stride->getValue()->getValue()) + if (Stride == 0 || StoreSize != Stride->getValue()->getValue()) { + // TODO: Could also handle negative stride here someday, that will require + // the validity check in mayLoopAccessLocation to be updated though. + // Enable this to print exact negative strides. + if (0 && Stride && StoreSize == -Stride->getValue()->getValue()) { + dbgs() << "NEGATIVE STRIDE: " << *SI << "\n"; + dbgs() << "BB: " << *SI->getParent(); + } + return false; + } // See if we can optimize just this store in isolation. if (processLoopStridedStore(StorePtr, StoreSize, SI->getAlignment(), diff --git a/contrib/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/contrib/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp index ec45b71..9f136d4 100644 --- a/contrib/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp +++ b/contrib/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp @@ -25,13 +25,14 @@ #include "llvm/Support/IRBuilder.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLibraryInfo.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Config/config.h" +#include "llvm/Config/config.h" // FIXME: Shouldn't depend on host! using namespace llvm; STATISTIC(NumSimplified, "Number of library calls simplified"); @@ -1369,6 +1370,8 @@ namespace { /// This pass optimizes well known library functions from libc and libm. /// class SimplifyLibCalls : public FunctionPass { + TargetLibraryInfo *TLI; + StringMap<LibCallOptimization*> Optimizations; // String and Memory LibCall Optimizations StrCatOpt StrCat; StrNCatOpt StrNCat; StrChrOpt StrChr; StrRChrOpt StrRChr; @@ -1385,7 +1388,7 @@ namespace { SPrintFOpt SPrintF; PrintFOpt PrintF; FWriteOpt FWrite; FPutsOpt FPuts; FPrintFOpt FPrintF; PutsOpt Puts; - + bool Modified; // This is only used by doInitialization. public: static char ID; // Pass identification @@ -1402,14 +1405,20 @@ namespace { void setDoesNotAlias(Function &F, unsigned n); bool doInitialization(Module &M); + void inferPrototypeAttributes(Function &F); virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired<TargetLibraryInfo>(); } }; - char SimplifyLibCalls::ID = 0; } // end anonymous namespace. -INITIALIZE_PASS(SimplifyLibCalls, "simplify-libcalls", - "Simplify well-known library calls", false, false) +char SimplifyLibCalls::ID = 0; + +INITIALIZE_PASS_BEGIN(SimplifyLibCalls, "simplify-libcalls", + "Simplify well-known library calls", false, false) +INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfo) +INITIALIZE_PASS_END(SimplifyLibCalls, "simplify-libcalls", + "Simplify well-known library calls", false, false) // Public interface to the Simplify LibCalls pass. FunctionPass *llvm::createSimplifyLibCallsPass() { @@ -1441,9 +1450,9 @@ void SimplifyLibCalls::InitOptimizations() { Optimizations["strcspn"] = &StrCSpn; Optimizations["strstr"] = &StrStr; Optimizations["memcmp"] = &MemCmp; - Optimizations["memcpy"] = &MemCpy; + if (TLI->has(LibFunc::memcpy)) Optimizations["memcpy"] = &MemCpy; Optimizations["memmove"] = &MemMove; - Optimizations["memset"] = &MemSet; + if (TLI->has(LibFunc::memset)) Optimizations["memset"] = &MemSet; // _chk variants of String and Memory LibCall Optimizations. Optimizations["__strcpy_chk"] = &StrCpyChk; @@ -1506,6 +1515,8 @@ void SimplifyLibCalls::InitOptimizations() { /// runOnFunction - Top level algorithm. /// bool SimplifyLibCalls::runOnFunction(Function &F) { + TLI = &getAnalysis<TargetLibraryInfo>(); + if (Optimizations.empty()) InitOptimizations(); @@ -1597,688 +1608,654 @@ void SimplifyLibCalls::setDoesNotAlias(Function &F, unsigned n) { } } + +void SimplifyLibCalls::inferPrototypeAttributes(Function &F) { + const FunctionType *FTy = F.getFunctionType(); + + StringRef Name = F.getName(); + switch (Name[0]) { + case 's': + if (Name == "strlen") { + if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy()) + return; + setOnlyReadsMemory(F); + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "strchr" || + Name == "strrchr") { + if (FTy->getNumParams() != 2 || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isIntegerTy()) + return; + setOnlyReadsMemory(F); + setDoesNotThrow(F); + } else if (Name == "strcpy" || + Name == "stpcpy" || + Name == "strcat" || + Name == "strtol" || + Name == "strtod" || + Name == "strtof" || + Name == "strtoul" || + Name == "strtoll" || + Name == "strtold" || + Name == "strncat" || + Name == "strncpy" || + Name == "strtoull") { + if (FTy->getNumParams() < 2 || + !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } else if (Name == "strxfrm") { + if (FTy->getNumParams() != 3 || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "strcmp" || + Name == "strspn" || + Name == "strncmp" || + Name == "strcspn" || + Name == "strcoll" || + Name == "strcasecmp" || + Name == "strncasecmp") { + if (FTy->getNumParams() < 2 || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) + return; + setOnlyReadsMemory(F); + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "strstr" || + Name == "strpbrk") { + if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy()) + return; + setOnlyReadsMemory(F); + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } else if (Name == "strtok" || + Name == "strtok_r") { + if (FTy->getNumParams() < 2 || !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } else if (Name == "scanf" || + Name == "setbuf" || + Name == "setvbuf") { + if (FTy->getNumParams() < 1 || !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "strdup" || + Name == "strndup") { + if (FTy->getNumParams() < 1 || !FTy->getReturnType()->isPointerTy() || + !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + setDoesNotCapture(F, 1); + } else if (Name == "stat" || + Name == "sscanf" || + Name == "sprintf" || + Name == "statvfs") { + if (FTy->getNumParams() < 2 || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "snprintf") { + if (FTy->getNumParams() != 3 || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(2)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 3); + } else if (Name == "setitimer") { + if (FTy->getNumParams() != 3 || + !FTy->getParamType(1)->isPointerTy() || + !FTy->getParamType(2)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + setDoesNotCapture(F, 3); + } else if (Name == "system") { + if (FTy->getNumParams() != 1 || + !FTy->getParamType(0)->isPointerTy()) + return; + // May throw; "system" is a valid pthread cancellation point. + setDoesNotCapture(F, 1); + } + break; + case 'm': + if (Name == "malloc") { + if (FTy->getNumParams() != 1 || + !FTy->getReturnType()->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + } else if (Name == "memcmp") { + if (FTy->getNumParams() != 3 || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) + return; + setOnlyReadsMemory(F); + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "memchr" || + Name == "memrchr") { + if (FTy->getNumParams() != 3) + return; + setOnlyReadsMemory(F); + setDoesNotThrow(F); + } else if (Name == "modf" || + Name == "modff" || + Name == "modfl" || + Name == "memcpy" || + Name == "memccpy" || + Name == "memmove") { + if (FTy->getNumParams() < 2 || + !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } else if (Name == "memalign") { + if (!FTy->getReturnType()->isPointerTy()) + return; + setDoesNotAlias(F, 0); + } else if (Name == "mkdir" || + Name == "mktime") { + if (FTy->getNumParams() == 0 || + !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } + break; + case 'r': + if (Name == "realloc") { + if (FTy->getNumParams() != 2 || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getReturnType()->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + setDoesNotCapture(F, 1); + } else if (Name == "read") { + if (FTy->getNumParams() != 3 || + !FTy->getParamType(1)->isPointerTy()) + return; + // May throw; "read" is a valid pthread cancellation point. + setDoesNotCapture(F, 2); + } else if (Name == "rmdir" || + Name == "rewind" || + Name == "remove" || + Name == "realpath") { + if (FTy->getNumParams() < 1 || + !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "rename" || + Name == "readlink") { + if (FTy->getNumParams() < 2 || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } + break; + case 'w': + if (Name == "write") { + if (FTy->getNumParams() != 3 || !FTy->getParamType(1)->isPointerTy()) + return; + // May throw; "write" is a valid pthread cancellation point. + setDoesNotCapture(F, 2); + } + break; + case 'b': + if (Name == "bcopy") { + if (FTy->getNumParams() != 3 || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "bcmp") { + if (FTy->getNumParams() != 3 || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setOnlyReadsMemory(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "bzero") { + if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } + break; + case 'c': + if (Name == "calloc") { + if (FTy->getNumParams() != 2 || + !FTy->getReturnType()->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + } else if (Name == "chmod" || + Name == "chown" || + Name == "ctermid" || + Name == "clearerr" || + Name == "closedir") { + if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } + break; + case 'a': + if (Name == "atoi" || + Name == "atol" || + Name == "atof" || + Name == "atoll") { + if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setOnlyReadsMemory(F); + setDoesNotCapture(F, 1); + } else if (Name == "access") { + if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } + break; + case 'f': + if (Name == "fopen") { + if (FTy->getNumParams() != 2 || + !FTy->getReturnType()->isPointerTy() || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "fdopen") { + if (FTy->getNumParams() != 2 || + !FTy->getReturnType()->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + setDoesNotCapture(F, 2); + } else if (Name == "feof" || + Name == "free" || + Name == "fseek" || + Name == "ftell" || + Name == "fgetc" || + Name == "fseeko" || + Name == "ftello" || + Name == "fileno" || + Name == "fflush" || + Name == "fclose" || + Name == "fsetpos" || + Name == "flockfile" || + Name == "funlockfile" || + Name == "ftrylockfile") { + if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "ferror") { + if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setOnlyReadsMemory(F); + } else if (Name == "fputc" || + Name == "fstat" || + Name == "frexp" || + Name == "frexpf" || + Name == "frexpl" || + Name == "fstatvfs") { + if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } else if (Name == "fgets") { + if (FTy->getNumParams() != 3 || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(2)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 3); + } else if (Name == "fread" || + Name == "fwrite") { + if (FTy->getNumParams() != 4 || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(3)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 4); + } else if (Name == "fputs" || + Name == "fscanf" || + Name == "fprintf" || + Name == "fgetpos") { + if (FTy->getNumParams() < 2 || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } + break; + case 'g': + if (Name == "getc" || + Name == "getlogin_r" || + Name == "getc_unlocked") { + if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "getenv") { + if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setOnlyReadsMemory(F); + setDoesNotCapture(F, 1); + } else if (Name == "gets" || + Name == "getchar") { + setDoesNotThrow(F); + } else if (Name == "getitimer") { + if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } else if (Name == "getpwnam") { + if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } + break; + case 'u': + if (Name == "ungetc") { + if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } else if (Name == "uname" || + Name == "unlink" || + Name == "unsetenv") { + if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "utime" || + Name == "utimes") { + if (FTy->getNumParams() != 2 || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } + break; + case 'p': + if (Name == "putc") { + if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } else if (Name == "puts" || + Name == "printf" || + Name == "perror") { + if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "pread" || + Name == "pwrite") { + if (FTy->getNumParams() != 4 || !FTy->getParamType(1)->isPointerTy()) + return; + // May throw; these are valid pthread cancellation points. + setDoesNotCapture(F, 2); + } else if (Name == "putchar") { + setDoesNotThrow(F); + } else if (Name == "popen") { + if (FTy->getNumParams() != 2 || + !FTy->getReturnType()->isPointerTy() || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "pclose") { + if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } + break; + case 'v': + if (Name == "vscanf") { + if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "vsscanf" || + Name == "vfscanf") { + if (FTy->getNumParams() != 3 || + !FTy->getParamType(1)->isPointerTy() || + !FTy->getParamType(2)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "valloc") { + if (!FTy->getReturnType()->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + } else if (Name == "vprintf") { + if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "vfprintf" || + Name == "vsprintf") { + if (FTy->getNumParams() != 3 || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "vsnprintf") { + if (FTy->getNumParams() != 4 || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(2)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 3); + } + break; + case 'o': + if (Name == "open") { + if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy()) + return; + // May throw; "open" is a valid pthread cancellation point. + setDoesNotCapture(F, 1); + } else if (Name == "opendir") { + if (FTy->getNumParams() != 1 || + !FTy->getReturnType()->isPointerTy() || + !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + setDoesNotCapture(F, 1); + } + break; + case 't': + if (Name == "tmpfile") { + if (!FTy->getReturnType()->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + } else if (Name == "times") { + if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } + break; + case 'h': + if (Name == "htonl" || + Name == "htons") { + setDoesNotThrow(F); + setDoesNotAccessMemory(F); + } + break; + case 'n': + if (Name == "ntohl" || + Name == "ntohs") { + setDoesNotThrow(F); + setDoesNotAccessMemory(F); + } + break; + case 'l': + if (Name == "lstat") { + if (FTy->getNumParams() != 2 || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "lchown") { + if (FTy->getNumParams() != 3 || !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } + break; + case 'q': + if (Name == "qsort") { + if (FTy->getNumParams() != 4 || !FTy->getParamType(3)->isPointerTy()) + return; + // May throw; places call through function pointer. + setDoesNotCapture(F, 4); + } + break; + case '_': + if (Name == "__strdup" || + Name == "__strndup") { + if (FTy->getNumParams() < 1 || + !FTy->getReturnType()->isPointerTy() || + !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + setDoesNotCapture(F, 1); + } else if (Name == "__strtok_r") { + if (FTy->getNumParams() != 3 || + !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } else if (Name == "_IO_getc") { + if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "_IO_putc") { + if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } + break; + case 1: + if (Name == "\1__isoc99_scanf") { + if (FTy->getNumParams() < 1 || + !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "\1stat64" || + Name == "\1lstat64" || + Name == "\1statvfs64" || + Name == "\1__isoc99_sscanf") { + if (FTy->getNumParams() < 1 || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "\1fopen64") { + if (FTy->getNumParams() != 2 || + !FTy->getReturnType()->isPointerTy() || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + setDoesNotCapture(F, 1); + setDoesNotCapture(F, 2); + } else if (Name == "\1fseeko64" || + Name == "\1ftello64") { + if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 1); + } else if (Name == "\1tmpfile64") { + if (!FTy->getReturnType()->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotAlias(F, 0); + } else if (Name == "\1fstat64" || + Name == "\1fstatvfs64") { + if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy()) + return; + setDoesNotThrow(F); + setDoesNotCapture(F, 2); + } else if (Name == "\1open64") { + if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy()) + return; + // May throw; "open" is a valid pthread cancellation point. + setDoesNotCapture(F, 1); + } + break; + } +} + /// doInitialization - Add attributes to well-known functions. /// bool SimplifyLibCalls::doInitialization(Module &M) { Modified = false; for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { Function &F = *I; - if (!F.isDeclaration()) - continue; - - if (!F.hasName()) - continue; - - const FunctionType *FTy = F.getFunctionType(); - - StringRef Name = F.getName(); - switch (Name[0]) { - case 's': - if (Name == "strlen") { - if (FTy->getNumParams() != 1 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setOnlyReadsMemory(F); - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - } else if (Name == "strchr" || - Name == "strrchr") { - if (FTy->getNumParams() != 2 || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getParamType(1)->isIntegerTy()) - continue; - setOnlyReadsMemory(F); - setDoesNotThrow(F); - } else if (Name == "strcpy" || - Name == "stpcpy" || - Name == "strcat" || - Name == "strtol" || - Name == "strtod" || - Name == "strtof" || - Name == "strtoul" || - Name == "strtoll" || - Name == "strtold" || - Name == "strncat" || - Name == "strncpy" || - Name == "strtoull") { - if (FTy->getNumParams() < 2 || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 2); - } else if (Name == "strxfrm") { - if (FTy->getNumParams() != 3 || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - setDoesNotCapture(F, 2); - } else if (Name == "strcmp" || - Name == "strspn" || - Name == "strncmp" || - Name == "strcspn" || - Name == "strcoll" || - Name == "strcasecmp" || - Name == "strncasecmp") { - if (FTy->getNumParams() < 2 || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getParamType(1)->isPointerTy()) - continue; - setOnlyReadsMemory(F); - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - setDoesNotCapture(F, 2); - } else if (Name == "strstr" || - Name == "strpbrk") { - if (FTy->getNumParams() != 2 || - !FTy->getParamType(1)->isPointerTy()) - continue; - setOnlyReadsMemory(F); - setDoesNotThrow(F); - setDoesNotCapture(F, 2); - } else if (Name == "strtok" || - Name == "strtok_r") { - if (FTy->getNumParams() < 2 || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 2); - } else if (Name == "scanf" || - Name == "setbuf" || - Name == "setvbuf") { - if (FTy->getNumParams() < 1 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - } else if (Name == "strdup" || - Name == "strndup") { - if (FTy->getNumParams() < 1 || - !FTy->getReturnType()->isPointerTy() || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotAlias(F, 0); - setDoesNotCapture(F, 1); - } else if (Name == "stat" || - Name == "sscanf" || - Name == "sprintf" || - Name == "statvfs") { - if (FTy->getNumParams() < 2 || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - setDoesNotCapture(F, 2); - } else if (Name == "snprintf") { - if (FTy->getNumParams() != 3 || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getParamType(2)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - setDoesNotCapture(F, 3); - } else if (Name == "setitimer") { - if (FTy->getNumParams() != 3 || - !FTy->getParamType(1)->isPointerTy() || - !FTy->getParamType(2)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 2); - setDoesNotCapture(F, 3); - } else if (Name == "system") { - if (FTy->getNumParams() != 1 || - !FTy->getParamType(0)->isPointerTy()) - continue; - // May throw; "system" is a valid pthread cancellation point. - setDoesNotCapture(F, 1); - } - break; - case 'm': - if (Name == "malloc") { - if (FTy->getNumParams() != 1 || - !FTy->getReturnType()->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotAlias(F, 0); - } else if (Name == "memcmp") { - if (FTy->getNumParams() != 3 || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getParamType(1)->isPointerTy()) - continue; - setOnlyReadsMemory(F); - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - setDoesNotCapture(F, 2); - } else if (Name == "memchr" || - Name == "memrchr") { - if (FTy->getNumParams() != 3) - continue; - setOnlyReadsMemory(F); - setDoesNotThrow(F); - } else if (Name == "modf" || - Name == "modff" || - Name == "modfl" || - Name == "memcpy" || - Name == "memccpy" || - Name == "memmove") { - if (FTy->getNumParams() < 2 || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 2); - } else if (Name == "memalign") { - if (!FTy->getReturnType()->isPointerTy()) - continue; - setDoesNotAlias(F, 0); - } else if (Name == "mkdir" || - Name == "mktime") { - if (FTy->getNumParams() == 0 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - } - break; - case 'r': - if (Name == "realloc") { - if (FTy->getNumParams() != 2 || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getReturnType()->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotAlias(F, 0); - setDoesNotCapture(F, 1); - } else if (Name == "read") { - if (FTy->getNumParams() != 3 || - !FTy->getParamType(1)->isPointerTy()) - continue; - // May throw; "read" is a valid pthread cancellation point. - setDoesNotCapture(F, 2); - } else if (Name == "rmdir" || - Name == "rewind" || - Name == "remove" || - Name == "realpath") { - if (FTy->getNumParams() < 1 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - } else if (Name == "rename" || - Name == "readlink") { - if (FTy->getNumParams() < 2 || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - setDoesNotCapture(F, 2); - } - break; - case 'w': - if (Name == "write") { - if (FTy->getNumParams() != 3 || - !FTy->getParamType(1)->isPointerTy()) - continue; - // May throw; "write" is a valid pthread cancellation point. - setDoesNotCapture(F, 2); - } - break; - case 'b': - if (Name == "bcopy") { - if (FTy->getNumParams() != 3 || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - setDoesNotCapture(F, 2); - } else if (Name == "bcmp") { - if (FTy->getNumParams() != 3 || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setOnlyReadsMemory(F); - setDoesNotCapture(F, 1); - setDoesNotCapture(F, 2); - } else if (Name == "bzero") { - if (FTy->getNumParams() != 2 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - } - break; - case 'c': - if (Name == "calloc") { - if (FTy->getNumParams() != 2 || - !FTy->getReturnType()->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotAlias(F, 0); - } else if (Name == "chmod" || - Name == "chown" || - Name == "ctermid" || - Name == "clearerr" || - Name == "closedir") { - if (FTy->getNumParams() == 0 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - } - break; - case 'a': - if (Name == "atoi" || - Name == "atol" || - Name == "atof" || - Name == "atoll") { - if (FTy->getNumParams() != 1 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setOnlyReadsMemory(F); - setDoesNotCapture(F, 1); - } else if (Name == "access") { - if (FTy->getNumParams() != 2 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - } - break; - case 'f': - if (Name == "fopen") { - if (FTy->getNumParams() != 2 || - !FTy->getReturnType()->isPointerTy() || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotAlias(F, 0); - setDoesNotCapture(F, 1); - setDoesNotCapture(F, 2); - } else if (Name == "fdopen") { - if (FTy->getNumParams() != 2 || - !FTy->getReturnType()->isPointerTy() || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotAlias(F, 0); - setDoesNotCapture(F, 2); - } else if (Name == "feof" || - Name == "free" || - Name == "fseek" || - Name == "ftell" || - Name == "fgetc" || - Name == "fseeko" || - Name == "ftello" || - Name == "fileno" || - Name == "fflush" || - Name == "fclose" || - Name == "fsetpos" || - Name == "flockfile" || - Name == "funlockfile" || - Name == "ftrylockfile") { - if (FTy->getNumParams() == 0 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - } else if (Name == "ferror") { - if (FTy->getNumParams() != 1 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - setOnlyReadsMemory(F); - } else if (Name == "fputc" || - Name == "fstat" || - Name == "frexp" || - Name == "frexpf" || - Name == "frexpl" || - Name == "fstatvfs") { - if (FTy->getNumParams() != 2 || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 2); - } else if (Name == "fgets") { - if (FTy->getNumParams() != 3 || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getParamType(2)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 3); - } else if (Name == "fread" || - Name == "fwrite") { - if (FTy->getNumParams() != 4 || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getParamType(3)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - setDoesNotCapture(F, 4); - } else if (Name == "fputs" || - Name == "fscanf" || - Name == "fprintf" || - Name == "fgetpos") { - if (FTy->getNumParams() < 2 || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - setDoesNotCapture(F, 2); - } - break; - case 'g': - if (Name == "getc" || - Name == "getlogin_r" || - Name == "getc_unlocked") { - if (FTy->getNumParams() == 0 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - } else if (Name == "getenv") { - if (FTy->getNumParams() != 1 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setOnlyReadsMemory(F); - setDoesNotCapture(F, 1); - } else if (Name == "gets" || - Name == "getchar") { - setDoesNotThrow(F); - } else if (Name == "getitimer") { - if (FTy->getNumParams() != 2 || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 2); - } else if (Name == "getpwnam") { - if (FTy->getNumParams() != 1 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - } - break; - case 'u': - if (Name == "ungetc") { - if (FTy->getNumParams() != 2 || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 2); - } else if (Name == "uname" || - Name == "unlink" || - Name == "unsetenv") { - if (FTy->getNumParams() != 1 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - } else if (Name == "utime" || - Name == "utimes") { - if (FTy->getNumParams() != 2 || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - setDoesNotCapture(F, 2); - } - break; - case 'p': - if (Name == "putc") { - if (FTy->getNumParams() != 2 || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 2); - } else if (Name == "puts" || - Name == "printf" || - Name == "perror") { - if (FTy->getNumParams() != 1 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - } else if (Name == "pread" || - Name == "pwrite") { - if (FTy->getNumParams() != 4 || - !FTy->getParamType(1)->isPointerTy()) - continue; - // May throw; these are valid pthread cancellation points. - setDoesNotCapture(F, 2); - } else if (Name == "putchar") { - setDoesNotThrow(F); - } else if (Name == "popen") { - if (FTy->getNumParams() != 2 || - !FTy->getReturnType()->isPointerTy() || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotAlias(F, 0); - setDoesNotCapture(F, 1); - setDoesNotCapture(F, 2); - } else if (Name == "pclose") { - if (FTy->getNumParams() != 1 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - } - break; - case 'v': - if (Name == "vscanf") { - if (FTy->getNumParams() != 2 || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - } else if (Name == "vsscanf" || - Name == "vfscanf") { - if (FTy->getNumParams() != 3 || - !FTy->getParamType(1)->isPointerTy() || - !FTy->getParamType(2)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - setDoesNotCapture(F, 2); - } else if (Name == "valloc") { - if (!FTy->getReturnType()->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotAlias(F, 0); - } else if (Name == "vprintf") { - if (FTy->getNumParams() != 2 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - } else if (Name == "vfprintf" || - Name == "vsprintf") { - if (FTy->getNumParams() != 3 || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - setDoesNotCapture(F, 2); - } else if (Name == "vsnprintf") { - if (FTy->getNumParams() != 4 || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getParamType(2)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - setDoesNotCapture(F, 3); - } - break; - case 'o': - if (Name == "open") { - if (FTy->getNumParams() < 2 || - !FTy->getParamType(0)->isPointerTy()) - continue; - // May throw; "open" is a valid pthread cancellation point. - setDoesNotCapture(F, 1); - } else if (Name == "opendir") { - if (FTy->getNumParams() != 1 || - !FTy->getReturnType()->isPointerTy() || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotAlias(F, 0); - setDoesNotCapture(F, 1); - } - break; - case 't': - if (Name == "tmpfile") { - if (!FTy->getReturnType()->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotAlias(F, 0); - } else if (Name == "times") { - if (FTy->getNumParams() != 1 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - } - break; - case 'h': - if (Name == "htonl" || - Name == "htons") { - setDoesNotThrow(F); - setDoesNotAccessMemory(F); - } - break; - case 'n': - if (Name == "ntohl" || - Name == "ntohs") { - setDoesNotThrow(F); - setDoesNotAccessMemory(F); - } - break; - case 'l': - if (Name == "lstat") { - if (FTy->getNumParams() != 2 || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - setDoesNotCapture(F, 2); - } else if (Name == "lchown") { - if (FTy->getNumParams() != 3 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - } - break; - case 'q': - if (Name == "qsort") { - if (FTy->getNumParams() != 4 || - !FTy->getParamType(3)->isPointerTy()) - continue; - // May throw; places call through function pointer. - setDoesNotCapture(F, 4); - } - break; - case '_': - if (Name == "__strdup" || - Name == "__strndup") { - if (FTy->getNumParams() < 1 || - !FTy->getReturnType()->isPointerTy() || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotAlias(F, 0); - setDoesNotCapture(F, 1); - } else if (Name == "__strtok_r") { - if (FTy->getNumParams() != 3 || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 2); - } else if (Name == "_IO_getc") { - if (FTy->getNumParams() != 1 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - } else if (Name == "_IO_putc") { - if (FTy->getNumParams() != 2 || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 2); - } - break; - case 1: - if (Name == "\1__isoc99_scanf") { - if (FTy->getNumParams() < 1 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - } else if (Name == "\1stat64" || - Name == "\1lstat64" || - Name == "\1statvfs64" || - Name == "\1__isoc99_sscanf") { - if (FTy->getNumParams() < 1 || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - setDoesNotCapture(F, 2); - } else if (Name == "\1fopen64") { - if (FTy->getNumParams() != 2 || - !FTy->getReturnType()->isPointerTy() || - !FTy->getParamType(0)->isPointerTy() || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotAlias(F, 0); - setDoesNotCapture(F, 1); - setDoesNotCapture(F, 2); - } else if (Name == "\1fseeko64" || - Name == "\1ftello64") { - if (FTy->getNumParams() == 0 || - !FTy->getParamType(0)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 1); - } else if (Name == "\1tmpfile64") { - if (!FTy->getReturnType()->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotAlias(F, 0); - } else if (Name == "\1fstat64" || - Name == "\1fstatvfs64") { - if (FTy->getNumParams() != 2 || - !FTy->getParamType(1)->isPointerTy()) - continue; - setDoesNotThrow(F); - setDoesNotCapture(F, 2); - } else if (Name == "\1open64") { - if (FTy->getNumParams() < 2 || - !FTy->getParamType(0)->isPointerTy()) - continue; - // May throw; "open" is a valid pthread cancellation point. - setDoesNotCapture(F, 1); - } - break; - } + if (F.isDeclaration() && F.hasName()) + inferPrototypeAttributes(F); } return Modified; } diff --git a/contrib/llvm/lib/Transforms/Utils/Local.cpp b/contrib/llvm/lib/Transforms/Utils/Local.cpp index 063c76e..3f789fa 100644 --- a/contrib/llvm/lib/Transforms/Utils/Local.cpp +++ b/contrib/llvm/lib/Transforms/Utils/Local.cpp @@ -262,12 +262,13 @@ bool llvm::RecursivelyDeleteTriviallyDeadInstructions(Value *V) { /// areAllUsesEqual - Check whether the uses of a value are all the same. /// This is similar to Instruction::hasOneUse() except this will also return -/// true when there are multiple uses that all refer to the same value. +/// true when there are no uses or multiple uses that all refer to the same +/// value. static bool areAllUsesEqual(Instruction *I) { Value::use_iterator UI = I->use_begin(); Value::use_iterator UE = I->use_end(); if (UI == UE) - return false; + return true; User *TheUse = *UI; for (++UI; UI != UE; ++UI) { @@ -281,31 +282,24 @@ static bool areAllUsesEqual(Instruction *I) { /// dead PHI node, due to being a def-use chain of single-use nodes that /// either forms a cycle or is terminated by a trivially dead instruction, /// delete it. If that makes any of its operands trivially dead, delete them -/// too, recursively. Return true if the PHI node is actually deleted. +/// too, recursively. Return true if a change was made. bool llvm::RecursivelyDeleteDeadPHINode(PHINode *PN) { - // We can remove a PHI if it is on a cycle in the def-use graph - // where each node in the cycle has degree one, i.e. only one use, - // and is an instruction with no side effects. - if (!areAllUsesEqual(PN)) - return false; + SmallPtrSet<Instruction*, 4> Visited; + for (Instruction *I = PN; areAllUsesEqual(I) && !I->mayHaveSideEffects(); + I = cast<Instruction>(*I->use_begin())) { + if (I->use_empty()) + return RecursivelyDeleteTriviallyDeadInstructions(I); - bool Changed = false; - SmallPtrSet<PHINode *, 4> PHIs; - PHIs.insert(PN); - for (Instruction *J = cast<Instruction>(*PN->use_begin()); - areAllUsesEqual(J) && !J->mayHaveSideEffects(); - J = cast<Instruction>(*J->use_begin())) - // If we find a PHI more than once, we're on a cycle that + // If we find an instruction more than once, we're on a cycle that // won't prove fruitful. - if (PHINode *JP = dyn_cast<PHINode>(J)) - if (!PHIs.insert(JP)) { - // Break the cycle and delete the PHI and its operands. - JP->replaceAllUsesWith(UndefValue::get(JP->getType())); - (void)RecursivelyDeleteTriviallyDeadInstructions(JP); - Changed = true; - break; - } - return Changed; + if (!Visited.insert(I)) { + // Break the cycle and delete the instruction and its operands. + I->replaceAllUsesWith(UndefValue::get(I->getType())); + (void)RecursivelyDeleteTriviallyDeadInstructions(I); + return true; + } + } + return false; } /// SimplifyInstructionsInBlock - Scan the specified basic block and try to diff --git a/contrib/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/contrib/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp index e6a4373..7788857 100644 --- a/contrib/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp +++ b/contrib/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp @@ -35,6 +35,7 @@ #include "llvm/Metadata.h" #include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/DebugInfo.h" +#include "llvm/Analysis/DIBuilder.h" #include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/ADT/DenseMap.h" @@ -190,7 +191,7 @@ namespace { /// std::vector<AllocaInst*> Allocas; DominatorTree &DT; - DIFactory *DIF; + DIBuilder *DIB; /// AST - An AliasSetTracker object to update. If null, don't update it. /// @@ -235,9 +236,9 @@ namespace { public: PromoteMem2Reg(const std::vector<AllocaInst*> &A, DominatorTree &dt, AliasSetTracker *ast) - : Allocas(A), DT(dt), DIF(0), AST(ast) {} + : Allocas(A), DT(dt), DIB(0), AST(ast) {} ~PromoteMem2Reg() { - delete DIF; + delete DIB; } void run(); @@ -951,9 +952,9 @@ void PromoteMem2Reg::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, if (!DIVar.Verify()) return; - if (!DIF) - DIF = new DIFactory(*SI->getParent()->getParent()->getParent()); - Instruction *DbgVal = DIF->InsertDbgValueIntrinsic(SI->getOperand(0), 0, + if (!DIB) + DIB = new DIBuilder(*SI->getParent()->getParent()->getParent()); + Instruction *DbgVal = DIB->insertDbgValueIntrinsic(SI->getOperand(0), 0, DIVar, SI); // Propagate any debug metadata from the store onto the dbg.value. diff --git a/contrib/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/contrib/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index fb660db..c670885 100644 --- a/contrib/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/contrib/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -247,6 +247,11 @@ static bool DominatesMergePoint(Value *V, BasicBlock *BB, if (PBB->getFirstNonPHIOrDbg() != I) return false; break; + case Instruction::GetElementPtr: + // GEPs are cheap if all indices are constant. + if (!cast<GetElementPtrInst>(I)->hasAllConstantIndices()) + return false; + break; case Instruction::Add: case Instruction::Sub: case Instruction::And: diff --git a/contrib/llvm/tools/clang/include/clang-c/Index.h b/contrib/llvm/tools/clang/include/clang-c/Index.h index b3b49c7..722f6be 100644 --- a/contrib/llvm/tools/clang/include/clang-c/Index.h +++ b/contrib/llvm/tools/clang/include/clang-c/Index.h @@ -35,7 +35,7 @@ extern "C" { #define CINDEX_LINKAGE #endif -/** \defgroup CINDEX C Interface to Clang +/** \defgroup CINDEX libclang: C Interface to Clang * * The C Interface to Clang provides a relatively small API that exposes * facilities for parsing source code into an abstract syntax tree (AST), diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h index 0e88713..c0eeb5a 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h @@ -115,6 +115,7 @@ class ASTContext { llvm::FoldingSet<PackExpansionType> PackExpansionTypes; mutable llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes; mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes; + mutable llvm::FoldingSet<AutoType> AutoTypes; llvm::FoldingSet<AttributedType> AttributedTypes; mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; @@ -551,11 +552,6 @@ public: return cudaConfigureCallDecl; } - /// This gets the struct used to keep track of pointer to blocks, complete - /// with captured variables. - QualType getBlockParmType(bool BlockHasCopyDispose, - llvm::SmallVectorImpl<const Expr *> &Layout) const; - /// This builds the struct used for __block variables. QualType BuildByRefType(llvm::StringRef DeclName, QualType Ty) const; @@ -1525,7 +1521,6 @@ private: /// \brief A counter used to uniquely identify "blocks". mutable unsigned int UniqueBlockByRefTypeID; - mutable unsigned int UniqueBlockParmTypeID; friend class DeclContext; friend class DeclarationNameTable; diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h b/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h index b659ce7..e153596 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h @@ -145,7 +145,14 @@ namespace clang { /// \returns the equivalent nested-name-specifier in the "to" /// context, or NULL if an error occurred. NestedNameSpecifier *Import(NestedNameSpecifier *FromNNS); - + + /// \brief Import the given nested-name-specifier from the "from" + /// context into the "to" context. + /// + /// \returns the equivalent nested-name-specifier in the "to" + /// context. + NestedNameSpecifierLoc Import(NestedNameSpecifierLoc FromNNS); + /// \brief Import the goven template name from the "from" context into the /// "to" context. TemplateName Import(TemplateName From); diff --git a/contrib/llvm/tools/clang/include/clang/AST/Decl.h b/contrib/llvm/tools/clang/include/clang/AST/Decl.h index ee515da..31cee24 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Decl.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Decl.h @@ -119,6 +119,14 @@ public: return getIdentifier() ? getIdentifier()->getName() : ""; } + llvm::StringRef getMessageUnavailableAttr(bool unavailable) const { + if (!unavailable) + return ""; + if (const UnavailableAttr *UA = getAttr<UnavailableAttr>()) + return UA->getMessage(); + return ""; + } + /// getNameAsString - Get a human-readable name for the declaration, even if /// it is one of the special kinds of names (C++ constructor, Objective-C /// selector, etc). Creating this name requires expensive string @@ -475,10 +483,7 @@ public: /// QualifierInfo - A struct with extended info about a syntactic /// name qualifier, to be used for the case of out-of-line declarations. struct QualifierInfo { - /// NNS - The syntactic name qualifier. - NestedNameSpecifier *NNS; - /// NNSRange - The source range for the qualifier. - SourceRange NNSRange; + NestedNameSpecifierLoc QualifierLoc; /// NumTemplParamLists - The number of template parameter lists /// that were matched against the template-ids occurring into the NNS. unsigned NumTemplParamLists; @@ -487,8 +492,7 @@ struct QualifierInfo { TemplateParameterList** TemplParamLists; /// Default constructor. - QualifierInfo() - : NNS(0), NNSRange(), NumTemplParamLists(0), TemplParamLists(0) {} + QualifierInfo() : QualifierLoc(), NumTemplParamLists(0), TemplParamLists(0) {} /// setTemplateParameterListsInfo - Sets info about matched template /// parameter lists. void setTemplateParameterListsInfo(ASTContext &Context, @@ -545,14 +549,22 @@ public: return SourceRange(getOuterLocStart(), getLocation()); } + /// \brief Retrieve the nested-name-specifier that qualifies the name of this + /// declaration, if it was present in the source. NestedNameSpecifier *getQualifier() const { - return hasExtInfo() ? getExtInfo()->NNS : 0; + return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier() + : 0; } - SourceRange getQualifierRange() const { - return hasExtInfo() ? getExtInfo()->NNSRange : SourceRange(); + + /// \brief Retrieve the nested-name-specifier (with source-location + /// information) that qualifies the name of this declaration, if it was + /// present in the source. + NestedNameSpecifierLoc getQualifierLoc() const { + return hasExtInfo() ? getExtInfo()->QualifierLoc + : NestedNameSpecifierLoc(); } - void setQualifierInfo(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange); + + void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc); unsigned getNumTemplateParameterLists() const { return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0; @@ -652,10 +664,6 @@ private: /// slot of its function, enabling the named return value optimization (NRVO). bool NRVOVariable : 1; - /// \brief Whether this variable has a deduced C++0x auto type for which we're - /// currently parsing the initializer. - bool ParsingAutoInit : 1; - friend class StmtIteratorBase; friend class ASTDeclReader; @@ -665,7 +673,7 @@ protected: StorageClass SCAsWritten) : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(), ThreadSpecified(false), HasCXXDirectInit(false), - ExceptionVar(false), NRVOVariable(false), ParsingAutoInit(false) { + ExceptionVar(false), NRVOVariable(false) { SClass = SC; SClassAsWritten = SCAsWritten; } @@ -889,18 +897,6 @@ public: void setInit(Expr *I); - /// \brief Check whether we are in the process of parsing an initializer - /// needed to deduce the type of this variable. - bool isParsingAutoInit() const { - return ParsingAutoInit; - } - - /// \brief Note whether we are currently parsing an initializer needed to - /// deduce the type of this variable. - void setParsingAutoInit(bool P) { - ParsingAutoInit = P; - } - EvaluatedStmt *EnsureEvaluatedStmt() const { EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>(); if (!Eval) { @@ -1050,16 +1046,18 @@ public: }; class ImplicitParamDecl : public VarDecl { -protected: - ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType Tw) - : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, SC_None, SC_None) { - setImplicit(); - } public: static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T); + + ImplicitParamDecl(DeclContext *DC, SourceLocation loc, + IdentifierInfo *name, QualType type) + : VarDecl(ImplicitParam, DC, loc, name, type, + /*tinfo*/ 0, SC_None, SC_None) { + setImplicit(); + } + // Implement isa/cast/dyncast/etc. static bool classof(const ImplicitParamDecl *D) { return true; } static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2154,14 +2152,22 @@ public: void setTypedefForAnonDecl(TypedefDecl *TDD); + /// \brief Retrieve the nested-name-specifier that qualifies the name of this + /// declaration, if it was present in the source. NestedNameSpecifier *getQualifier() const { - return hasExtInfo() ? getExtInfo()->NNS : 0; + return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier() + : 0; } - SourceRange getQualifierRange() const { - return hasExtInfo() ? getExtInfo()->NNSRange : SourceRange(); + + /// \brief Retrieve the nested-name-specifier (with source-location + /// information) that qualifies the name of this declaration, if it was + /// present in the source. + NestedNameSpecifierLoc getQualifierLoc() const { + return hasExtInfo() ? getExtInfo()->QualifierLoc + : NestedNameSpecifierLoc(); } - void setQualifierInfo(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange); + + void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc); unsigned getNumTemplateParameterLists() const { return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0; diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h index bf249ce..b35d134 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h @@ -299,6 +299,13 @@ public: return const_cast<Decl*>(this)->getDeclContext(); } + /// Finds the innermost non-closure context of this declaration. + /// That is, walk out the DeclContext chain, skipping any blocks. + DeclContext *getNonClosureContext(); + const DeclContext *getNonClosureContext() const { + return const_cast<Decl*>(this)->getNonClosureContext(); + } + TranslationUnitDecl *getTranslationUnitDecl(); const TranslationUnitDecl *getTranslationUnitDecl() const { return const_cast<Decl*>(this)->getTranslationUnitDecl(); @@ -787,6 +794,10 @@ public: return cast<Decl>(this)->getASTContext(); } + bool isClosure() const { + return DeclKind == Decl::Block; + } + bool isFunctionOrMethod() const { switch (DeclKind) { case Decl::Block: diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h index d11ee8f..1656a7e 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h @@ -1741,13 +1741,8 @@ class UsingDirectiveDecl : public NamedDecl { /// SourceLocation - Location of 'namespace' token. SourceLocation NamespaceLoc; - /// \brief The source range that covers the nested-name-specifier - /// preceding the namespace name. - SourceRange QualifierRange; - - /// \brief The nested-name-specifier that precedes the namespace - /// name, if any. - NestedNameSpecifier *Qualifier; + /// \brief The nested-name-specifier that precedes the namespace. + NestedNameSpecifierLoc QualifierLoc; /// NominatedNamespace - Namespace nominated by using-directive. NamedDecl *NominatedNamespace; @@ -1765,25 +1760,24 @@ class UsingDirectiveDecl : public NamedDecl { UsingDirectiveDecl(DeclContext *DC, SourceLocation UsingLoc, SourceLocation NamespcLoc, - SourceRange QualifierRange, - NestedNameSpecifier *Qualifier, + NestedNameSpecifierLoc QualifierLoc, SourceLocation IdentLoc, NamedDecl *Nominated, DeclContext *CommonAncestor) : NamedDecl(UsingDirective, DC, IdentLoc, getName()), UsingLoc(UsingLoc), - NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange), - Qualifier(Qualifier), NominatedNamespace(Nominated), - CommonAncestor(CommonAncestor) { - } + NamespaceLoc(NamespcLoc), QualifierLoc(QualifierLoc), + NominatedNamespace(Nominated), CommonAncestor(CommonAncestor) { } public: - /// \brief Retrieve the source range of the nested-name-specifier - /// that qualifies the namespace name. - SourceRange getQualifierRange() const { return QualifierRange; } - + /// \brief Retrieve the nested-name-specifier that qualifies the + /// name of the namespace, with source-location information. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + /// \brief Retrieve the nested-name-specifier that qualifies the /// name of the namespace. - NestedNameSpecifier *getQualifier() const { return Qualifier; } + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } NamedDecl *getNominatedNamespaceAsWritten() { return NominatedNamespace; } const NamedDecl *getNominatedNamespaceAsWritten() const { @@ -1815,8 +1809,7 @@ public: static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, SourceLocation NamespaceLoc, - SourceRange QualifierRange, - NestedNameSpecifier *Qualifier, + NestedNameSpecifierLoc QualifierLoc, SourceLocation IdentLoc, NamedDecl *Nominated, DeclContext *CommonAncestor); @@ -1844,49 +1837,37 @@ class NamespaceAliasDecl : public NamedDecl { /// \brief The location of the "namespace" keyword. SourceLocation NamespaceLoc; - /// \brief The source range that covers the nested-name-specifier - /// preceding the namespace name. - SourceRange QualifierRange; - - /// \brief The nested-name-specifier that precedes the namespace - /// name, if any. - NestedNameSpecifier *Qualifier; - /// IdentLoc - Location of namespace identifier. Accessed by TargetNameLoc. SourceLocation IdentLoc; - + + /// \brief The nested-name-specifier that precedes the namespace. + NestedNameSpecifierLoc QualifierLoc; + /// Namespace - The Decl that this alias points to. Can either be a /// NamespaceDecl or a NamespaceAliasDecl. NamedDecl *Namespace; NamespaceAliasDecl(DeclContext *DC, SourceLocation NamespaceLoc, SourceLocation AliasLoc, IdentifierInfo *Alias, - SourceRange QualifierRange, - NestedNameSpecifier *Qualifier, + NestedNameSpecifierLoc QualifierLoc, SourceLocation IdentLoc, NamedDecl *Namespace) : NamedDecl(NamespaceAlias, DC, AliasLoc, Alias), - NamespaceLoc(NamespaceLoc), QualifierRange(QualifierRange), - Qualifier(Qualifier), IdentLoc(IdentLoc), Namespace(Namespace) { } + NamespaceLoc(NamespaceLoc), IdentLoc(IdentLoc), + QualifierLoc(QualifierLoc), Namespace(Namespace) { } friend class ASTDeclReader; public: - /// \brief Retrieve the source range of the nested-name-specifier - /// that qualifiers the namespace name. - SourceRange getQualifierRange() const { return QualifierRange; } - - /// \brief Set the source range of the nested-name-specifier that qualifies - /// the namespace name. - void setQualifierRange(SourceRange R) { QualifierRange = R; } - + /// \brief Retrieve the nested-name-specifier that qualifies the + /// name of the namespace, with source-location information. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + /// \brief Retrieve the nested-name-specifier that qualifies the /// name of the namespace. - NestedNameSpecifier *getQualifier() const { return Qualifier; } - - /// \brief Set the nested-name-specifier that qualifies the name of the - /// namespace. - void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } - + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } + /// \brief Retrieve the namespace declaration aliased by this directive. NamespaceDecl *getNamespace() { if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(Namespace)) @@ -1917,8 +1898,7 @@ public: SourceLocation NamespaceLoc, SourceLocation AliasLoc, IdentifierInfo *Alias, - SourceRange QualifierRange, - NestedNameSpecifier *Qualifier, + NestedNameSpecifierLoc QualifierLoc, SourceLocation IdentLoc, NamedDecl *Namespace); @@ -2002,15 +1982,11 @@ public: /// UsingDecl - Represents a C++ using-declaration. For example: /// using someNameSpace::someIdentifier; class UsingDecl : public NamedDecl { - /// \brief The source range that covers the nested-name-specifier - /// preceding the declaration name. - SourceRange NestedNameRange; - /// \brief The source location of the "using" location itself. SourceLocation UsingLocation; - /// \brief Target nested name specifier. - NestedNameSpecifier* TargetNestedName; + /// \brief The nested-name-specifier that precedes the name. + NestedNameSpecifierLoc QualifierLoc; /// DNLoc - Provides source/type location info for the /// declaration name embedded in the ValueDecl base class. @@ -2023,37 +1999,34 @@ class UsingDecl : public NamedDecl { // \brief Has 'typename' keyword. bool IsTypeName; - UsingDecl(DeclContext *DC, SourceRange NNR, - SourceLocation UL, NestedNameSpecifier* TargetNNS, + UsingDecl(DeclContext *DC, SourceLocation UL, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool IsTypeNameArg) : NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()), - NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS), + UsingLocation(UL), QualifierLoc(QualifierLoc), DNLoc(NameInfo.getInfo()), FirstUsingShadow(0),IsTypeName(IsTypeNameArg) { } public: - /// \brief Returns the source range that covers the nested-name-specifier - /// preceding the namespace name. - SourceRange getNestedNameRange() const { return NestedNameRange; } - - /// \brief Set the source range of the nested-name-specifier. - void setNestedNameRange(SourceRange R) { NestedNameRange = R; } - - // FIXME: Naming is inconsistent with other get*Loc functions. /// \brief Returns the source location of the "using" keyword. SourceLocation getUsingLocation() const { return UsingLocation; } /// \brief Set the source location of the 'using' keyword. void setUsingLocation(SourceLocation L) { UsingLocation = L; } - /// \brief Get the target nested name declaration. - NestedNameSpecifier* getTargetNestedNameDecl() const { - return TargetNestedName; + /// \brief Retrieve the nested-name-specifier that qualifies the name, + /// with source-location information. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + /// \brief Retrieve the nested-name-specifier that qualifies the name. + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); } - /// \brief Set the target nested name declaration. - void setTargetNestedNameDecl(NestedNameSpecifier *NNS) { - TargetNestedName = NNS; + /// \brief Retrieve the source range of the nested-name-specifier + /// that qualifies the name. + SourceRange getQualifierRange() const { + return QualifierLoc.getSourceRange(); } DeclarationNameInfo getNameInfo() const { @@ -2119,8 +2092,8 @@ public: void removeShadowDecl(UsingShadowDecl *S); static UsingDecl *Create(ASTContext &C, DeclContext *DC, - SourceRange NNR, SourceLocation UsingL, - NestedNameSpecifier* TargetNNS, + SourceLocation UsingL, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool IsTypeNameArg); @@ -2145,61 +2118,55 @@ public: /// using Base<T>::foo; /// }; class UnresolvedUsingValueDecl : public ValueDecl { - /// \brief The source range that covers the nested-name-specifier - /// preceding the declaration name. - SourceRange TargetNestedNameRange; - /// \brief The source location of the 'using' keyword SourceLocation UsingLocation; - NestedNameSpecifier *TargetNestedNameSpecifier; + /// \brief The nested-name-specifier that precedes the name. + NestedNameSpecifierLoc QualifierLoc; /// DNLoc - Provides source/type location info for the /// declaration name embedded in the ValueDecl base class. DeclarationNameLoc DNLoc; UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty, - SourceLocation UsingLoc, SourceRange TargetNNR, - NestedNameSpecifier *TargetNNS, + SourceLocation UsingLoc, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo) : ValueDecl(UnresolvedUsingValue, DC, NameInfo.getLoc(), NameInfo.getName(), Ty), - TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc), - TargetNestedNameSpecifier(TargetNNS), DNLoc(NameInfo.getInfo()) + UsingLocation(UsingLoc), QualifierLoc(QualifierLoc), + DNLoc(NameInfo.getInfo()) { } public: - /// \brief Returns the source range that covers the nested-name-specifier - /// preceding the namespace name. - SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; } - - /// \brief Set the source range coverting the nested-name-specifier preceding - /// the namespace name. - void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; } - - /// \brief Get target nested name declaration. - NestedNameSpecifier* getTargetNestedNameSpecifier() const { - return TargetNestedNameSpecifier; - } - - /// \brief Set the nested name declaration. - void setTargetNestedNameSpecifier(NestedNameSpecifier* NNS) { - TargetNestedNameSpecifier = NNS; - } - /// \brief Returns the source location of the 'using' keyword. SourceLocation getUsingLoc() const { return UsingLocation; } /// \brief Set the source location of the 'using' keyword. void setUsingLoc(SourceLocation L) { UsingLocation = L; } + /// \brief Retrieve the nested-name-specifier that qualifies the name, + /// with source-location information. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + /// \brief Retrieve the nested-name-specifier that qualifies the name. + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } + + /// \brief Retrieve the source range of the nested-name-specifier + /// that qualifies the name. + SourceRange getQualifierRange() const { + return QualifierLoc.getSourceRange(); + } + DeclarationNameInfo getNameInfo() const { return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); } static UnresolvedUsingValueDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, - SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo); SourceRange getSourceRange() const { @@ -2224,49 +2191,52 @@ public: /// The type associated with a unresolved using typename decl is /// currently always a typename type. class UnresolvedUsingTypenameDecl : public TypeDecl { - /// \brief The source range that covers the nested-name-specifier - /// preceding the declaration name. - SourceRange TargetNestedNameRange; - /// \brief The source location of the 'using' keyword SourceLocation UsingLocation; /// \brief The source location of the 'typename' keyword SourceLocation TypenameLocation; - NestedNameSpecifier *TargetNestedNameSpecifier; + /// \brief The nested-name-specifier that precedes the name. + NestedNameSpecifierLoc QualifierLoc; UnresolvedUsingTypenameDecl(DeclContext *DC, SourceLocation UsingLoc, - SourceLocation TypenameLoc, - SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, - SourceLocation TargetNameLoc, IdentifierInfo *TargetName) + SourceLocation TypenameLoc, + NestedNameSpecifierLoc QualifierLoc, + SourceLocation TargetNameLoc, + IdentifierInfo *TargetName) : TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName), - TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc), - TypenameLocation(TypenameLoc), TargetNestedNameSpecifier(TargetNNS) - { } + UsingLocation(UsingLoc), TypenameLocation(TypenameLoc), + QualifierLoc(QualifierLoc) { } friend class ASTDeclReader; public: - /// \brief Returns the source range that covers the nested-name-specifier - /// preceding the namespace name. - SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; } - - /// \brief Get target nested name declaration. - NestedNameSpecifier* getTargetNestedNameSpecifier() { - return TargetNestedNameSpecifier; - } - /// \brief Returns the source location of the 'using' keyword. SourceLocation getUsingLoc() const { return UsingLocation; } /// \brief Returns the source location of the 'typename' keyword. SourceLocation getTypenameLoc() const { return TypenameLocation; } + /// \brief Retrieve the nested-name-specifier that qualifies the name, + /// with source-location information. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + /// \brief Retrieve the nested-name-specifier that qualifies the name. + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } + + /// \brief Retrieve the source range of the nested-name-specifier + /// that qualifies the name. + SourceRange getQualifierRange() const { + return QualifierLoc.getSourceRange(); + } + + // FIXME: DeclarationNameInfo static UnresolvedUsingTypenameDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, - SourceLocation TypenameLoc, - SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, + SourceLocation TypenameLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TargetNameLoc, DeclarationName TargetName); SourceRange getSourceRange() const { diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h b/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h index cb9e168..63cdac5 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h @@ -39,12 +39,12 @@ public: Decl*& operator[](unsigned i) { assert (i < NumDecls && "Out-of-bounds access."); - return *((Decl**) (this+1)); + return ((Decl**) (this+1))[i]; } Decl* const& operator[](unsigned i) const { assert (i < NumDecls && "Out-of-bounds access."); - return *((Decl* const*) (this+1)); + return ((Decl* const*) (this+1))[i]; } }; diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h index 176c6ba..f41859c 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h +++ b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h @@ -48,6 +48,7 @@ class TemplateParameterList { /// parameter list. unsigned NumParams; +protected: TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc, NamedDecl **Params, unsigned NumParams, SourceLocation RAngleLoc); @@ -107,6 +108,19 @@ public: } }; +/// FixedSizeTemplateParameterList - Stores a list of template parameters for a +/// TemplateDecl and its derived classes. Suitable for creating on the stack. +template<size_t N> +class FixedSizeTemplateParameterList : public TemplateParameterList { + NamedDecl *Params[N]; + +public: + FixedSizeTemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc, + NamedDecl **Params, SourceLocation RAngleLoc) : + TemplateParameterList(TemplateLoc, LAngleLoc, Params, N, RAngleLoc) { + } +}; + /// \brief A template argument list. class TemplateArgumentList { /// \brief The template argument list. @@ -914,6 +928,9 @@ class TemplateTypeParmDecl : public TypeDecl { TypeForDecl = Type.getTypePtrOrNull(); } + /// Sema creates these on the stack during auto type deduction. + friend class Sema; + public: static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, unsigned P, diff --git a/contrib/llvm/tools/clang/include/clang/AST/Expr.h b/contrib/llvm/tools/clang/include/clang/AST/Expr.h index a17205c..95bfad5 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Expr.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Expr.h @@ -1843,9 +1843,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const { - return SourceRange(getCallee()->getLocStart(), RParenLoc); - } + SourceRange getSourceRange() const; static bool classof(const Stmt *T) { return T->getStmtClass() >= firstCallExprConstant && diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h index 85ce962..225db3c 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h +++ b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h @@ -108,8 +108,6 @@ public: /// FIXME: Returns 0 for member pointer call exprs. CXXRecordDecl *getRecordDecl(); - SourceRange getSourceRange() const; - static bool classof(const Stmt *T) { return T->getStmtClass() == CXXMemberCallExprClass; } @@ -1333,13 +1331,9 @@ class CXXPseudoDestructorExpr : public Expr { /// \brief The location of the '.' or '->' operator. SourceLocation OperatorLoc; - + /// \brief The nested-name-specifier that follows the operator, if present. - NestedNameSpecifier *Qualifier; - - /// \brief The source range that covers the nested-name-specifier, if - /// present. - SourceRange QualifierRange; + NestedNameSpecifierLoc QualifierLoc; /// \brief The type that precedes the '::' in a qualified pseudo-destructor /// expression. @@ -1356,11 +1350,12 @@ class CXXPseudoDestructorExpr : public Expr { /// resolve the name. PseudoDestructorTypeStorage DestroyedType; + friend class ASTStmtReader; + public: CXXPseudoDestructorExpr(ASTContext &Context, Expr *Base, bool isArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, TypeSourceInfo *ScopeType, SourceLocation ColonColonLoc, SourceLocation TildeLoc, @@ -1368,36 +1363,32 @@ public: explicit CXXPseudoDestructorExpr(EmptyShell Shell) : Expr(CXXPseudoDestructorExprClass, Shell), - Base(0), IsArrow(false), Qualifier(0), ScopeType(0) { } + Base(0), IsArrow(false), QualifierLoc(), ScopeType(0) { } - void setBase(Expr *E) { Base = E; } Expr *getBase() const { return cast<Expr>(Base); } /// \brief Determines whether this member expression actually had /// a C++ nested-name-specifier prior to the name of the member, e.g., /// x->Base::foo. - bool hasQualifier() const { return Qualifier != 0; } - - /// \brief If the member name was qualified, retrieves the source range of - /// the nested-name-specifier that precedes the member name. Otherwise, - /// returns an empty source range. - SourceRange getQualifierRange() const { return QualifierRange; } - void setQualifierRange(SourceRange R) { QualifierRange = R; } + bool hasQualifier() const { return QualifierLoc; } + /// \brief Retrieves the nested-name-specifier that qualifies the type name, + /// with source-location information. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + /// \brief If the member name was qualified, retrieves the /// nested-name-specifier that precedes the member name. Otherwise, returns /// NULL. - NestedNameSpecifier *getQualifier() const { return Qualifier; } - void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } /// \brief Determine whether this pseudo-destructor expression was written /// using an '->' (otherwise, it used a '.'). bool isArrow() const { return IsArrow; } - void setArrow(bool A) { IsArrow = A; } /// \brief Retrieve the location of the '.' or '->' operator. SourceLocation getOperatorLoc() const { return OperatorLoc; } - void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } /// \brief Retrieve the scope type in a qualified pseudo-destructor /// expression. @@ -1409,16 +1400,13 @@ public: /// nested-name-specifier. It is stored as the "scope type" of the pseudo- /// destructor expression. TypeSourceInfo *getScopeTypeInfo() const { return ScopeType; } - void setScopeTypeInfo(TypeSourceInfo *Info) { ScopeType = Info; } /// \brief Retrieve the location of the '::' in a qualified pseudo-destructor /// expression. SourceLocation getColonColonLoc() const { return ColonColonLoc; } - void setColonColonLoc(SourceLocation L) { ColonColonLoc = L; } /// \brief Retrieve the location of the '~'. SourceLocation getTildeLoc() const { return TildeLoc; } - void setTildeLoc(SourceLocation L) { TildeLoc = L; } /// \brief Retrieve the source location information for the type /// being destroyed. @@ -1885,30 +1873,24 @@ public: /// ("value"). Such expressions will instantiate to a DeclRefExpr once the /// declaration can be found. class DependentScopeDeclRefExpr : public Expr { - /// The name of the entity we will be referencing. - DeclarationNameInfo NameInfo; - - /// QualifierRange - The source range that covers the - /// nested-name-specifier. - SourceRange QualifierRange; - /// \brief The nested-name-specifier that qualifies this unresolved /// declaration name. - NestedNameSpecifier *Qualifier; + NestedNameSpecifierLoc QualifierLoc; + + /// The name of the entity we will be referencing. + DeclarationNameInfo NameInfo; /// \brief Whether the name includes explicit template arguments. bool HasExplicitTemplateArgs; DependentScopeDeclRefExpr(QualType T, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *Args); public: static DependentScopeDeclRefExpr *Create(ASTContext &C, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs = 0); @@ -1918,24 +1900,23 @@ public: /// \brief Retrieve the name that this expression refers to. const DeclarationNameInfo &getNameInfo() const { return NameInfo; } - void setNameInfo(const DeclarationNameInfo &N) { NameInfo = N; } /// \brief Retrieve the name that this expression refers to. DeclarationName getDeclName() const { return NameInfo.getName(); } - void setDeclName(DeclarationName N) { NameInfo.setName(N); } /// \brief Retrieve the location of the name within the expression. SourceLocation getLocation() const { return NameInfo.getLoc(); } - void setLocation(SourceLocation L) { NameInfo.setLoc(L); } - - /// \brief Retrieve the source range of the nested-name-specifier. - SourceRange getQualifierRange() const { return QualifierRange; } - void setQualifierRange(SourceRange R) { QualifierRange = R; } + /// \brief Retrieve the nested-name-specifier that qualifies the + /// name, with source location information. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + /// \brief Retrieve the nested-name-specifier that qualifies this /// declaration. - NestedNameSpecifier *getQualifier() const { return Qualifier; } - void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } /// Determines whether this lookup had explicit template arguments. bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; } @@ -1986,7 +1967,7 @@ public: } SourceRange getSourceRange() const { - SourceRange Range(QualifierRange.getBegin(), getLocation()); + SourceRange Range(QualifierLoc.getBeginLoc(), getLocation()); if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); return Range; diff --git a/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h index 99cc1f2..024bf40 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h +++ b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h @@ -25,10 +25,12 @@ namespace llvm { namespace clang { class ASTContext; +class NamespaceAliasDecl; class NamespaceDecl; class IdentifierInfo; struct PrintingPolicy; class Type; +class TypeLoc; class LangOptions; /// \brief Represents a C++ nested name specifier, such as @@ -41,13 +43,22 @@ class LangOptions; /// (for dependent names), or the global specifier ('::', must be the /// first specifier). class NestedNameSpecifier : public llvm::FoldingSetNode { + + /// \brief Enumeration describing + enum StoredSpecifierKind { + StoredIdentifier = 0, + StoredNamespaceOrAlias = 1, + StoredTypeSpec = 2, + StoredTypeSpecWithTemplate = 3 + }; + /// \brief The nested name specifier that precedes this nested name /// specifier. /// /// The pointer is the nested-name-specifier that precedes this /// one. The integer stores one of the first four values of type /// SpecifierKind. - llvm::PointerIntPair<NestedNameSpecifier *, 2> Prefix; + llvm::PointerIntPair<NestedNameSpecifier *, 2, StoredSpecifierKind> Prefix; /// \brief The last component in the nested name specifier, which /// can be an identifier, a declaration, or a type. @@ -63,21 +74,23 @@ public: /// specifier. enum SpecifierKind { /// \brief An identifier, stored as an IdentifierInfo*. - Identifier = 0, - /// \brief A namespace, stored as a Namespace*. - Namespace = 1, + Identifier, + /// \brief A namespace, stored as a NamespaceDecl*. + Namespace, + /// \brief A namespace alias, stored as a NamespaceAliasDecl*. + NamespaceAlias, /// \brief A type, stored as a Type*. - TypeSpec = 2, + TypeSpec, /// \brief A type that was preceded by the 'template' keyword, /// stored as a Type*. - TypeSpecWithTemplate = 3, + TypeSpecWithTemplate, /// \brief The global specifier '::'. There is no stored value. - Global = 4 + Global }; private: /// \brief Builds the global specifier. - NestedNameSpecifier() : Prefix(0, 0), Specifier(0) { } + NestedNameSpecifier() : Prefix(0, StoredIdentifier), Specifier(0) { } /// \brief Copy constructor used internally to clone nested name /// specifiers. @@ -108,6 +121,11 @@ public: NestedNameSpecifier *Prefix, NamespaceDecl *NS); + /// \brief Builds a nested name specifier that names a namespace alias. + static NestedNameSpecifier *Create(const ASTContext &Context, + NestedNameSpecifier *Prefix, + NamespaceAliasDecl *Alias); + /// \brief Builds a nested name specifier that names a type. static NestedNameSpecifier *Create(const ASTContext &Context, NestedNameSpecifier *Prefix, @@ -136,16 +154,12 @@ public: NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); } /// \brief Determine what kind of nested name specifier is stored. - SpecifierKind getKind() const { - if (Specifier == 0) - return Global; - return (SpecifierKind)Prefix.getInt(); - } + SpecifierKind getKind() const; /// \brief Retrieve the identifier stored in this nested name /// specifier. IdentifierInfo *getAsIdentifier() const { - if (Prefix.getInt() == Identifier) + if (Prefix.getInt() == StoredIdentifier) return (IdentifierInfo *)Specifier; return 0; @@ -153,17 +167,16 @@ public: /// \brief Retrieve the namespace stored in this nested name /// specifier. - NamespaceDecl *getAsNamespace() const { - if (Prefix.getInt() == Namespace) - return (NamespaceDecl *)Specifier; + NamespaceDecl *getAsNamespace() const; - return 0; - } + /// \brief Retrieve the namespace alias stored in this nested name + /// specifier. + NamespaceAliasDecl *getAsNamespaceAlias() const; /// \brief Retrieve the type stored in this nested name specifier. const Type *getAsType() const { - if (Prefix.getInt() == TypeSpec || - Prefix.getInt() == TypeSpecWithTemplate) + if (Prefix.getInt() == StoredTypeSpec || + Prefix.getInt() == StoredTypeSpecWithTemplate) return (const Type *)Specifier; return 0; @@ -191,6 +204,114 @@ public: void dump(const LangOptions &LO); }; +/// \brief A C++ nested-name-specifier augmented with source location +/// information. +class NestedNameSpecifierLoc { + NestedNameSpecifier *Qualifier; + void *Data; + + /// \brief Determines the data length for the last component in the + /// given nested-name-specifier. + static unsigned getLocalDataLength(NestedNameSpecifier *Qualifier); + + /// \brief Determines the data length for the entire + /// nested-name-specifier. + static unsigned getDataLength(NestedNameSpecifier *Qualifier); + +public: + /// \brief Construct an empty nested-name-specifier. + NestedNameSpecifierLoc() : Qualifier(0), Data(0) { } + + /// \brief Construct a nested-name-specifier with source location information + /// from + NestedNameSpecifierLoc(NestedNameSpecifier *Qualifier, void *Data) + : Qualifier(Qualifier), Data(Data) { } + + /// \brief Evalutes true when this nested-name-specifier location is + /// non-empty. + operator bool() const { return Qualifier; } + + /// \brief Retrieve the nested-name-specifier to which this instance + /// refers. + NestedNameSpecifier *getNestedNameSpecifier() const { + return Qualifier; + } + + /// \brief Retrieve the opaque pointer that refers to source-location data. + void *getOpaqueData() const { return Data; } + + /// \brief Retrieve the source range covering the entirety of this + /// nested-name-specifier. + /// + /// For example, if this instance refers to a nested-name-specifier + /// \c ::std::vector<int>::, the returned source range would cover + /// from the initial '::' to the last '::'. + SourceRange getSourceRange() const; + + /// \brief Retrieve the source range covering just the last part of + /// this nested-name-specifier, not including the prefix. + /// + /// For example, if this instance refers to a nested-name-specifier + /// \c ::std::vector<int>::, the returned source range would cover + /// from "vector" to the last '::'. + SourceRange getLocalSourceRange() const; + + /// \brief Retrieve the location of the beginning of this + /// nested-name-specifier. + SourceLocation getBeginLoc() const { + return getSourceRange().getBegin(); + } + + /// \brief Retrieve the location of the end of this + /// nested-name-specifier. + SourceLocation getEndLoc() const { + return getSourceRange().getEnd(); + } + + /// \brief Retrieve the location of the beginning of this + /// component of the nested-name-specifier. + SourceLocation getLocalBeginLoc() const { + return getLocalSourceRange().getBegin(); + } + + /// \brief Retrieve the location of the end of this component of the + /// nested-name-specifier. + SourceLocation getLocalEndLoc() const { + return getLocalSourceRange().getEnd(); + } + + /// \brief Return the prefix of this nested-name-specifier. + /// + /// For example, if this instance refers to a nested-name-specifier + /// \c ::std::vector<int>::, the prefix is \c ::std::. Note that the + /// returned prefix may be empty, if this is the first component of + /// the nested-name-specifier. + NestedNameSpecifierLoc getPrefix() const { + if (!Qualifier) + return *this; + + return NestedNameSpecifierLoc(Qualifier->getPrefix(), Data); + } + + /// \brief For a nested-name-specifier that refers to a type, + /// retrieve the type with source-location information. + TypeLoc getTypeLoc() const; + + /// \brief Determines the data length for the entire + /// nested-name-specifier. + unsigned getDataLength() const { return getDataLength(Qualifier); } + + friend bool operator==(NestedNameSpecifierLoc X, + NestedNameSpecifierLoc Y) { + return X.Qualifier == Y.Qualifier && X.Data == Y.Data; + } + + friend bool operator!=(NestedNameSpecifierLoc X, + NestedNameSpecifierLoc Y) { + return !(X == Y); + } +}; + /// Insertion operator for diagnostics. This allows sending NestedNameSpecifiers /// into a diagnostic with <<. inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, diff --git a/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h index 921b799..e85b6dc 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h @@ -181,6 +181,12 @@ public: /// \returns false if the visitation was terminated early, true otherwise. bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS); + /// \brief Recursively visit a C++ nested-name-specifier with location + /// information. + /// + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); + /// \brief Recursively visit a template name and dispatch to the /// appropriate method. /// @@ -502,6 +508,7 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier( switch (NNS->getKind()) { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: return true; @@ -514,6 +521,31 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier( } template<typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc( + NestedNameSpecifierLoc NNS) { + if (!NNS) + return true; + + if (NestedNameSpecifierLoc Prefix = NNS.getPrefix()) + TRY_TO(TraverseNestedNameSpecifierLoc(Prefix)); + + switch (NNS.getNestedNameSpecifier()->getKind()) { + case NestedNameSpecifier::Identifier: + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: + case NestedNameSpecifier::Global: + return true; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + TRY_TO(TraverseTypeLoc(NNS.getTypeLoc())); + break; + } + + return true; +} + +template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) { if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) TRY_TO(TraverseNestedNameSpecifier(DTN->getQualifier())); @@ -1142,11 +1174,11 @@ DEF_TRAVERSE_DECL(ObjCPropertyDecl, { }) DEF_TRAVERSE_DECL(UsingDecl, { - TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameDecl())); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); }) DEF_TRAVERSE_DECL(UsingDirectiveDecl, { - TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); }) DEF_TRAVERSE_DECL(UsingShadowDecl, { }) @@ -1312,7 +1344,7 @@ DEF_TRAVERSE_DECL(TypedefDecl, { DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, { // A dependent using declaration which was marked with 'typename'. // template<class T> class A : public B<T> { using typename B<T>::foo; }; - TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameSpecifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); // We shouldn't traverse D->getTypeForDecl(); it's a result of // declaring the type, not something that was written in the // source. @@ -1425,7 +1457,7 @@ DEF_TRAVERSE_DECL(EnumConstantDecl, { DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, { // Like UnresolvedUsingTypenameDecl, but without the 'typename': // template <class T> Class A : public Base<T> { using Base<T>::foo; }; - TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameSpecifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); }) DEF_TRAVERSE_DECL(IndirectFieldDecl, {}) @@ -1660,20 +1692,18 @@ DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, { }) DEF_TRAVERSE_STMT(DeclRefExpr, { + TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); TRY_TO(TraverseTemplateArgumentLocsHelper( S->getTemplateArgs(), S->getNumTemplateArgs())); - // FIXME: Should we be recursing on the qualifier? - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); }) DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, { - // FIXME: Should we be recursing on these two things? + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (S->hasExplicitTemplateArgs()) { TRY_TO(TraverseTemplateArgumentLocsHelper( S->getExplicitTemplateArgs().getTemplateArgs(), S->getNumTemplateArgs())); } - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); }) DEF_TRAVERSE_STMT(MemberExpr, { @@ -1814,7 +1844,7 @@ DEF_TRAVERSE_STMT(CXXDeleteExpr, { }) DEF_TRAVERSE_STMT(ExprWithCleanups, { }) DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { }) DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo()) TRY_TO(TraverseTypeLoc(ScopeInfo->getTypeLoc())); if (TypeSourceInfo *DestroyedTypeInfo = S->getDestroyedTypeInfo()) diff --git a/contrib/llvm/tools/clang/include/clang/AST/Stmt.h b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h index 7ede9ce..d1f7d66 100644 --- a/contrib/llvm/tools/clang/include/clang/AST/Stmt.h +++ b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h @@ -1328,7 +1328,8 @@ public: } Expr *getInputExpr(unsigned i); - + void setInputExpr(unsigned i, Expr *E); + const Expr *getInputExpr(unsigned i) const { return const_cast<AsmStmt*>(this)->getInputExpr(i); } diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h new file mode 100644 index 0000000..72f644a --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h @@ -0,0 +1,49 @@ +//==- CFGReachabilityAnalysis.h - Basic reachability analysis ----*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a flow-sensitive, (mostly) path-insensitive reachability +// analysis based on Clang's CFGs. Clients can query if a given basic block +// is reachable within the CFG. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_ANALYSIS_CFG_REACHABILITY +#define CLANG_ANALYSIS_CFG_REACHABILITY + +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" + +namespace clang { + +class CFG; +class CFGBlock; + +// A class that performs reachability queries for CFGBlocks. Several internal +// checks in this checker require reachability information. The requests all +// tend to have a common destination, so we lazily do a predecessor search +// from the destination node and cache the results to prevent work +// duplication. +class CFGReachabilityAnalysis { + typedef llvm::BitVector ReachableSet; + typedef llvm::DenseMap<unsigned, ReachableSet> ReachableMap; + ReachableSet analyzed; + ReachableMap reachable; +public: + CFGReachabilityAnalysis(const CFG &cfg); + + /// Returns true if the block 'Dst' can be reached from block 'Src'. + bool isReachable(const CFGBlock *Src, const CFGBlock *Dst); + +private: + void mapReachability(const CFGBlock *Dst); +}; + +} + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h index 2ecbfdc..8514514 100644 --- a/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h +++ b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h @@ -29,6 +29,8 @@ class Decl; class Stmt; class CFG; class CFGBlock; +class CFGReachabilityAnalysis; +class CFGStmtMap; class LiveVariables; class ParentMap; class PseudoConstantAnalysis; @@ -48,11 +50,13 @@ class AnalysisContext { // AnalysisContext owns the following data. CFG *cfg, *completeCFG; + CFGStmtMap *cfgStmtMap; bool builtCFG, builtCompleteCFG; LiveVariables *liveness; LiveVariables *relaxedLiveness; ParentMap *PM; PseudoConstantAnalysis *PCA; + CFGReachabilityAnalysis *CFA; llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars; llvm::BumpPtrAllocator A; bool UseUnoptimizedCFG; @@ -65,9 +69,9 @@ public: bool addehedges = false, bool addImplicitDtors = false, bool addInitializers = false) - : D(d), TU(tu), cfg(0), completeCFG(0), + : D(d), TU(tu), cfg(0), completeCFG(0), cfgStmtMap(0), builtCFG(false), builtCompleteCFG(false), - liveness(0), relaxedLiveness(0), PM(0), PCA(0), + liveness(0), relaxedLiveness(0), PM(0), PCA(0), CFA(0), ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG), AddEHEdges(addehedges), AddImplicitDtors(addImplicitDtors), AddInitializers(addInitializers) {} @@ -91,7 +95,11 @@ public: Stmt *getBody(); CFG *getCFG(); + + CFGStmtMap *getCFGStmtMap(); + CFGReachabilityAnalysis *getCFGReachablityAnalysis(); + /// Return a version of the CFG without any edges pruned. CFG *getUnoptimizedCFG(); diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def index 7d270ad..b73ac1f 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def +++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def @@ -60,6 +60,7 @@ // n -> nothrow // r -> noreturn // c -> const +// t -> signature is meaningless, use custom typechecking // F -> this is a libc/libm function with a '__builtin_' prefix added. // f -> this is a libc/libm function without the '__builtin_' prefix. It can // be followed by ':headername:' to state which header this function @@ -383,8 +384,8 @@ BUILTIN(__builtin_bswap32, "UiUi", "nc") BUILTIN(__builtin_bswap64, "ULLiULLi", "nc") // Random GCC builtins -BUILTIN(__builtin_constant_p, "i.", "nc") -BUILTIN(__builtin_classify_type, "i.", "nc") +BUILTIN(__builtin_constant_p, "i.", "nct") +BUILTIN(__builtin_classify_type, "i.", "nct") BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc") BUILTIN(__builtin___NSStringMakeConstantString, "FC*cC*", "nc") BUILTIN(__builtin_va_start, "vA.", "n") diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h index 4df4c8f..0d17e03 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h @@ -117,6 +117,11 @@ public: return strchr(GetRecord(ID).Attributes, 'f') != 0; } + /// \brief Determines whether this builtin has custom typechecking. + bool hasCustomTypechecking(unsigned ID) const { + return strchr(GetRecord(ID).Attributes, 't') != 0; + } + /// \brief Completely forget that the given ID was ever considered a builtin, /// e.g., because the user provided a conflicting signature. void ForgetBuiltin(unsigned ID, IdentifierTable &Table); diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h index 19e7c91..3fc60d1 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h @@ -474,8 +474,9 @@ public: /// /// \param Loc The source location we are interested in finding out the /// diagnostic state. Can be null in order to query the latest state. - Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc) const { - return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this); + Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, + diag::Mapping *mapping = 0) const { + return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this, mapping); } /// Report - Issue the message to the client. @c DiagID is a member of the diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td index 5f9f4a7..3070676 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -177,12 +177,15 @@ def warn_pch_elide_constructors : Error< def warn_pch_exceptions : Error< "exceptions were %select{disabled|enabled}0 in PCH file but " "are currently %select{disabled|enabled}1">; -def warn_pch_sjlj_exceptions : Error< - "sjlj-exceptions were %select{disabled|enabled}0 in PCH file but " - "are currently %select{disabled|enabled}1">; def warn_pch_objc_exceptions : Error< "Objective-C exceptions were %select{disabled|enabled}0 in PCH file but " "are currently %select{disabled|enabled}1">; +def warn_pch_cxx_exceptions : Error< + "C++ exceptions were %select{disabled|enabled}0 in PCH file but " + "are currently %select{disabled|enabled}1">; +def warn_pch_sjlj_exceptions : Error< + "sjlj-exceptions were %select{disabled|enabled}0 in PCH file but " + "are currently %select{disabled|enabled}1">; def warn_pch_objc_runtime : Error< "PCH file was compiled with the %select{NeXT|GNU}0 runtime but the " "%select{NeXT|GNU}1 runtime is selected">; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td index d4377c9..412fb58 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td @@ -198,9 +198,11 @@ def Unused : DiagGroup<"unused", DiagCategory<"Unused Entity Issue">; // Format settings. -def Format : DiagGroup<"format", [FormatExtraArgs, FormatZeroLength, NonNull]>, +def FormatSecurity : DiagGroup<"format-security">; +def Format : DiagGroup<"format", + [FormatExtraArgs, FormatZeroLength, NonNull, + FormatSecurity]>, DiagCategory<"Format String Issue">; -def FormatSecurity : DiagGroup<"format-security", [Format]>; def FormatNonLiteral : DiagGroup<"format-nonliteral", [FormatSecurity]>; def FormatY2K : DiagGroup<"format-y2k", [Format]>; def Format2 : DiagGroup<"format=2", diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h index b463805..2b03cae 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h @@ -188,14 +188,16 @@ private: /// \param Loc The source location we are interested in finding out the /// diagnostic state. Can be null in order to query the latest state. DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, - const Diagnostic &Diag) const; + const Diagnostic &Diag, + diag::Mapping *mapping = 0) const; /// getDiagnosticLevel - This is an internal implementation helper used when /// DiagClass is already known. DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID, unsigned DiagClass, SourceLocation Loc, - const Diagnostic &Diag) const; + const Diagnostic &Diag, + diag::Mapping *mapping = 0) const; /// ProcessDiag - This is the method used to report a diagnostic that is /// finally fully formed. diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td index 9d7ec9d..9a68af9 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -28,6 +28,10 @@ def ext_extra_struct_semi : Extension< def ext_extra_ivar_semi : Extension< "extra ';' inside instance variable list">; +def auto_storage_class : ExtWarn< + "'auto' storage class specifier is redundant and will be " + "removed in future releases">; + def ext_duplicate_declspec : Extension<"duplicate '%0' declaration specifier">; def ext_plain_complex : ExtWarn< "plain '_Complex' requires a type specifier; assuming '_Complex double'">; @@ -57,6 +61,11 @@ def ext_enumerator_list_comma : Extension< "feature">; def err_enumerator_list_missing_comma : Error< "missing ',' between enumerators">; +def err_enumerator_unnamed_no_def : Error< + "unnamed enumeration must be a definition">; +def ext_ms_enum_fixed_underlying_type : Extension< + "enumeration types with a fixed underlying type are a Microsoft extension">, + InGroup<Microsoft>; def ext_gnu_indirect_goto : Extension< "use of GNU indirect-goto extension">, InGroup<GNU>; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td index 2e7f274..a9fb2da 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -351,12 +351,18 @@ def note_required_for_protocol_at : def warn_conflicting_ret_types : Warning< "conflicting return type in implementation of %0: %1 vs %2">; +def warn_conflicting_ret_type_modifiers : Warning< + "conflicting distributed object modifiers on return type " + "in implementation of %0">; def warn_non_covariant_ret_types : Warning< "conflicting return type in implementation of %0: %1 vs %2">, InGroup<DiagGroup<"method-signatures">>, DefaultIgnore; def warn_conflicting_param_types : Warning< "conflicting parameter types in implementation of %0: %1 vs %2">; +def warn_conflicting_param_modifiers : Warning< + "conflicting distributed object modifiers on parameter type " + "in implementation of %0">; def warn_non_contravariant_param_types : Warning< "conflicting parameter types in implementation of %0: %1 vs %2">, InGroup<DiagGroup<"method-signatures">>, DefaultIgnore; @@ -898,7 +904,8 @@ def err_new_array_of_auto : Error< def err_auto_not_allowed : Error< "'auto' not allowed %select{in function prototype|in struct member" "|in union member|in class member|in exception declaration" - "|in template parameter|in block literal|in template argument|here}0">; + "|in template parameter|in block literal|in template argument" + "|in typedef|in function return type|here}0">; def err_auto_var_requires_init : Error< "declaration of variable %0 with type %1 requires an initializer">; def err_auto_new_requires_ctor_arg : Error< @@ -911,6 +918,8 @@ def err_auto_missing_trailing_return : Error< "'auto' return without trailing return type">; def err_trailing_return_without_auto : Error< "function with trailing return type must specify return type 'auto', not %0">; +def err_trailing_return_in_parens : Error< + "trailing return type may not be nested within parentheses">; def err_auto_var_deduction_failure : Error< "variable %0 with type %1 has incompatible initializer of type %2">; def err_auto_new_deduction_failure : Error< @@ -1145,6 +1154,9 @@ def warn_impcast_literal_float_to_integer : Warning< "implicit conversion turns literal floating-point number into integer: " "%0 to %1">, InGroup<DiagGroup<"literal-conversion">>, DefaultIgnore; +def warn_impcast_different_enum_types : Warning< + "implicit conversion from enumeration type %0 to different enumeration type " + "%1">, InGroup<DiagGroup<"conversion">>; def warn_cast_align : Warning< "cast from %0 to %1 increases required alignment from %2 to %3">, @@ -1299,11 +1311,11 @@ def err_ovl_no_viable_member_function_in_call : Error< def err_ovl_ambiguous_call : Error< "call to %0 is ambiguous">; def err_ovl_deleted_call : Error< - "call to %select{unavailable|deleted}0 function %1">; + "call to %select{unavailable|deleted}0 function %1 %2">; def err_ovl_ambiguous_member_call : Error< "call to member function %0 is ambiguous">; def err_ovl_deleted_member_call : Error< - "call to %select{unavailable|deleted}0 member function %1">; + "call to %select{unavailable|deleted}0 member function %1 %2">; def note_ovl_too_many_candidates : Note< "remaining %0 candidate%s0 omitted; " "pass -fshow-overloads=all to show them">; @@ -1455,7 +1467,7 @@ def err_ovl_ambiguous_oper_binary : Error< "use of overloaded operator '%0' is ambiguous (with operand types %1 and %2)">; def err_ovl_no_viable_oper : Error<"no viable overloaded '%0'">; def err_ovl_deleted_oper : Error< - "overload resolution selected %select{unavailable|deleted}0 operator '%1'">; + "overload resolution selected %select{unavailable|deleted}0 operator '%1' %2">; def err_ovl_no_viable_subscript : Error<"no viable overloaded operator[] for type %0">; def err_ovl_no_oper : @@ -1469,7 +1481,7 @@ def err_ovl_no_viable_object_call : Error< def err_ovl_ambiguous_object_call : Error< "call to object of type %0 is ambiguous">; def err_ovl_deleted_object_call : Error< - "call to %select{unavailable|deleted}0 function call operator in type %1">; + "call to %select{unavailable|deleted}0 function call operator in type %1 %2">; def note_ovl_surrogate_cand : Note<"conversion candidate of type %0">; def err_member_call_without_object : Error< "call to non-static member function without an object argument">; @@ -2015,9 +2027,10 @@ def err_redefinition_extern_inline : Error< // This should eventually be an error. def warn_undefined_internal : Warning< - "%select{function|variable}0 %q1 has internal linkage but is not defined">; + "%select{function|variable}0 %q1 has internal linkage but is not defined">, + DiagGroup<"undefined-internal">; def note_used_here : Note<"used here">; - + def warn_redefinition_of_typedef : Warning< "redefinition of typedef %0 is invalid in C">, InGroup<DiagGroup<"typedef-redefinition"> >, DefaultError; @@ -2328,6 +2341,13 @@ def warn_division_by_zero : Warning<"division by zero is undefined">; def warn_remainder_by_zero : Warning<"remainder by zero is undefined">; def warn_shift_negative : Warning<"shift count is negative">; def warn_shift_gt_typewidth : Warning<"shift count >= width of type">; +def warn_shift_result_gt_typewidth : Warning< + "shift result (%0) requires %1 bits to represent, but %2 only has %3 bits">, + InGroup<DiagGroup<"shift-overflow">>; +def warn_shift_result_overrides_sign_bit : Warning< + "shift result (%0) overrides the sign bit of the shift expression's type " + "(%1) and becomes negative">, + InGroup<DiagGroup<"shift-sign-overflow">>, DefaultIgnore; def warn_precedence_bitwise_rel : Warning< "%0 has lower precedence than %1; %1 will be evaluated first">, @@ -2387,13 +2407,10 @@ def err_typecheck_member_reference_type : Error< def err_typecheck_member_reference_unknown : Error< "cannot refer to member %0 in %1 with '%select{.|->}2'">; def err_member_reference_needs_call : Error< - "base of member reference is an overloaded function; perhaps you meant " - "to call %select{it|the 0-argument overload}0?">; + "base of member reference is %select{a function|an overloaded function}0; " + "perhaps you meant to call it%select{| with no arguments}1?">; def note_member_ref_possible_intended_overload : Note< "possibly valid overload here">; -def err_member_reference_needs_call_zero_arg : Error< - "base of member reference has function type %0; perhaps you meant to call " - "this function with '()'?">; def warn_subscript_is_char : Warning<"array subscript is of type 'char'">, InGroup<CharSubscript>, DefaultIgnore; @@ -2452,6 +2469,13 @@ def err_typecheck_incomplete_array_needs_initializer : Error< def err_array_init_not_init_list : Error< "array initializer must be an initializer " "list%select{| or string literal}0">; +def err_array_init_different_type : Error< + "cannot initialize array of type %0 with array of type %1">; +def err_array_init_non_constant_array : Error< + "cannot initialize array of type %0 with non-constant array of type %1">; +def ext_array_init_copy : Extension< + "initialization of an array of type %0 from a compound literal of type %1 is " + "a GNU extension">; def warn_deprecated_string_literal_conversion : Warning< "conversion from string literal to %0 is deprecated">, InGroup<DeprecatedWritableStr>; def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">; @@ -2950,10 +2974,7 @@ def note_equality_comparison_silence : Note< def warn_synthesized_ivar_access : Warning< "direct access of synthesized ivar by using property access %0">, InGroup<NonfragileAbi2>, DefaultIgnore; -def warn_ivar_variable_conflict : Warning< - "when default property synthesis is on, " - "%0 lookup will access property ivar instead of global variable">, - InGroup<NonfragileAbi2>; + def note_global_declared_at : Note<"global variable declared here">; // assignment related diagnostics (also for argument passing, returning, etc). @@ -3108,6 +3129,8 @@ def err_kern_type_not_void_return : Error< "kernel function type %0 must have void return type">; def err_config_scalar_return : Error< "CUDA special function 'cudaConfigureCall' must have scalar return type">; +def err_kern_call_not_global_function : Error< + "kernel call to non-global function %0">; def err_cannot_pass_objc_interface_to_vararg : Error< diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h index b148943..a9fd25c 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h @@ -53,8 +53,9 @@ public: unsigned LaxVectorConversions : 1; unsigned AltiVec : 1; // Support AltiVec-style vector initializers. unsigned Exceptions : 1; // Support exception handling. - unsigned SjLjExceptions : 1; // Use setjmp-longjump exception handling. unsigned ObjCExceptions : 1; // Support Objective-C exceptions. + unsigned CXXExceptions : 1; // Support C++ exceptions. + unsigned SjLjExceptions : 1; // Use setjmp-longjump exception handling. unsigned RTTI : 1; // Support RTTI information. unsigned MSBitfields : 1; // MS-compatible structure layout @@ -166,8 +167,8 @@ public: NoConstantCFStrings = 0; InlineVisibilityHidden = 0; C99 = Microsoft = Borland = CPlusPlus = CPlusPlus0x = 0; CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0; - Exceptions = SjLjExceptions = Freestanding = NoBuiltin = 0; - ObjCExceptions = 1; + Exceptions = ObjCExceptions = CXXExceptions = SjLjExceptions = 0; + Freestanding = NoBuiltin = 0; MSBitfields = 0; NeXTRuntime = 1; RTTI = 1; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h index d00195b..c636194 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h @@ -75,7 +75,7 @@ public: /// \brief An allocator for Storage objects, which uses a small cache to /// objects, used to reduce malloc()/free() traffic for partial diagnostics. class StorageAllocator { - static const unsigned NumCached = 4; + static const unsigned NumCached = 16; Storage Cached[NumCached]; Storage *FreeList[NumCached]; unsigned NumFreeListEntries; diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h index c0fbd08..b1443da 100644 --- a/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h +++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h @@ -684,10 +684,10 @@ public: /// before calling this method. unsigned getColumnNumber(FileID FID, unsigned FilePos, bool *Invalid = 0) const; - unsigned getSpellingColumnNumber(SourceLocation Loc, - bool *Invalid = 0) const; + unsigned getSpellingColumnNumber(SourceLocation Loc, bool *Invalid = 0) const; unsigned getInstantiationColumnNumber(SourceLocation Loc, bool *Invalid = 0) const; + unsigned getPresumedColumnNumber(SourceLocation Loc, bool *Invalid = 0) const; /// getLineNumber - Given a SourceLocation, return the spelling line number @@ -695,10 +695,10 @@ public: /// line offsets for the MemoryBuffer, so this is not cheap: use only when /// about to emit a diagnostic. unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid = 0) const; - + unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid = 0) const; unsigned getInstantiationLineNumber(SourceLocation Loc, bool *Invalid = 0) const; - unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid = 0) const; + unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid = 0) const; /// Return the filename or buffer identifier of the buffer the location is in. /// Note that this name does not respect #line directives. Use getPresumedLoc diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td index 57107ba..186ba9b 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td +++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td @@ -73,9 +73,6 @@ def analyzer_display_progress : Flag<"-analyzer-display-progress">, HelpText<"Emit verbose output about the analyzer's progress">; def analyzer_experimental_checks : Flag<"-analyzer-experimental-checks">, HelpText<"Use experimental path-sensitive checks">; -def analyzer_experimental_internal_checks : - Flag<"-analyzer-experimental-internal-checks">, - HelpText<"Use new default path-sensitive checks currently in testing">; def analyze_function : Separate<"-analyze-function">, HelpText<"Run analysis on specific function">; def analyze_function_EQ : Joined<"-analyze-function=">, Alias<analyze_function>; @@ -108,6 +105,9 @@ def analyzer_disable_checker : Separate<"-analyzer-disable-checker">, def analyzer_disable_checker_EQ : Joined<"-analyzer-disable-checker=">, Alias<analyzer_disable_checker>; +def analyzer_checker_help : Flag<"-analyzer-checker-help">, + HelpText<"Display the list of analyzer checkers that are available">; + //===----------------------------------------------------------------------===// // CodeGen Options //===----------------------------------------------------------------------===// @@ -418,10 +418,12 @@ def fblocks : Flag<"-fblocks">, def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">; def fexceptions : Flag<"-fexceptions">, HelpText<"Enable support for exception handling">; +def fobjc_exceptions : Flag<"-fobjc-exceptions">, + HelpText<"Enable Objective-C exceptions">; +def fcxx_exceptions : Flag<"-fcxx-exceptions">, + HelpText<"Enable C++ exceptions">; def fsjlj_exceptions : Flag<"-fsjlj-exceptions">, HelpText<"Use SjLj style exceptions">; -def fno_objc_exceptions : Flag<"-fno-objc-exceptions">, - HelpText<"Disable Objective-C exceptions">; def ffreestanding : Flag<"-ffreestanding">, HelpText<"Assert that the compilation takes place in a freestanding environment">; def fformat_extensions : Flag<"-fformat-extensions">, @@ -538,6 +540,8 @@ def idirafter : JoinedOrSeparate<"-idirafter">, MetaVarName<"<directory>">, HelpText<"Add directory to AFTER include search path">; def iquote : JoinedOrSeparate<"-iquote">, MetaVarName<"<directory>">, HelpText<"Add directory to QUOTE include search path">; +def cxx_isystem : JoinedOrSeparate<"-cxx-isystem">, MetaVarName<"<directory>">, + HelpText<"Add directory to the C++ SYSTEM include search path">; def isystem : JoinedOrSeparate<"-isystem">, MetaVarName<"<directory>">, HelpText<"Add directory to SYSTEM include search path">; def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">,MetaVarName<"<directory>">, @@ -552,8 +556,6 @@ def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">, HelpText<"Set directory to include search path with prefix">; def isysroot : JoinedOrSeparate<"-isysroot">, MetaVarName<"<dir>">, HelpText<"Set the system root directory (usually /)">; -def cxx_system_include : Separate<"-cxx-system-include">, - HelpText<"Add a system #include directory for the C++ standard library">; def v : Flag<"-v">, HelpText<"Enable verbose output">; //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Options.td b/contrib/llvm/tools/clang/include/clang/Driver/Options.td index 1a8a150..0faab3b 100644 --- a/contrib/llvm/tools/clang/include/clang/Driver/Options.td +++ b/contrib/llvm/tools/clang/include/clang/Driver/Options.td @@ -208,6 +208,7 @@ def compatibility__version : JoinedOrSeparate<"-compatibility_version">; def coverage : Flag<"-coverage">; def cpp_precomp : Flag<"-cpp-precomp">; def current__version : JoinedOrSeparate<"-current_version">; +def cxx_isystem : JoinedOrSeparate<"-cxx-isystem">, Group<clang_i_Group>; def c : Flag<"-c">, Flags<[DriverOption]>, HelpText<"Only run preprocess, compile, and assemble steps">; def dA : Flag<"-dA">, Group<d_Group>; diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h index 5806928..64263c1 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/AnalyzerOptions.h @@ -64,6 +64,7 @@ public: std::string AnalyzeSpecificFunction; unsigned MaxNodes; unsigned MaxLoop; + unsigned ShowCheckerHelp : 1; unsigned AnalyzeAll : 1; unsigned AnalyzerDisplayProgress : 1; unsigned AnalyzeNestedBlocks : 1; @@ -75,7 +76,6 @@ public: unsigned VisualizeEGDot : 1; unsigned VisualizeEGUbi : 1; unsigned EnableExperimentalChecks : 1; - unsigned EnableExperimentalInternalChecks : 1; unsigned InlineCall : 1; unsigned UnoptimizedCFG : 1; unsigned CFGAddImplicitDtors : 1; @@ -87,6 +87,7 @@ public: AnalysisStoreOpt = BasicStoreModel; AnalysisConstraintsOpt = RangeConstraintsModel; AnalysisDiagOpt = PD_HTML; + ShowCheckerHelp = 0; AnalyzeAll = 0; AnalyzerDisplayProgress = 0; AnalyzeNestedBlocks = 0; @@ -98,7 +99,6 @@ public: VisualizeEGDot = 0; VisualizeEGUbi = 0; EnableExperimentalChecks = 0; - EnableExperimentalInternalChecks = 0; InlineCall = 0; UnoptimizedCFG = 0; CFGAddImplicitDtors = 0; diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def b/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def index 1b158fd..58f7e55 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def +++ b/contrib/llvm/tools/clang/include/clang/Frontend/DeclXML.def @@ -349,7 +349,7 @@ NODE_XML(UsingDecl, "Using") ID_ATTRIBUTE_XML ATTRIBUTE_FILE_LOCATION_XML ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getTargetNestedNameDecl(), "target_nested_namespace_decl") + ATTRIBUTE_XML(getQualifier(), "target_nested_namespace_decl") ATTRIBUTE_XML(isTypeName(), "is_typename") END_NODE_XML diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h index cbb4a57..b0669eb 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/HeaderSearchOptions.h @@ -22,6 +22,7 @@ namespace frontend { Quoted = 0, ///< `#include ""` paths. Thing `gcc -iquote`. Angled, ///< Paths for both `#include ""` and `#include <>`. (`-I`) System, ///< Like Angled, but marks system directories. + CXXSystem, ///< Like System, but only used for C++. After ///< Like System, but searched after the system directories. }; } @@ -54,9 +55,6 @@ public: /// User specified include entries. std::vector<Entry> UserEntries; - /// If non-empty, the list of C++ standard include paths to use. - std::vector<std::string> CXXSystemIncludes; - /// A (system-path) delimited list of include paths to be added from the /// environment following the user specified includes (but prior to builtin /// and standard includes). This is parsed in the same manner as the CPATH diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h index 485161b..02342c1 100644 --- a/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h +++ b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h @@ -28,6 +28,7 @@ class Decl; class DependencyOutputOptions; class Diagnostic; class DiagnosticOptions; +class FileManager; class HeaderSearch; class HeaderSearchOptions; class IdentifierTable; @@ -42,7 +43,8 @@ class FrontendOptions; /// Normalize \arg File for use in a user defined #include directive (in the /// predefines buffer). -std::string NormalizeDashIncludePath(llvm::StringRef File); +std::string NormalizeDashIncludePath(llvm::StringRef File, + FileManager &FileMgr); /// Apply the header search options to get given HeaderSearch object. void ApplyHeaderSearchOptions(HeaderSearch &HS, diff --git a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h index 018f7e9..9005adc 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h @@ -942,9 +942,6 @@ private: /// is not enclosed within a string literal. void HandleMicrosoft__pragma(Token &Tok); - void Handle_Pragma(unsigned Introducer, const std::string &StrVal, - SourceLocation PragmaLoc, SourceLocation RParenLoc); - /// EnterSourceFileWithLexer - Add a lexer to the top of the include stack and /// start lexing tokens from it instead of the current buffer. void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir); diff --git a/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h b/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h index 3f13e9c..6ae00cd 100644 --- a/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h +++ b/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h @@ -121,6 +121,10 @@ public: /// Lex - Lex and return a token from this macro stream. void Lex(Token &Tok); + /// isParsingPreprocessorDirective - Return true if we are in the middle of a + /// preprocessor directive. + bool isParsingPreprocessorDirective() const; + private: void destroy(); diff --git a/contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h b/contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h index 0a6656e..8b389b1 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h @@ -25,6 +25,9 @@ class FunctionDecl; class ObjCMethodDecl; class QualType; class Sema; +namespace sema { + class FunctionScopeInfo; +} namespace sema { @@ -47,16 +50,14 @@ private: enum VisitFlag { NotVisited = 0, Visited = 1, Pending = 2 }; llvm::DenseMap<const FunctionDecl*, VisitFlag> VisitedFD; - void IssueWarnings(Policy P, const Decl *D, QualType BlockTy); public: AnalysisBasedWarnings(Sema &s); - Policy getDefaultPolicy() { return DefaultPolicy; } + void IssueWarnings(Policy P, FunctionScopeInfo *fscope, + const Decl *D, const BlockExpr *blkExpr); - void IssueWarnings(Policy P, const BlockExpr *E); - void IssueWarnings(Policy P, const FunctionDecl *D); - void IssueWarnings(Policy P, const ObjCMethodDecl *D); + Policy getDefaultPolicy() { return DefaultPolicy; } }; }} // end namespace clang::sema diff --git a/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h b/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h index 9c4bb64..64126bd 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h @@ -29,10 +29,15 @@ #include "llvm/Support/ErrorHandling.h" namespace clang { + class ASTContext; + class TypeLoc; class LangOptions; class Diagnostic; class IdentifierInfo; + class NamespaceAliasDecl; + class NamespaceDecl; class NestedNameSpecifier; + class NestedNameSpecifierLoc; class Preprocessor; class Declarator; struct TemplateIdAnnotation; @@ -52,9 +57,29 @@ class CXXScopeSpec { SourceRange Range; NestedNameSpecifier *ScopeRep; -public: - CXXScopeSpec() : Range(), ScopeRep() { } + /// \brief Buffer used to store source-location information for the + /// nested-name-specifier. + /// + /// Note that we explicitly manage the buffer (rather than using a + /// SmallVector) because \c Declarator expects it to be possible to memcpy() + /// a \c CXXScopeSpec. + char *Buffer; + + /// \brief The size of the buffer used to store source-location information + /// for the nested-name-specifier. + unsigned BufferSize; + + /// \brief The capacity of the buffer used to store source-location + /// information for the nested-name-specifier. + unsigned BufferCapacity; +public: + CXXScopeSpec() : Range(), ScopeRep(), Buffer(0), BufferSize(0), + BufferCapacity(0) { } + CXXScopeSpec(const CXXScopeSpec &Other); + CXXScopeSpec &operator=(const CXXScopeSpec &Other); + ~CXXScopeSpec(); + const SourceRange &getRange() const { return Range; } void setRange(const SourceRange &R) { Range = R; } void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); } @@ -63,7 +88,87 @@ public: SourceLocation getEndLoc() const { return Range.getEnd(); } NestedNameSpecifier *getScopeRep() const { return ScopeRep; } - void setScopeRep(NestedNameSpecifier *S) { ScopeRep = S; } + + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'type::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param TemplateKWLoc The location of the 'template' keyword, if present. + /// + /// \param TL The TypeLoc that describes the type preceding the '::'. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL, + SourceLocation ColonColonLoc); + + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'identifier::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param Identifier The identifier. + /// + /// \param IdentifierLoc The location of the identifier. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, IdentifierInfo *Identifier, + SourceLocation IdentifierLoc, SourceLocation ColonColonLoc); + + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'namespace::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param Namespace The namespace. + /// + /// \param NamespaceLoc The location of the namespace name. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, NamespaceDecl *Namespace, + SourceLocation NamespaceLoc, SourceLocation ColonColonLoc); + + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'namespace-alias::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param Alias The namespace alias. + /// + /// \param AliasLoc The location of the namespace alias + /// name. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, NamespaceAliasDecl *Alias, + SourceLocation AliasLoc, SourceLocation ColonColonLoc); + + /// \brief Turn this (empty) nested-name-specifier into the global + /// nested-name-specifier '::'. + void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); + + /// \brief Make a new nested-name-specifier from incomplete source-location + /// information. + /// + /// FIXME: This routine should be used very, very rarely, in cases where we + /// need to synthesize a nested-name-specifier. Most code should instead use + /// \c Adopt() with a proper \c NestedNameSpecifierLoc. + void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, + SourceRange R); + + /// \brief Adopt an existing nested-name-specifier (with source-range + /// information). + void Adopt(NestedNameSpecifierLoc Other); + + /// \brief Retrieve a nested-name-specifier with location information, copied + /// into the given AST context. + /// + /// \param Context The context into which this nested-name-specifier will be + /// copied. + NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const; /// No scope specifier. bool isEmpty() const { return !Range.isValid(); } @@ -75,6 +180,15 @@ public: /// A scope specifier is present, and it refers to a real scope. bool isValid() const { return isNotEmpty() && ScopeRep != 0; } + /// \brief Indicate that this nested-name-specifier is invalid. + void SetInvalid(SourceRange R) { + assert(R.isValid() && "Must have a valid source range"); + if (Range.getBegin().isInvalid()) + Range.setBegin(R.getBegin()); + Range.setEnd(R.getEnd()); + ScopeRep = 0; + } + /// Deprecated. Some call sites intend isNotEmpty() while others intend /// isValid(). bool isSet() const { return ScopeRep != 0; } @@ -83,6 +197,13 @@ public: Range = SourceRange(); ScopeRep = 0; } + + /// \brief Retrieve the data associated with the source-location information. + char *location_data() const { return Buffer; } + + /// \brief Retrieve the size of the data associated with source-location + /// information. + unsigned location_size() const { return BufferSize; } }; /// DeclSpec - This class captures information about "declaration specifiers", @@ -825,6 +946,16 @@ struct DeclaratorChunk { struct PointerTypeInfo : TypeInfoCommon { /// The type qualifiers: const/volatile/restrict. unsigned TypeQuals : 3; + + /// The location of the const-qualifier, if any. + unsigned ConstQualLoc; + + /// The location of the volatile-qualifier, if any. + unsigned VolatileQualLoc; + + /// The location of the restrict-qualifier, if any. + unsigned RestrictQualLoc; + void destroy() { } }; @@ -1055,12 +1186,18 @@ struct DeclaratorChunk { /// getPointer - Return a DeclaratorChunk for a pointer. /// static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc, + SourceLocation ConstQualLoc, + SourceLocation VolatileQualLoc, + SourceLocation RestrictQualLoc, const ParsedAttributes &attrs) { DeclaratorChunk I; - I.Kind = Pointer; - I.Loc = Loc; - I.Ptr.TypeQuals = TypeQuals; - I.Ptr.AttrList = attrs.getList(); + I.Kind = Pointer; + I.Loc = Loc; + I.Ptr.TypeQuals = TypeQuals; + I.Ptr.ConstQualLoc = ConstQualLoc.getRawEncoding(); + I.Ptr.VolatileQualLoc = VolatileQualLoc.getRawEncoding(); + I.Ptr.RestrictQualLoc = RestrictQualLoc.getRawEncoding(); + I.Ptr.AttrList = attrs.getList(); return I; } diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h b/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h index 6d7bc63..e2b083e 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h @@ -20,6 +20,8 @@ namespace clang { struct ObjCMethodList; class Sema; +class Scope; +class LookupResult; /// \brief An abstract interface that should be implemented by /// external AST sources that also provide information for semantic @@ -47,6 +49,16 @@ public: /// instance and factory methods, respectively, with this selector. virtual std::pair<ObjCMethodList,ObjCMethodList> ReadMethodPool(Selector Sel); + /// \brief Do last resort, unqualified lookup on a LookupResult that + /// Sema cannot find. + /// + /// \param R a LookupResult that is being recovered. + /// + /// \param S the Scope of the identifier occurrence. + /// + /// \return true to tell Sema to recover using the LookupResult. + virtual bool LookupUnqualified(LookupResult &R, Scope *S) { return false; } + // isa/cast/dyn_cast support static bool classof(const ExternalASTSource *Source) { return Source->SemaSource; diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h b/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h index c191565..bdf0d8e 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h @@ -467,7 +467,10 @@ public: CAssignment, /// \brief String initialization - StringInit + StringInit, + + /// \brief Array initialization from another array (GNU C extension). + ArrayInit }; /// \brief Describes the kind of a particular step in an initialization @@ -513,7 +516,10 @@ public: SK_StringInit, /// \brief An initialization that "converts" an Objective-C object /// (not a point to an object) to another Objective-C object type. - SK_ObjCObjectConversion + SK_ObjCObjectConversion, + /// \brief Array initialization (from an array rvalue). + /// This is a GNU C extension. + SK_ArrayInit }; /// \brief A single step in the initialization sequence. @@ -563,6 +569,10 @@ public: /// \brief Array must be initialized with an initializer list or a /// string literal. FK_ArrayNeedsInitListOrStringLiteral, + /// \brief Array type mismatch. + FK_ArrayTypeMismatch, + /// \brief Non-constant array initializer + FK_NonConstantArrayInit, /// \brief Cannot resolve the address of an overloaded function. FK_AddressOfOverloadFailed, /// \brief Overloading due to reference initialization failed. @@ -775,6 +785,9 @@ public: /// always a no-op. void AddObjCObjectConversionStep(QualType T); + /// \brief Add an array initialization step. + void AddArrayInitStep(QualType T); + /// \brief Note that this initialization sequence failed. void SetFailed(FailureKind Failure) { SequenceKind = FailedSequence; diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h b/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h index 5aa6f47..9e1a616 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h @@ -177,6 +177,12 @@ namespace clang { = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) + sizeof(ParsedTemplateArgument) * NumArgs); TemplateId->NumArgs = NumArgs; + + // Default-construct parsed template arguments. + ParsedTemplateArgument *TemplateArgs = TemplateId->getTemplateArgs(); + for (unsigned I = 0; I != NumArgs; ++I) + new (TemplateArgs + I) ParsedTemplateArgument(); + return TemplateId; } diff --git a/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h b/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h index b0bb955..51297ae 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_SEMA_SCOPE_INFO_H #include "clang/AST/Type.h" +#include "clang/Basic/PartialDiagnostic.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SetVector.h" @@ -30,6 +31,17 @@ class SwitchStmt; namespace sema { +class PossiblyUnreachableDiag { +public: + PartialDiagnostic PD; + SourceLocation Loc; + const Stmt *stmt; + + PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc, + const Stmt *stmt) + : PD(PD), Loc(Loc), stmt(stmt) {} +}; + /// \brief Retains information about a function, method, or block that is /// currently being parsed. class FunctionScopeInfo { @@ -60,6 +72,11 @@ public: /// block, if there is any chance of applying the named return value /// optimization. llvm::SmallVector<ReturnStmt*, 4> Returns; + + /// \brief A list of PartialDiagnostics created but delayed within the + /// current function scope. These diagnostics are vetted for reachability + /// prior to being emitted. + llvm::SmallVector<PossiblyUnreachableDiag, 4> PossiblyUnreachableDiags; void setHasBranchIntoScope() { HasBranchIntoScope = true; diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h index 91d6914..a937398 100644 --- a/contrib/llvm/tools/clang/include/clang/Sema/Sema.h +++ b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h @@ -267,6 +267,10 @@ public: /// same list more than once. llvm::OwningPtr<RecordDeclSetTy> PureVirtualClassDiagSet; + /// ParsingInitForAutoVars - a set of declarations with auto types for which + /// we are currently parsing the initializer. + llvm::SmallPtrSet<const Decl*, 4> ParsingInitForAutoVars; + /// \brief A mapping from external names to the most recent /// locally-scoped external declaration with that name. /// @@ -684,7 +688,8 @@ public: void PushFunctionScope(); void PushBlockScope(Scope *BlockScope, BlockDecl *Block); - void PopFunctionOrBlockScope(); + void PopFunctionOrBlockScope(const sema::AnalysisBasedWarnings::Policy *WP =0, + const Decl *D = 0, const BlockExpr *blkExpr = 0); sema::FunctionScopeInfo *getCurFunction() const { return FunctionScopes.back(); @@ -856,9 +861,12 @@ public: void ActOnUninitializedDecl(Decl *dcl, bool TypeMayContainAuto); void ActOnInitializerError(Decl *Dcl); void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc); + void FinalizeDeclaration(Decl *D); DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, Decl **Group, unsigned NumDecls); + DeclGroupPtrTy BuildDeclaratorGroup(Decl **Group, unsigned NumDecls, + bool TypeMayContainAuto = true); void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, SourceLocation LocAfterDecls); Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D); @@ -1518,7 +1526,8 @@ public: void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method, bool &IncompleteImpl, unsigned DiagID); void WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethod, - ObjCMethodDecl *IntfMethod); + ObjCMethodDecl *MethodDecl, + bool IsProtocolMethodDecl); bool isPropertyReadonly(ObjCPropertyDecl *PropertyDecl, ObjCInterfaceDecl *IDecl); @@ -1883,7 +1892,16 @@ public: void MarkDeclarationReferenced(SourceLocation Loc, Decl *D); void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T); void MarkDeclarationsReferencedInExpr(Expr *E); - bool DiagRuntimeBehavior(SourceLocation Loc, const PartialDiagnostic &PD); + + /// \brief Conditionally issue a diagnostic based on the current + /// evaluation context. + /// + /// \param stmt - If stmt is non-null, delay reporting the diagnostic until + /// the function body is parsed, and then do a basic reachability analysis to + /// determine if the statement is reachable. If it is unreachable, the + /// diagnostic will not be emitted. + bool DiagRuntimeBehavior(SourceLocation Loc, const Stmt *stmt, + const PartialDiagnostic &PD); // Primary Expressions. SourceRange getExprRange(Expr *E) const; @@ -2573,11 +2591,19 @@ public: CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS); bool isUnknownSpecialization(const CXXScopeSpec &SS); - /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the - /// global scope ('::'). - NestedNameSpecifier * - ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc); - + /// \brief The parser has parsed a global nested-name-specifier '::'. + /// + /// \param S The scope in which this nested-name-specifier occurs. + /// + /// \param CCLoc The location of the '::'. + /// + /// \param SS The nested-name-specifier, which will be updated in-place + /// to reflect the parsed nested-name-specifier. + /// + /// \returns true if an error occurred, false otherwise. + bool ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc, + CXXScopeSpec &SS); + bool isAcceptableNestedNameSpecifier(NamedDecl *SD); NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS); @@ -2586,43 +2612,97 @@ public: IdentifierInfo &II, ParsedType ObjectType); - NestedNameSpecifier *BuildCXXNestedNameSpecifier(Scope *S, - CXXScopeSpec &SS, - SourceLocation IdLoc, - SourceLocation CCLoc, - IdentifierInfo &II, - QualType ObjectType, - NamedDecl *ScopeLookupResult, - bool EnteringContext, - bool ErrorRecoveryLookup); - - NestedNameSpecifier *ActOnCXXNestedNameSpecifier(Scope *S, - CXXScopeSpec &SS, - SourceLocation IdLoc, - SourceLocation CCLoc, - IdentifierInfo &II, - ParsedType ObjectType, - bool EnteringContext); + bool BuildCXXNestedNameSpecifier(Scope *S, + IdentifierInfo &Identifier, + SourceLocation IdentifierLoc, + SourceLocation CCLoc, + QualType ObjectType, + bool EnteringContext, + CXXScopeSpec &SS, + NamedDecl *ScopeLookupResult, + bool ErrorRecoveryLookup); + + /// \brief The parser has parsed a nested-name-specifier 'identifier::'. + /// + /// \param S The scope in which this nested-name-specifier occurs. + /// + /// \param Identifier The identifier preceding the '::'. + /// + /// \param IdentifierLoc The location of the identifier. + /// + /// \param CCLoc The location of the '::'. + /// + /// \param ObjectType The type of the object, if we're parsing + /// nested-name-specifier in a member access expression. + /// + /// \param EnteringContext Whether we're entering the context nominated by + /// this nested-name-specifier. + /// + /// \param SS The nested-name-specifier, which is both an input + /// parameter (the nested-name-specifier before this type) and an + /// output parameter (containing the full nested-name-specifier, + /// including this new type). + /// + /// \returns true if an error occurred, false otherwise. + bool ActOnCXXNestedNameSpecifier(Scope *S, + IdentifierInfo &Identifier, + SourceLocation IdentifierLoc, + SourceLocation CCLoc, + ParsedType ObjectType, + bool EnteringContext, + CXXScopeSpec &SS); bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, - IdentifierInfo &II, + IdentifierInfo &Identifier, + SourceLocation IdentifierLoc, + SourceLocation ColonLoc, ParsedType ObjectType, bool EnteringContext); - /// ActOnCXXNestedNameSpecifier - Called during parsing of a - /// nested-name-specifier that involves a template-id, e.g., - /// "foo::bar<int, float>::", and now we need to build a scope - /// specifier. \p SS is empty or the previously parsed nested-name - /// part ("foo::"), \p Type is the already-parsed class template - /// specialization (or other template-id that names a type), \p - /// TypeRange is the source range where the type is located, and \p - /// CCLoc is the location of the trailing '::'. - CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S, - const CXXScopeSpec &SS, - ParsedType Type, - SourceRange TypeRange, - SourceLocation CCLoc); - + /// \brief The parser has parsed a nested-name-specifier 'type::'. + /// + /// \param S The scope in which this nested-name-specifier occurs. + /// + /// \param Type The type, which will be a template specialization + /// type, preceding the '::'. + /// + /// \param CCLoc The location of the '::'. + /// + /// \param SS The nested-name-specifier, which is both an input + /// parameter (the nested-name-specifier before this type) and an + /// output parameter (containing the full nested-name-specifier, + /// including this new type). + /// + /// \returns true if an error occurred, false otherwise. + bool ActOnCXXNestedNameSpecifier(Scope *S, + ParsedType Type, + SourceLocation CCLoc, + CXXScopeSpec &SS); + + /// \brief Given a C++ nested-name-specifier, produce an annotation value + /// that the parser can use later to reconstruct the given + /// nested-name-specifier. + /// + /// \param SS A nested-name-specifier. + /// + /// \returns A pointer containing all of the information in the + /// nested-name-specifier \p SS. + void *SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS); + + /// \brief Given an annotation pointer for a nested-name-specifier, restore + /// the nested-name-specifier structure. + /// + /// \param Annotation The annotation pointer, produced by + /// \c SaveNestedNameSpecifierAnnotation(). + /// + /// \param AnnotationRange The source range corresponding to the annotation. + /// + /// \param SS The nested-name-specifier that will be updated with the contents + /// of the annotation pointer. + void RestoreNestedNameSpecifierAnnotation(void *Annotation, + SourceRange AnnotationRange, + CXXScopeSpec &SS); + bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS); /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global @@ -4213,6 +4293,11 @@ public: SubstNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range, const MultiLevelTemplateArgumentList &TemplateArgs); + + NestedNameSpecifierLoc + SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, + const MultiLevelTemplateArgumentList &TemplateArgs); + DeclarationNameInfo SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo, const MultiLevelTemplateArgumentList &TemplateArgs); @@ -4772,7 +4857,8 @@ public: QualType CheckSubtractionOperands( // C99 6.5.6 Expr *&lex, Expr *&rex, SourceLocation OpLoc, QualType* CompLHSTy = 0); QualType CheckShiftOperands( // C99 6.5.7 - Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); + Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc, + bool isCompAssign = false); QualType CheckCompareOperands( // C99 6.5.8/9 Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc, bool isRelational); diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h index 9799b8d..424e78c 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h +++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h @@ -116,7 +116,8 @@ public: /// \returns true to indicate the predefines are invalid or false otherwise. virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, llvm::StringRef OriginalFileName, - std::string &SuggestedPredefines) { + std::string &SuggestedPredefines, + FileManager &FileMgr) { return false; } @@ -143,7 +144,8 @@ public: virtual bool ReadTargetTriple(llvm::StringRef Triple); virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, llvm::StringRef OriginalFileName, - std::string &SuggestedPredefines); + std::string &SuggestedPredefines, + FileManager &FileMgr); virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID); virtual void ReadCounter(unsigned Value); @@ -1131,6 +1133,10 @@ public: NestedNameSpecifier *ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx); + NestedNameSpecifierLoc ReadNestedNameSpecifierLoc(PerFileData &F, + const RecordData &Record, + unsigned &Idx); + /// \brief Read a template name. TemplateName ReadTemplateName(PerFileData &F, const RecordData &Record, unsigned &Idx); diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h index beb4936..04ad93f 100644 --- a/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h +++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h @@ -443,6 +443,9 @@ public: /// \brief Emits a reference to a declarator info. void AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordDataImpl &Record); + /// \brief Emits a type with source-location information. + void AddTypeLoc(TypeLoc TL, RecordDataImpl &Record); + /// \brief Emits a template argument location info. void AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, const TemplateArgumentLocInfo &Arg, @@ -474,6 +477,10 @@ public: /// \brief Emit a nested name specifier. void AddNestedNameSpecifier(NestedNameSpecifier *NNS, RecordDataImpl &Record); + + /// \brief Emit a nested name specifier with source-location information. + void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, + RecordDataImpl &Record); /// \brief Emit a template name. void AddTemplateName(TemplateName Name, RecordDataImpl &Record); diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h index 42feb78..afba12d 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h @@ -40,7 +40,6 @@ TransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled, const LangOptions& lopts); void RegisterExperimentalChecks(ExprEngine &Eng); -void RegisterExperimentalInternalChecks(ExprEngine &Eng); void RegisterCallInliner(ExprEngine &Eng); diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 1786fe6..93d7958 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -72,6 +72,7 @@ protected: friend class BugReportEquivClass; virtual void Profile(llvm::FoldingSetNodeID& hash) const { + hash.AddPointer(&BT); hash.AddInteger(getLocation().getRawEncoding()); hash.AddString(Description); } @@ -277,6 +278,8 @@ private: void FlushReport(BugReportEquivClass& EQ); + llvm::FoldingSet<BugReportEquivClass> EQClasses; + protected: BugReporter(BugReporterData& d, Kind k) : BugTypes(F.getEmptySet()), kind(k), D(d) {} @@ -302,6 +305,10 @@ public: iterator begin() { return BugTypes.begin(); } iterator end() { return BugTypes.end(); } + typedef llvm::FoldingSet<BugReportEquivClass>::iterator EQClasses_iterator; + EQClasses_iterator EQClasses_begin() { return EQClasses.begin(); } + EQClasses_iterator EQClasses_end() { return EQClasses.end(); } + ASTContext& getContext() { return D.getASTContext(); } SourceManager& getSourceManager() { return D.getSourceManager(); } @@ -344,6 +351,13 @@ public: } static bool classof(const BugReporter* R) { return true; } + +private: + llvm::StringMap<BugType *> StrBugTypes; + + /// \brief Returns a BugType that is associated with the given name and + /// category. + BugType *getBugTypeForName(llvm::StringRef name, llvm::StringRef category); }; // FIXME: Get rid of GRBugReporter. It's the wrong abstraction. diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h index 2793284..7b9bb03 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h @@ -29,8 +29,6 @@ class BugType { private: const std::string Name; const std::string Category; - llvm::FoldingSet<BugReportEquivClass> EQClasses; - friend class BugReporter; bool SuppressonSink; public: BugType(llvm::StringRef name, llvm::StringRef cat) @@ -48,14 +46,6 @@ public: void setSuppressOnSink(bool x) { SuppressonSink = x; } virtual void FlushReports(BugReporter& BR); - - typedef llvm::FoldingSet<BugReportEquivClass>::iterator iterator; - iterator begin() { return EQClasses.begin(); } - iterator end() { return EQClasses.end(); } - - typedef llvm::FoldingSet<BugReportEquivClass>::const_iterator const_iterator; - const_iterator begin() const { return EQClasses.begin(); } - const_iterator end() const { return EQClasses.end(); } }; class BuiltinBug : public BugType { diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h index 65c8b80..2768195 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -14,23 +14,92 @@ #ifndef LLVM_CLANG_SA_CORE_CHECKERMANAGER_H #define LLVM_CLANG_SA_CORE_CHECKERMANAGER_H +#include "clang/Basic/LangOptions.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" #include <vector> namespace clang { class Decl; + class Stmt; + class CallExpr; namespace ento { class ExprEngine; class AnalysisManager; class BugReporter; + class CheckerContext; + class ObjCMessage; + class SVal; + class ExplodedNode; + class ExplodedNodeSet; + class ExplodedGraph; + class GRState; + class EndOfFunctionNodeBuilder; + class MemRegion; + class SymbolReaper; + +class GraphExpander { +public: + virtual ~GraphExpander(); + virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) = 0; +}; + +struct VoidCheckerFnParm {}; +template <typename P1=VoidCheckerFnParm, typename P2=VoidCheckerFnParm, + typename P3=VoidCheckerFnParm, typename P4=VoidCheckerFnParm> +class CheckerFn { + typedef void (*Func)(void *, P1, P2, P3, P4); + Func Fn; +public: + void *Checker; + CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { } + void operator()(P1 p1, P2 p2, P3 p3, P4 p4) { Fn(Checker, p1, p2, p3, p4); } +}; + +template <typename P1, typename P2, typename P3> +class CheckerFn<P1, P2, P3, VoidCheckerFnParm> { + typedef void (*Func)(void *, P1, P2, P3); + Func Fn; +public: + void *Checker; + CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { } + void operator()(P1 p1, P2 p2, P3 p3) { Fn(Checker, p1, p2, p3); } +}; + +template <typename P1, typename P2> +class CheckerFn<P1, P2, VoidCheckerFnParm, VoidCheckerFnParm> { + typedef void (*Func)(void *, P1, P2); + Func Fn; +public: + void *Checker; + CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { } + void operator()(P1 p1, P2 p2) { Fn(Checker, p1, p2); } +}; + +template <> +class CheckerFn<VoidCheckerFnParm, VoidCheckerFnParm, VoidCheckerFnParm, + VoidCheckerFnParm> { + typedef void (*Func)(void *); + Func Fn; +public: + void *Checker; + CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { } + void operator()() { Fn(Checker); } +}; class CheckerManager { + const LangOptions LangOpts; + public: + CheckerManager(const LangOptions &langOpts) : LangOpts(langOpts) { } ~CheckerManager(); + const LangOptions &getLangOptions() const { return LangOpts; } + typedef void *CheckerRef; + typedef CheckerFn<> CheckerDtor; //===----------------------------------------------------------------------===// // registerChecker @@ -40,17 +109,12 @@ public: template <typename CHECKER> void registerChecker() { CHECKER *checker = new CHECKER(); - Checkers.push_back(std::pair<CheckerRef, Dtor>(checker, destruct<CHECKER>)); + CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>)); CHECKER::_register(checker, *this); } - typedef void (*RegisterToEngFunc)(ExprEngine &Eng); - void addCheckerRegisterFunction(RegisterToEngFunc fn) { - Funcs.push_back(fn); - } - //===----------------------------------------------------------------------===// -// Functions for running checkers. +// Functions for running checkers for AST traversing.. //===----------------------------------------------------------------------===// /// \brief Run checkers handling Decls. @@ -62,48 +126,290 @@ public: BugReporter &BR); //===----------------------------------------------------------------------===// -// Internal registration functions. +// Functions for running checkers for path-sensitive checking. +//===----------------------------------------------------------------------===// + + /// \brief Run checkers for pre-visiting Stmts. + void runCheckersForPreStmt(ExplodedNodeSet &Dst, + const ExplodedNodeSet &Src, + const Stmt *S, + ExprEngine &Eng) { + runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng); + } + + /// \brief Run checkers for post-visiting Stmts. + void runCheckersForPostStmt(ExplodedNodeSet &Dst, + const ExplodedNodeSet &Src, + const Stmt *S, + ExprEngine &Eng) { + runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng); + } + + /// \brief Run checkers for visiting Stmts. + void runCheckersForStmt(bool isPreVisit, + ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, + const Stmt *S, ExprEngine &Eng); + + /// \brief Run checkers for pre-visiting obj-c messages. + void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst, + const ExplodedNodeSet &Src, + const ObjCMessage &msg, + ExprEngine &Eng) { + runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng); + } + + /// \brief Run checkers for post-visiting obj-c messages. + void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst, + const ExplodedNodeSet &Src, + const ObjCMessage &msg, + ExprEngine &Eng) { + runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng); + } + + /// \brief Run checkers for visiting obj-c messages. + void runCheckersForObjCMessage(bool isPreVisit, + ExplodedNodeSet &Dst, + const ExplodedNodeSet &Src, + const ObjCMessage &msg, ExprEngine &Eng); + + /// \brief Run checkers for load/store of a location. + void runCheckersForLocation(ExplodedNodeSet &Dst, + const ExplodedNodeSet &Src, + SVal location, bool isLoad, + const Stmt *S, + ExprEngine &Eng); + + /// \brief Run checkers for end of analysis. + void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, + ExprEngine &Eng); + + /// \brief Run checkers for end of path. + void runCheckersForEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng); + + /// \brief Run checkers for live symbols. + void runCheckersForLiveSymbols(const GRState *state, + SymbolReaper &SymReaper); + + /// \brief Run checkers for dead symbols. + void runCheckersForDeadSymbols(ExplodedNodeSet &Dst, + const ExplodedNodeSet &Src, + SymbolReaper &SymReaper, const Stmt *S, + ExprEngine &Eng); + + /// \brief True if at least one checker wants to check region changes. + bool wantsRegionChangeUpdate(const GRState *state); + + /// \brief Run checkers for region changes. + const GRState *runCheckersForRegionChanges(const GRState *state, + const MemRegion * const *Begin, + const MemRegion * const *End); + + /// \brief Run checkers for evaluating a call. + void runCheckersForEvalCall(ExplodedNodeSet &Dst, + const ExplodedNodeSet &Src, + const CallExpr *CE, ExprEngine &Eng, + GraphExpander *defaultEval = 0); + +//===----------------------------------------------------------------------===// +// Internal registration functions for AST traversing. //===----------------------------------------------------------------------===// // Functions used by the registration mechanism, checkers should not touch // these directly. - typedef void (*CheckDeclFunc)(CheckerRef checker, const Decl *D, - AnalysisManager& mgr, BugReporter &BR); + typedef CheckerFn<const Decl *, AnalysisManager&, BugReporter &> + CheckDeclFunc; + typedef CheckerFn<const Stmt *, CheckerContext &> CheckStmtFunc; + typedef bool (*HandlesDeclFunc)(const Decl *D); - void _registerForDecl(CheckerRef checker, CheckDeclFunc checkfn, - HandlesDeclFunc isForDeclFn); + void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn); - void _registerForBody(CheckerRef checker, CheckDeclFunc checkfn); - - void registerCheckersToEngine(ExprEngine &eng); + void _registerForBody(CheckDeclFunc checkfn); + +//===----------------------------------------------------------------------===// +// Internal registration functions for path-sensitive checking. +//===----------------------------------------------------------------------===// + + typedef CheckerFn<const ObjCMessage &, CheckerContext &> CheckObjCMessageFunc; + typedef CheckerFn<const SVal &/*location*/, bool/*isLoad*/, CheckerContext &> + CheckLocationFunc; + typedef CheckerFn<ExplodedGraph &, BugReporter &, ExprEngine &> + CheckEndAnalysisFunc; + typedef CheckerFn<EndOfFunctionNodeBuilder &, ExprEngine &> CheckEndPathFunc; + typedef CheckerFn<SymbolReaper &, CheckerContext &> CheckDeadSymbolsFunc; + typedef CheckerFn<const GRState *, SymbolReaper &> CheckLiveSymbolsFunc; + + typedef bool (*HandlesStmtFunc)(const Stmt *D); + void _registerForPreStmt(CheckStmtFunc checkfn, + HandlesStmtFunc isForStmtFn); + void _registerForPostStmt(CheckStmtFunc checkfn, + HandlesStmtFunc isForStmtFn); + + void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn); + void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn); + + void _registerForLocation(CheckLocationFunc checkfn); + + void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn); + + void _registerForEndPath(CheckEndPathFunc checkfn); + + void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn); + + void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn); + + class CheckRegionChangesFunc { + typedef const GRState * (*Func)(void *, const GRState *, + const MemRegion * const *, + const MemRegion * const *); + Func Fn; + public: + void *Checker; + CheckRegionChangesFunc(void *checker, Func fn) : Fn(fn), Checker(checker) {} + const GRState *operator()(const GRState *state, + const MemRegion * const *begin, + const MemRegion * const *end) { + return Fn(Checker, state, begin, end); + } + }; + + class WantsRegionChangeUpdateFunc { + typedef bool (*Func)(void *, const GRState *); + Func Fn; + public: + void *Checker; + WantsRegionChangeUpdateFunc(void *checker, Func fn) + : Fn(fn), Checker(checker) { } + bool operator()(const GRState *state) { + return Fn(Checker, state); + } + }; + + void _registerForRegionChanges(CheckRegionChangesFunc checkfn, + WantsRegionChangeUpdateFunc wantUpdateFn); + + class EvalCallFunc { + typedef bool (*Func)(void *, const CallExpr *, CheckerContext &); + Func Fn; + public: + void *Checker; + EvalCallFunc(void *checker, Func fn) : Fn(fn), Checker(checker) { } + bool operator()(const CallExpr *CE, CheckerContext &C) { + return Fn(Checker, CE, C); + } + }; + + void _registerForEvalCall(EvalCallFunc checkfn); + +//===----------------------------------------------------------------------===// +// Implementation details. +//===----------------------------------------------------------------------===// private: template <typename CHECKER> static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); } - std::vector<RegisterToEngFunc> Funcs; + std::vector<CheckerDtor> CheckerDtors; struct DeclCheckerInfo { - CheckerRef Checker; CheckDeclFunc CheckFn; HandlesDeclFunc IsForDeclFn; }; std::vector<DeclCheckerInfo> DeclCheckers; - std::vector<std::pair<CheckerRef, CheckDeclFunc> > BodyCheckers; - - typedef void (*Dtor)(void *); - std::vector<std::pair<CheckerRef, Dtor> > Checkers; + std::vector<CheckDeclFunc> BodyCheckers; - typedef llvm::SmallVector<std::pair<CheckerRef, CheckDeclFunc>, 4> - CachedDeclCheckers; + typedef llvm::SmallVector<CheckDeclFunc, 4> CachedDeclCheckers; typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy; CachedDeclCheckersMapTy CachedDeclCheckersMap; + + struct StmtCheckerInfo { + CheckStmtFunc CheckFn; + HandlesStmtFunc IsForStmtFn; + bool IsPreVisit; + }; + std::vector<StmtCheckerInfo> StmtCheckers; + + struct CachedStmtCheckersKey { + unsigned StmtKind; + bool IsPreVisit; + + CachedStmtCheckersKey() : StmtKind(0), IsPreVisit(0) { } + CachedStmtCheckersKey(unsigned stmtKind, bool isPreVisit) + : StmtKind(stmtKind), IsPreVisit(isPreVisit) { } + + static CachedStmtCheckersKey getSentinel() { + return CachedStmtCheckersKey(~0U, 0); + } + unsigned getHashValue() const { + llvm::FoldingSetNodeID ID; + ID.AddInteger(StmtKind); + ID.AddBoolean(IsPreVisit); + return ID.ComputeHash(); + } + bool operator==(const CachedStmtCheckersKey &RHS) const { + return StmtKind == RHS.StmtKind && IsPreVisit == RHS.IsPreVisit; + } + }; + friend struct llvm::DenseMapInfo<CachedStmtCheckersKey>; + + typedef llvm::SmallVector<CheckStmtFunc, 4> CachedStmtCheckers; + typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers> + CachedStmtCheckersMapTy; + CachedStmtCheckersMapTy CachedStmtCheckersMap; + + CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit); + + std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers; + std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers; + + std::vector<CheckLocationFunc> LocationCheckers; + + std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers; + + std::vector<CheckEndPathFunc> EndPathCheckers; + + std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers; + + std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers; + + struct RegionChangesCheckerInfo { + CheckRegionChangesFunc CheckFn; + WantsRegionChangeUpdateFunc WantUpdateFn; + }; + std::vector<RegionChangesCheckerInfo> RegionChangesCheckers; + + std::vector<EvalCallFunc> EvalCallCheckers; }; } // end ento namespace } // end clang namespace +namespace llvm { + /// Define DenseMapInfo so that CachedStmtCheckersKey can be used as key + /// in DenseMap and DenseSets. + template <> + struct DenseMapInfo<clang::ento::CheckerManager::CachedStmtCheckersKey> { + static inline clang::ento::CheckerManager::CachedStmtCheckersKey + getEmptyKey() { + return clang::ento::CheckerManager::CachedStmtCheckersKey(); + } + static inline clang::ento::CheckerManager::CachedStmtCheckersKey + getTombstoneKey() { + return clang::ento::CheckerManager::CachedStmtCheckersKey::getSentinel(); + } + + static unsigned + getHashValue(clang::ento::CheckerManager::CachedStmtCheckersKey S) { + return S.getHashValue(); + } + + static bool isEqual(clang::ento::CheckerManager::CachedStmtCheckersKey LHS, + clang::ento::CheckerManager::CachedStmtCheckersKey RHS) { + return LHS == RHS; + } + }; +} // end namespace llvm + #endif diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h index 414ad92..40b838e 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h @@ -17,6 +17,10 @@ #include "llvm/ADT/StringRef.h" #include <vector> +namespace llvm { + class raw_ostream; +} + namespace clang { namespace ento { @@ -45,6 +49,7 @@ public: virtual ~CheckerProvider(); virtual void registerCheckers(CheckerManager &checkerMgr, CheckerOptInfo *checkOpts, unsigned numCheckOpts) = 0; + virtual void printHelp(llvm::raw_ostream &OS) = 0; }; } // end ento namespace diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h index 8c96866..e080d19 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerV2.h @@ -41,7 +41,9 @@ class ASTDecl { public: template <typename CHECKER> static void _register(CHECKER *checker, CheckerManager &mgr) { - mgr._registerForDecl(checker, _checkDecl<CHECKER>, _handlesDecl); + mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker, + _checkDecl<CHECKER>), + _handlesDecl); } }; @@ -55,12 +57,197 @@ class ASTCodeBody { public: template <typename CHECKER> static void _register(CHECKER *checker, CheckerManager &mgr) { - mgr._registerForBody(checker, _checkBody<CHECKER>); + mgr._registerForBody(CheckerManager::CheckDeclFunc(checker, + _checkBody<CHECKER>)); + } +}; + +template <typename STMT> +class PreStmt { + template <typename CHECKER> + static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { + ((const CHECKER *)checker)->checkPreStmt(llvm::cast<STMT>(S), C); + } + + static bool _handlesStmt(const Stmt *S) { + return llvm::isa<STMT>(S); + } +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker, + _checkStmt<CHECKER>), + _handlesStmt); + } +}; + +template <typename STMT> +class PostStmt { + template <typename CHECKER> + static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { + ((const CHECKER *)checker)->checkPostStmt(llvm::cast<STMT>(S), C); + } + + static bool _handlesStmt(const Stmt *S) { + return llvm::isa<STMT>(S); + } +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker, + _checkStmt<CHECKER>), + _handlesStmt); + } +}; + +class PreObjCMessage { + template <typename CHECKER> + static void _checkObjCMessage(void *checker, const ObjCMessage &msg, + CheckerContext &C) { + ((const CHECKER *)checker)->checkPreObjCMessage(msg, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForPreObjCMessage( + CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); + } +}; + +class PostObjCMessage { + template <typename CHECKER> + static void _checkObjCMessage(void *checker, const ObjCMessage &msg, + CheckerContext &C) { + ((const CHECKER *)checker)->checkPostObjCMessage(msg, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForPostObjCMessage( + CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); + } +}; + +class Location { + template <typename CHECKER> + static void _checkLocation(void *checker, const SVal &location, bool isLoad, + CheckerContext &C) { + ((const CHECKER *)checker)->checkLocation(location, isLoad, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForLocation( + CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>)); + } +}; + +class EndAnalysis { + template <typename CHECKER> + static void _checkEndAnalysis(void *checker, ExplodedGraph &G, + BugReporter &BR, ExprEngine &Eng) { + ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForEndAnalysis( + CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>)); + } +}; + +class EndPath { + template <typename CHECKER> + static void _checkEndPath(void *checker, EndOfFunctionNodeBuilder &B, + ExprEngine &Eng) { + ((const CHECKER *)checker)->checkEndPath(B, Eng); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForEndPath( + CheckerManager::CheckEndPathFunc(checker, _checkEndPath<CHECKER>)); + } +}; + +class LiveSymbols { + template <typename CHECKER> + static void _checkLiveSymbols(void *checker, const GRState *state, + SymbolReaper &SR) { + ((const CHECKER *)checker)->checkLiveSymbols(state, SR); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForLiveSymbols( + CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>)); + } +}; + +class DeadSymbols { + template <typename CHECKER> + static void _checkDeadSymbols(void *checker, + SymbolReaper &SR, CheckerContext &C) { + ((const CHECKER *)checker)->checkDeadSymbols(SR, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForDeadSymbols( + CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>)); + } +}; + +class RegionChanges { + template <typename CHECKER> + static const GRState *_checkRegionChanges(void *checker, const GRState *state, + const MemRegion * const *Begin, + const MemRegion * const *End) { + return ((const CHECKER *)checker)->checkRegionChanges(state, Begin, End); + } + template <typename CHECKER> + static bool _wantsRegionChangeUpdate(void *checker, const GRState *state) { + return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForRegionChanges( + CheckerManager::CheckRegionChangesFunc(checker, + _checkRegionChanges<CHECKER>), + CheckerManager::WantsRegionChangeUpdateFunc(checker, + _wantsRegionChangeUpdate<CHECKER>)); } }; } // end check namespace +namespace eval { + +class Call { + template <typename CHECKER> + static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) { + return ((const CHECKER *)checker)->evalCall(CE, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForEvalCall( + CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>)); + } +}; + +} // end eval namespace + template <typename CHECK1, typename CHECK2=check::_VoidCheck, typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck, typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck, diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h index 22c2027..627bc0a 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h @@ -15,8 +15,7 @@ #ifndef LLVM_CLANG_GR_CHECKER #define LLVM_CLANG_GR_CHECKER -#include "clang/Analysis/Support/SaveAndRestore.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" //===----------------------------------------------------------------------===// // Checker interface. @@ -26,163 +25,6 @@ namespace clang { namespace ento { -class CheckerContext { - ExplodedNodeSet &Dst; - StmtNodeBuilder &B; - ExprEngine &Eng; - ExplodedNode *Pred; - SaveAndRestore<bool> OldSink; - const void *checkerTag; - SaveAndRestore<ProgramPoint::Kind> OldPointKind; - SaveOr OldHasGen; - const GRState *ST; - const Stmt *statement; - const unsigned size; -public: - bool *respondsToCallback; -public: - CheckerContext(ExplodedNodeSet &dst, StmtNodeBuilder &builder, - ExprEngine &eng, ExplodedNode *pred, - const void *tag, ProgramPoint::Kind K, - bool *respondsToCB = 0, - const Stmt *stmt = 0, const GRState *st = 0) - : Dst(dst), B(builder), Eng(eng), Pred(pred), - OldSink(B.BuildSinks), - checkerTag(tag), - OldPointKind(B.PointKind, K), - OldHasGen(B.hasGeneratedNode), - ST(st), statement(stmt), size(Dst.size()), - respondsToCallback(respondsToCB) {} - - ~CheckerContext(); - - ExprEngine &getEngine() { - return Eng; - } - - AnalysisManager &getAnalysisManager() { - return Eng.getAnalysisManager(); - } - - ConstraintManager &getConstraintManager() { - return Eng.getConstraintManager(); - } - - StoreManager &getStoreManager() { - return Eng.getStoreManager(); - } - - ExplodedNodeSet &getNodeSet() { return Dst; } - StmtNodeBuilder &getNodeBuilder() { return B; } - ExplodedNode *&getPredecessor() { return Pred; } - const GRState *getState() { return ST ? ST : B.GetState(Pred); } - - ASTContext &getASTContext() { - return Eng.getContext(); - } - - BugReporter &getBugReporter() { - return Eng.getBugReporter(); - } - - SourceManager &getSourceManager() { - return getBugReporter().getSourceManager(); - } - - SValBuilder &getSValBuilder() { - return Eng.getSValBuilder(); - } - - ExplodedNode *generateNode(bool autoTransition = true) { - assert(statement && "Only transitions with statements currently supported"); - ExplodedNode *N = generateNodeImpl(statement, getState(), false, - checkerTag); - if (N && autoTransition) - Dst.Add(N); - return N; - } - - ExplodedNode *generateNode(const Stmt *stmt, const GRState *state, - bool autoTransition = true, const void *tag = 0) { - assert(state); - ExplodedNode *N = generateNodeImpl(stmt, state, false, - tag ? tag : checkerTag); - if (N && autoTransition) - addTransition(N); - return N; - } - - ExplodedNode *generateNode(const GRState *state, ExplodedNode *pred, - bool autoTransition = true) { - assert(statement && "Only transitions with statements currently supported"); - ExplodedNode *N = generateNodeImpl(statement, state, pred, false); - if (N && autoTransition) - addTransition(N); - return N; - } - - ExplodedNode *generateNode(const GRState *state, bool autoTransition = true, - const void *tag = 0) { - assert(statement && "Only transitions with statements currently supported"); - ExplodedNode *N = generateNodeImpl(statement, state, false, - tag ? tag : checkerTag); - if (N && autoTransition) - addTransition(N); - return N; - } - - ExplodedNode *generateSink(const Stmt *stmt, const GRState *state = 0) { - return generateNodeImpl(stmt, state ? state : getState(), true, - checkerTag); - } - - ExplodedNode *generateSink(const GRState *state = 0) { - assert(statement && "Only transitions with statements currently supported"); - return generateNodeImpl(statement, state ? state : getState(), true, - checkerTag); - } - - void addTransition(ExplodedNode *node) { - Dst.Add(node); - } - - void addTransition(const GRState *state, const void *tag = 0) { - assert(state); - // If the 'state' is not new, we need to check if the cached state 'ST' - // is new. - if (state != getState() || (ST && ST != B.GetState(Pred))) - // state is new or equals to ST. - generateNode(state, true, tag); - else - Dst.Add(Pred); - } - - void EmitReport(BugReport *R) { - Eng.getBugReporter().EmitReport(R); - } - - AnalysisContext *getCurrentAnalysisContext() const { - return Pred->getLocationContext()->getAnalysisContext(); - } - -private: - ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state, - bool markAsSink, const void *tag) { - ExplodedNode *node = B.generateNode(stmt, state, Pred, tag); - if (markAsSink && node) - node->markAsSink(); - return node; - } - - ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state, - ExplodedNode *pred, bool markAsSink) { - ExplodedNode *node = B.generateNode(stmt, state, pred, checkerTag); - if (markAsSink && node) - node->markAsSink(); - return node; - } -}; - class Checker { private: friend class ExprEngine; diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h new file mode 100644 index 0000000..4429c6b --- /dev/null +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -0,0 +1,187 @@ +//== CheckerContext.h - Context info for path-sensitive checkers--*- 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 CheckerContext that provides contextual info for +// path-sensitive checkers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT +#define LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT + +#include "clang/Analysis/Support/SaveAndRestore.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" + +namespace clang { + +namespace ento { + +class CheckerContext { + ExplodedNodeSet &Dst; + StmtNodeBuilder &B; + ExprEngine &Eng; + ExplodedNode *Pred; + SaveAndRestore<bool> OldSink; + const void *checkerTag; + SaveAndRestore<ProgramPoint::Kind> OldPointKind; + SaveOr OldHasGen; + const GRState *ST; + const Stmt *statement; + const unsigned size; +public: + bool *respondsToCallback; +public: + CheckerContext(ExplodedNodeSet &dst, StmtNodeBuilder &builder, + ExprEngine &eng, ExplodedNode *pred, + const void *tag, ProgramPoint::Kind K, + bool *respondsToCB = 0, + const Stmt *stmt = 0, const GRState *st = 0) + : Dst(dst), B(builder), Eng(eng), Pred(pred), + OldSink(B.BuildSinks), + checkerTag(tag), + OldPointKind(B.PointKind, K), + OldHasGen(B.hasGeneratedNode), + ST(st), statement(stmt), size(Dst.size()), + respondsToCallback(respondsToCB) {} + + ~CheckerContext(); + + ExprEngine &getEngine() { + return Eng; + } + + AnalysisManager &getAnalysisManager() { + return Eng.getAnalysisManager(); + } + + ConstraintManager &getConstraintManager() { + return Eng.getConstraintManager(); + } + + StoreManager &getStoreManager() { + return Eng.getStoreManager(); + } + + ExplodedNodeSet &getNodeSet() { return Dst; } + StmtNodeBuilder &getNodeBuilder() { return B; } + ExplodedNode *&getPredecessor() { return Pred; } + const GRState *getState() { return ST ? ST : B.GetState(Pred); } + const Stmt *getStmt() const { return statement; } + + ASTContext &getASTContext() { + return Eng.getContext(); + } + + BugReporter &getBugReporter() { + return Eng.getBugReporter(); + } + + SourceManager &getSourceManager() { + return getBugReporter().getSourceManager(); + } + + SValBuilder &getSValBuilder() { + return Eng.getSValBuilder(); + } + + ExplodedNode *generateNode(bool autoTransition = true) { + assert(statement && "Only transitions with statements currently supported"); + ExplodedNode *N = generateNodeImpl(statement, getState(), false, + checkerTag); + if (N && autoTransition) + Dst.Add(N); + return N; + } + + ExplodedNode *generateNode(const Stmt *stmt, const GRState *state, + bool autoTransition = true, const void *tag = 0) { + assert(state); + ExplodedNode *N = generateNodeImpl(stmt, state, false, + tag ? tag : checkerTag); + if (N && autoTransition) + addTransition(N); + return N; + } + + ExplodedNode *generateNode(const GRState *state, ExplodedNode *pred, + bool autoTransition = true) { + assert(statement && "Only transitions with statements currently supported"); + ExplodedNode *N = generateNodeImpl(statement, state, pred, false); + if (N && autoTransition) + addTransition(N); + return N; + } + + ExplodedNode *generateNode(const GRState *state, bool autoTransition = true, + const void *tag = 0) { + assert(statement && "Only transitions with statements currently supported"); + ExplodedNode *N = generateNodeImpl(statement, state, false, + tag ? tag : checkerTag); + if (N && autoTransition) + addTransition(N); + return N; + } + + ExplodedNode *generateSink(const Stmt *stmt, const GRState *state = 0) { + return generateNodeImpl(stmt, state ? state : getState(), true, + checkerTag); + } + + ExplodedNode *generateSink(const GRState *state = 0) { + assert(statement && "Only transitions with statements currently supported"); + return generateNodeImpl(statement, state ? state : getState(), true, + checkerTag); + } + + void addTransition(ExplodedNode *node) { + Dst.Add(node); + } + + void addTransition(const GRState *state, const void *tag = 0) { + assert(state); + // If the 'state' is not new, we need to check if the cached state 'ST' + // is new. + if (state != getState() || (ST && ST != B.GetState(Pred))) + // state is new or equals to ST. + generateNode(state, true, tag); + else + Dst.Add(Pred); + } + + void EmitReport(BugReport *R) { + Eng.getBugReporter().EmitReport(R); + } + + AnalysisContext *getCurrentAnalysisContext() const { + return Pred->getLocationContext()->getAnalysisContext(); + } + +private: + ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state, + bool markAsSink, const void *tag) { + ExplodedNode *node = B.generateNode(stmt, state, Pred, tag); + if (markAsSink && node) + node->markAsSink(); + return node; + } + + ExplodedNode *generateNodeImpl(const Stmt* stmt, const GRState *state, + ExplodedNode *pred, bool markAsSink) { + ExplodedNode *node = B.generateNode(stmt, state, pred, checkerTag); + if (markAsSink && node) + node->markAsSink(); + return node; + } +}; + +} // end GR namespace + +} // end clang namespace + +#endif diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 800e63a..25c6447 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -447,16 +447,22 @@ class EndOfFunctionNodeBuilder { CoreEngine &Eng; const CFGBlock& B; ExplodedNode* Pred; + void *Tag; public: bool hasGeneratedNode; public: - EndOfFunctionNodeBuilder(const CFGBlock* b, ExplodedNode* N, CoreEngine* e) - : Eng(*e), B(*b), Pred(N), hasGeneratedNode(false) {} + EndOfFunctionNodeBuilder(const CFGBlock* b, ExplodedNode* N, CoreEngine* e, + void *checkerTag = 0) + : Eng(*e), B(*b), Pred(N), Tag(checkerTag), hasGeneratedNode(false) {} ~EndOfFunctionNodeBuilder(); + EndOfFunctionNodeBuilder withCheckerTag(void *tag) { + return EndOfFunctionNodeBuilder(&B, Pred, &Eng, tag); + } + WorkList &getWorkList() { return *Eng.WList; } ExplodedNode* getPredecessor() const { return Pred; } @@ -471,8 +477,8 @@ public: B.getBlockID()); } - ExplodedNode* generateNode(const GRState* State, const void *tag = 0, - ExplodedNode *P = 0); + ExplodedNode* generateNode(const GRState* State, ExplodedNode *P = 0, + const void *tag = 0); void GenerateCallExitNode(const GRState *state); diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 767644a..16f54ee 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -137,6 +137,10 @@ public: virtual AnalysisManager &getAnalysisManager() { return AMgr; } + CheckerManager &getCheckerManager() const { + return *AMgr.getCheckerManager(); + } + SValBuilder &getSValBuilder() { return svalBuilder; } TransferFuncs& getTF() { return *TF; } diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h index 411441f..07cdbf5 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h @@ -151,7 +151,21 @@ namespace ento { typedef bool data_type; static inline data_type MakeData(void* const* p) { - return (bool) (uintptr_t) p; + return p ? (data_type) (uintptr_t) *p + : data_type(); + } + static inline void *MakeVoidPtr(data_type d) { + return (void*) (uintptr_t) d; + } + }; + + // Partial specialization for unsigned. + template <> struct GRStatePartialTrait<unsigned> { + typedef unsigned data_type; + + static inline data_type MakeData(void* const* p) { + return p ? (data_type) (uintptr_t) *p + : data_type(); } static inline void *MakeVoidPtr(data_type d) { return (void*) (uintptr_t) d; diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h index 4c3e379..9d6298f 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h @@ -12,12 +12,15 @@ namespace clang { class AnalyzerOptions; + class LangOptions; class Diagnostic; namespace ento { class CheckerManager; -CheckerManager *registerCheckers(const AnalyzerOptions &opts,Diagnostic &diags); +CheckerManager *registerCheckers(const AnalyzerOptions &opts, + const LangOptions &langOpts, + Diagnostic &diags); } // end ento namespace diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h index e3867a2..f014181 100644 --- a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h +++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h @@ -26,6 +26,8 @@ protected: llvm::StringRef InFile); }; +void printCheckerHelp(llvm::raw_ostream &OS); + } // end GR namespace } // end namespace clang diff --git a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp index 945dfb8..9c24550 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTContext.cpp @@ -205,7 +205,7 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, DeclarationNames(*this), ExternalSource(0), Listener(0), PrintingPolicy(LOpts), LastSDM(0, 0), - UniqueBlockByRefTypeID(0), UniqueBlockParmTypeID(0) { + UniqueBlockByRefTypeID(0) { ObjCIdRedefinitionType = QualType(); ObjCClassRedefinitionType = QualType(); ObjCSelRedefinitionType = QualType(); @@ -874,7 +874,7 @@ ASTContext::getTypeInfo(const Type *T) const { case Type::Auto: { const AutoType *A = cast<AutoType>(T); assert(A->isDeduced() && "Cannot request the size of a dependent type"); - return getTypeInfo(cast<AutoType>(T)->getDeducedType().getTypePtr()); + return getTypeInfo(A->getDeducedType().getTypePtr()); } case Type::Paren: @@ -2683,12 +2683,22 @@ QualType ASTContext::getDecltypeType(Expr *e) const { return QualType(dt, 0); } -/// getAutoType - Unlike many "get<Type>" functions, we don't unique -/// AutoType AST's. +/// getAutoType - We only unique auto types after they've been deduced. QualType ASTContext::getAutoType(QualType DeducedType) const { - AutoType *at = new (*this, TypeAlignment) AutoType(DeducedType); - Types.push_back(at); - return QualType(at, 0); + void *InsertPos = 0; + if (!DeducedType.isNull()) { + // Look in the folding set for an existing type. + llvm::FoldingSetNodeID ID; + AutoType::Profile(ID, DeducedType); + if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(AT, 0); + } + + AutoType *AT = new (*this, TypeAlignment) AutoType(DeducedType); + Types.push_back(AT); + if (InsertPos) + AutoTypes.InsertNode(AT, InsertPos); + return QualType(AT, 0); } /// getTagDeclType - Return the unique reference to the type for the @@ -2971,7 +2981,15 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { case NestedNameSpecifier::Namespace: // A namespace is canonical; build a nested-name-specifier with // this namespace and no prefix. - return NestedNameSpecifier::Create(*this, 0, NNS->getAsNamespace()); + return NestedNameSpecifier::Create(*this, 0, + NNS->getAsNamespace()->getOriginalNamespace()); + + case NestedNameSpecifier::NamespaceAlias: + // A namespace is canonical; build a nested-name-specifier with + // this namespace and no prefix. + return NestedNameSpecifier::Create(*this, 0, + NNS->getAsNamespaceAlias()->getNamespace() + ->getOriginalNamespace()); case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: { @@ -3609,78 +3627,6 @@ ASTContext::BuildByRefType(llvm::StringRef DeclName, QualType Ty) const { return getPointerType(getTagDeclType(T)); } - -QualType ASTContext::getBlockParmType( - bool BlockHasCopyDispose, - llvm::SmallVectorImpl<const Expr *> &Layout) const { - - // FIXME: Move up - llvm::SmallString<36> Name; - llvm::raw_svector_ostream(Name) << "__block_literal_" - << ++UniqueBlockParmTypeID; - RecordDecl *T; - T = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(), - &Idents.get(Name.str())); - T->startDefinition(); - QualType FieldTypes[] = { - getPointerType(VoidPtrTy), - IntTy, - IntTy, - getPointerType(VoidPtrTy), - (BlockHasCopyDispose ? - getPointerType(getBlockDescriptorExtendedType()) : - getPointerType(getBlockDescriptorType())) - }; - - const char *FieldNames[] = { - "__isa", - "__flags", - "__reserved", - "__FuncPtr", - "__descriptor" - }; - - for (size_t i = 0; i < 5; ++i) { - FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), - &Idents.get(FieldNames[i]), - FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, /*Mutable=*/false); - Field->setAccess(AS_public); - T->addDecl(Field); - } - - for (unsigned i = 0; i < Layout.size(); ++i) { - const Expr *E = Layout[i]; - - QualType FieldType = E->getType(); - IdentifierInfo *FieldName = 0; - if (isa<CXXThisExpr>(E)) { - FieldName = &Idents.get("this"); - } else if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E)) { - const ValueDecl *D = BDRE->getDecl(); - FieldName = D->getIdentifier(); - if (BDRE->isByRef()) - FieldType = BuildByRefType(D->getName(), FieldType); - } else { - // Padding. - assert(isa<ConstantArrayType>(FieldType) && - isa<DeclRefExpr>(E) && - !cast<DeclRefExpr>(E)->getDecl()->getDeclName() && - "doesn't match characteristics of padding decl"); - } - - FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), - FieldName, FieldType, /*TInfo=*/0, - /*BitWidth=*/0, /*Mutable=*/false); - Field->setAccess(AS_public); - T->addDecl(Field); - } - - T->completeDefinition(); - - return getPointerType(getTagDeclType(T)); -} - void ASTContext::setObjCFastEnumerationStateType(QualType T) { const RecordType *Rec = T->getAs<RecordType>(); assert(Rec && "Invalid ObjCFAstEnumerationStateType"); diff --git a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp index 65c0a3b..21f10fb 100644 --- a/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ASTImporter.cpp @@ -2097,11 +2097,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { D->isScoped(), D->isScopedUsingClassTag(), D->isFixed()); // Import the qualifier, if any. - if (D->getQualifier()) { - NestedNameSpecifier *NNS = Importer.Import(D->getQualifier()); - SourceRange NNSRange = Importer.Import(D->getQualifierRange()); - D2->setQualifierInfo(NNS, NNSRange); - } + D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); D2->setAccess(D->getAccess()); D2->setLexicalDeclContext(LexicalDC); Importer.Imported(D, D2); @@ -2225,12 +2221,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { Name.getAsIdentifierInfo(), Importer.Import(D->getTagKeywordLoc())); } - // Import the qualifier, if any. - if (D->getQualifier()) { - NestedNameSpecifier *NNS = Importer.Import(D->getQualifier()); - SourceRange NNSRange = Importer.Import(D->getQualifierRange()); - D2->setQualifierInfo(NNS, NNSRange); - } + + D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); D2->setLexicalDeclContext(LexicalDC); LexicalDC->addDecl(D2); } @@ -2408,11 +2400,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } // Import the qualifier, if any. - if (D->getQualifier()) { - NestedNameSpecifier *NNS = Importer.Import(D->getQualifier()); - SourceRange NNSRange = Importer.Import(D->getQualifierRange()); - ToFunction->setQualifierInfo(NNS, NNSRange); - } + ToFunction->setQualifierInfo(Importer.Import(D->getQualifierLoc())); ToFunction->setAccess(D->getAccess()); ToFunction->setLexicalDeclContext(LexicalDC); ToFunction->setVirtualAsWritten(D->isVirtualAsWritten()); @@ -2666,12 +2654,7 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { Name.getAsIdentifierInfo(), T, TInfo, D->getStorageClass(), D->getStorageClassAsWritten()); - // Import the qualifier, if any. - if (D->getQualifier()) { - NestedNameSpecifier *NNS = Importer.Import(D->getQualifier()); - SourceRange NNSRange = Importer.Import(D->getQualifierRange()); - ToVar->setQualifierInfo(NNS, NNSRange); - } + ToVar->setQualifierInfo(Importer.Import(D->getQualifierLoc())); ToVar->setAccess(D->getAccess()); ToVar->setLexicalDeclContext(LexicalDC); Importer.Imported(D, ToVar); @@ -3591,14 +3574,7 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { Name.getAsIdentifierInfo(), Importer.Import(DTemplated->getTagKeywordLoc())); D2Templated->setAccess(DTemplated->getAccess()); - - - // Import the qualifier, if any. - if (DTemplated->getQualifier()) { - NestedNameSpecifier *NNS = Importer.Import(DTemplated->getQualifier()); - SourceRange NNSRange = Importer.Import(DTemplated->getQualifierRange()); - D2Templated->setQualifierInfo(NNS, NNSRange); - } + D2Templated->setQualifierInfo(Importer.Import(DTemplated->getQualifierLoc())); D2Templated->setLexicalDeclContext(LexicalDC); // Create the class template declaration itself. @@ -3703,12 +3679,7 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( ClassTemplate->AddSpecialization(D2, InsertPos); // Import the qualifier, if any. - if (D->getQualifier()) { - NestedNameSpecifier *NNS = Importer.Import(D->getQualifier()); - SourceRange NNSRange = Importer.Import(D->getQualifierRange()); - D2->setQualifierInfo(NNS, NNSRange); - } - + D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); // Add the specialization to this context. D2->setLexicalDeclContext(LexicalDC); @@ -4067,6 +4038,11 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { return 0; } +NestedNameSpecifierLoc ASTImporter::Import(NestedNameSpecifierLoc FromNNS) { + // FIXME: Implement! + return NestedNameSpecifierLoc(); +} + TemplateName ASTImporter::Import(TemplateName From) { switch (From.getKind()) { case TemplateName::Template: diff --git a/contrib/llvm/tools/clang/lib/AST/Decl.cpp b/contrib/llvm/tools/clang/lib/AST/Decl.cpp index 56db8c7..73fe117 100644 --- a/contrib/llvm/tools/clang/lib/AST/Decl.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Decl.cpp @@ -266,8 +266,12 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { return LinkageInfo::internal(); } - if (D->isInAnonymousNamespace()) - return LinkageInfo::uniqueExternal(); + if (D->isInAnonymousNamespace()) { + const VarDecl *Var = dyn_cast<VarDecl>(D); + const FunctionDecl *Func = dyn_cast<FunctionDecl>(D); + if ((!Var || !Var->isExternC()) && (!Func || !Func->isExternC())) + return LinkageInfo::uniqueExternal(); + } // Set up the defaults. @@ -704,7 +708,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) { // external linkage. if (D->getLexicalDeclContext()->isFunctionOrMethod()) { if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { - if (Function->isInAnonymousNamespace()) + if (Function->isInAnonymousNamespace() && !Function->isExternC()) return LinkageInfo::uniqueExternal(); LinkageInfo LV; @@ -725,7 +729,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) { if (const VarDecl *Var = dyn_cast<VarDecl>(D)) if (Var->getStorageClass() == SC_Extern || Var->getStorageClass() == SC_PrivateExtern) { - if (Var->isInAnonymousNamespace()) + if (Var->isInAnonymousNamespace() && !Var->isExternC()) return LinkageInfo::uniqueExternal(); LinkageInfo LV; @@ -837,8 +841,10 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { // UsingDirectiveDecl's are not really NamedDecl's, and all have same name. // We want to keep it, unless it nominates same namespace. if (getKind() == Decl::UsingDirective) { - return cast<UsingDirectiveDecl>(this)->getNominatedNamespace() == - cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace(); + return cast<UsingDirectiveDecl>(this)->getNominatedNamespace() + ->getOriginalNamespace() == + cast<UsingDirectiveDecl>(OldD)->getNominatedNamespace() + ->getOriginalNamespace(); } if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this)) @@ -864,9 +870,13 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { return cast<UsingShadowDecl>(this)->getTargetDecl() == cast<UsingShadowDecl>(OldD)->getTargetDecl(); - if (isa<UsingDecl>(this) && isa<UsingDecl>(OldD)) - return cast<UsingDecl>(this)->getTargetNestedNameDecl() == - cast<UsingDecl>(OldD)->getTargetNestedNameDecl(); + if (isa<UsingDecl>(this) && isa<UsingDecl>(OldD)) { + ASTContext &Context = getASTContext(); + return Context.getCanonicalNestedNameSpecifier( + cast<UsingDecl>(this)->getQualifier()) == + Context.getCanonicalNestedNameSpecifier( + cast<UsingDecl>(OldD)->getQualifier()); + } // For non-function declarations, if the declarations are of the // same kind then this must be a redeclaration, or semantic analysis @@ -927,9 +937,8 @@ SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const { return SourceLocation(); } -void DeclaratorDecl::setQualifierInfo(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange) { - if (Qualifier) { +void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { + if (QualifierLoc) { // Make sure the extended decl info is allocated. if (!hasExtInfo()) { // Save (non-extended) type source info pointer. @@ -940,12 +949,10 @@ void DeclaratorDecl::setQualifierInfo(NestedNameSpecifier *Qualifier, getExtInfo()->TInfo = savedTInfo; } // Set qualifier info. - getExtInfo()->NNS = Qualifier; - getExtInfo()->NNSRange = QualifierRange; + getExtInfo()->QualifierLoc = QualifierLoc; } else { // Here Qualifier == 0, i.e., we are removing the qualifier (if any). - assert(QualifierRange.isInvalid()); if (hasExtInfo()) { // Save type source info pointer. TypeSourceInfo *savedTInfo = getExtInfo()->TInfo; @@ -967,7 +974,7 @@ QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context, TemplateParameterList **TPLists) { assert((NumTPLists == 0 || TPLists != 0) && "Empty array of template parameters with positive size!"); - assert((NumTPLists == 0 || NNS) && + assert((NumTPLists == 0 || QualifierLoc) && "Nonempty array of template parameters with no qualifier!"); // Free previous template parameters (if any). @@ -1037,8 +1044,11 @@ bool VarDecl::isExternC() const { getStorageClass() != SC_Static) || (getDeclContext()->isFunctionOrMethod() && hasExternalStorage()); - for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit(); - DC = DC->getParent()) { + const DeclContext *DC = getDeclContext(); + if (DC->isFunctionOrMethod()) + return false; + + for (; !DC->isTranslationUnit(); DC = DC->getParent()) { if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) { if (Linkage->getLanguage() == LinkageSpecDecl::lang_c) return getStorageClass() != SC_Static; @@ -1046,8 +1056,6 @@ bool VarDecl::isExternC() const { break; } - if (DC->isFunctionOrMethod()) - return false; } return false; @@ -1363,8 +1371,11 @@ bool FunctionDecl::isExternC() const { if (!Context.getLangOptions().CPlusPlus) return getStorageClass() != SC_Static && !getAttr<OverloadableAttr>(); - for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit(); - DC = DC->getParent()) { + const DeclContext *DC = getDeclContext(); + if (DC->isRecord()) + return false; + + for (; !DC->isTranslationUnit(); DC = DC->getParent()) { if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) { if (Linkage->getLanguage() == LinkageSpecDecl::lang_c) return getStorageClass() != SC_Static && @@ -1372,9 +1383,6 @@ bool FunctionDecl::isExternC() const { break; } - - if (DC->isRecord()) - break; } return isMain(); @@ -2018,19 +2026,16 @@ TagDecl* TagDecl::getDefinition() const { return 0; } -void TagDecl::setQualifierInfo(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange) { - if (Qualifier) { +void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { + if (QualifierLoc) { // Make sure the extended qualifier info is allocated. if (!hasExtInfo()) TypedefDeclOrQualifier = new (getASTContext()) ExtInfo; // Set qualifier info. - getExtInfo()->NNS = Qualifier; - getExtInfo()->NNSRange = QualifierRange; + getExtInfo()->QualifierLoc = QualifierLoc; } else { // Here Qualifier == 0, i.e., we are removing the qualifier (if any). - assert(QualifierRange.isInvalid()); if (hasExtInfo()) { getASTContext().Deallocate(getExtInfo()); TypedefDeclOrQualifier = (TypedefDecl*) 0; @@ -2211,8 +2216,10 @@ NamespaceDecl *NamespaceDecl::getNextNamespace() { } ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, QualType T) { - return new (C) ImplicitParamDecl(ImplicitParam, DC, L, Id, T); + SourceLocation loc, + IdentifierInfo *name, + QualType type) { + return new (C) ImplicitParamDecl(DC, loc, name, type); } FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, diff --git a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp index be379d5..81df00d 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclBase.cpp @@ -465,6 +465,22 @@ void Decl::CheckAccessDeclContext() const { #endif } +DeclContext *Decl::getNonClosureContext() { + DeclContext *DC = getDeclContext(); + + // This is basically "while (DC->isClosure()) DC = DC->getParent();" + // except that it's significantly more efficient to cast to a known + // decl type and call getDeclContext() than to call getParent(). + do { + if (isa<BlockDecl>(DC)) { + DC = cast<BlockDecl>(DC)->getDeclContext(); + continue; + } + } while (false); + + assert(!DC->isClosure()); + return DC; +} //===----------------------------------------------------------------------===// // DeclContext Implementation diff --git a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp index fba73f5..46768c1 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp @@ -1267,15 +1267,14 @@ LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, SourceLocation NamespaceLoc, - SourceRange QualifierRange, - NestedNameSpecifier *Qualifier, + NestedNameSpecifierLoc QualifierLoc, SourceLocation IdentLoc, NamedDecl *Used, DeclContext *CommonAncestor) { if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Used)) Used = NS->getOriginalNamespace(); - return new (C) UsingDirectiveDecl(DC, L, NamespaceLoc, QualifierRange, - Qualifier, IdentLoc, Used, CommonAncestor); + return new (C) UsingDirectiveDecl(DC, L, NamespaceLoc, QualifierLoc, + IdentLoc, Used, CommonAncestor); } NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() { @@ -1289,14 +1288,13 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, SourceLocation AliasLoc, IdentifierInfo *Alias, - SourceRange QualifierRange, - NestedNameSpecifier *Qualifier, + NestedNameSpecifierLoc QualifierLoc, SourceLocation IdentLoc, NamedDecl *Namespace) { if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Namespace)) Namespace = NS->getOriginalNamespace(); - return new (C) NamespaceAliasDecl(DC, UsingLoc, AliasLoc, Alias, QualifierRange, - Qualifier, IdentLoc, Namespace); + return new (C) NamespaceAliasDecl(DC, UsingLoc, AliasLoc, Alias, + QualifierLoc, IdentLoc, Namespace); } UsingDecl *UsingShadowDecl::getUsingDecl() const { @@ -1337,35 +1335,31 @@ void UsingDecl::removeShadowDecl(UsingShadowDecl *S) { S->UsingOrNextShadow = this; } -UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, - SourceRange NNR, SourceLocation UL, - NestedNameSpecifier* TargetNNS, +UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UL, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool IsTypeNameArg) { - return new (C) UsingDecl(DC, NNR, UL, TargetNNS, NameInfo, IsTypeNameArg); + return new (C) UsingDecl(DC, UL, QualifierLoc, NameInfo, IsTypeNameArg); } UnresolvedUsingValueDecl * UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, - SourceRange TargetNNR, - NestedNameSpecifier *TargetNNS, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo) { return new (C) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc, - TargetNNR, TargetNNS, NameInfo); + QualifierLoc, NameInfo); } UnresolvedUsingTypenameDecl * UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, SourceLocation TypenameLoc, - SourceRange TargetNNR, - NestedNameSpecifier *TargetNNS, + NestedNameSpecifierLoc QualifierLoc, SourceLocation TargetNameLoc, DeclarationName TargetName) { return new (C) UnresolvedUsingTypenameDecl(DC, UsingLoc, TypenameLoc, - TargetNNR, TargetNNS, - TargetNameLoc, + QualifierLoc, TargetNameLoc, TargetName.getAsIdentifierInfo()); } diff --git a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp index 77b4257..c6ae128 100644 --- a/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/AST/DeclPrinter.cpp @@ -918,20 +918,20 @@ void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) { void DeclPrinter::VisitUsingDecl(UsingDecl *D) { Out << "using "; - D->getTargetNestedNameDecl()->print(Out, Policy); + D->getQualifier()->print(Out, Policy); Out << D; } void DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { Out << "using typename "; - D->getTargetNestedNameSpecifier()->print(Out, Policy); + D->getQualifier()->print(Out, Policy); Out << D->getDeclName(); } void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { Out << "using "; - D->getTargetNestedNameSpecifier()->print(Out, Policy); + D->getQualifier()->print(Out, Policy); Out << D->getDeclName(); } diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp index 391b26a..1c1061b 100644 --- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp @@ -836,6 +836,19 @@ QualType CallExpr::getCallReturnType() const { return FnType->getResultType(); } +SourceRange CallExpr::getSourceRange() const { + if (isa<CXXOperatorCallExpr>(this)) + return cast<CXXOperatorCallExpr>(this)->getSourceRange(); + + SourceLocation begin = getCallee()->getLocStart(); + if (begin.isInvalid() && getNumArgs() > 0) + begin = getArg(0)->getLocStart(); + SourceLocation end = getRParenLoc(); + if (end.isInvalid() && getNumArgs() > 0) + end = getArg(getNumArgs() - 1)->getLocEnd(); + return SourceRange(begin, end); +} + OffsetOfExpr *OffsetOfExpr::Create(ASTContext &C, QualType type, SourceLocation OperatorLoc, TypeSourceInfo *tsi, diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp index 28ff9fb..4f4a6b4 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp @@ -128,10 +128,10 @@ PseudoDestructorTypeStorage::PseudoDestructorTypeStorage(TypeSourceInfo *Info) } CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(ASTContext &Context, - Expr *Base, bool isArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - TypeSourceInfo *ScopeType, SourceLocation ColonColonLoc, - SourceLocation TildeLoc, PseudoDestructorTypeStorage DestroyedType) + Expr *Base, bool isArrow, SourceLocation OperatorLoc, + NestedNameSpecifierLoc QualifierLoc, TypeSourceInfo *ScopeType, + SourceLocation ColonColonLoc, SourceLocation TildeLoc, + PseudoDestructorTypeStorage DestroyedType) : Expr(CXXPseudoDestructorExprClass, Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0, FunctionProtoType::ExtProtoInfo())), @@ -142,15 +142,16 @@ CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(ASTContext &Context, /*isValueDependent=*/Base->isValueDependent(), // ContainsUnexpandedParameterPack (Base->containsUnexpandedParameterPack() || - (Qualifier && Qualifier->containsUnexpandedParameterPack()) || + (QualifierLoc && + QualifierLoc.getNestedNameSpecifier() + ->containsUnexpandedParameterPack()) || (ScopeType && ScopeType->getType()->containsUnexpandedParameterPack()) || (DestroyedType.getTypeSourceInfo() && DestroyedType.getTypeSourceInfo()->getType() ->containsUnexpandedParameterPack()))), Base(static_cast<Stmt *>(Base)), IsArrow(isArrow), - OperatorLoc(OperatorLoc), Qualifier(Qualifier), - QualifierRange(QualifierRange), + OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc), ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), TildeLoc(TildeLoc), DestroyedType(DestroyedType) { } @@ -282,15 +283,16 @@ CXXRecordDecl *OverloadExpr::getNamingClass() const { // DependentScopeDeclRefExpr DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *Args) : Expr(DependentScopeDeclRefExprClass, T, VK_LValue, OK_Ordinary, true, true, (NameInfo.containsUnexpandedParameterPack() || - (Qualifier && Qualifier->containsUnexpandedParameterPack()))), - NameInfo(NameInfo), QualifierRange(QualifierRange), Qualifier(Qualifier), + (QualifierLoc && + QualifierLoc.getNestedNameSpecifier() + ->containsUnexpandedParameterPack()))), + QualifierLoc(QualifierLoc), NameInfo(NameInfo), HasExplicitTemplateArgs(Args != 0) { if (Args) { @@ -306,16 +308,14 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T, DependentScopeDeclRefExpr * DependentScopeDeclRefExpr::Create(ASTContext &C, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *Args) { std::size_t size = sizeof(DependentScopeDeclRefExpr); if (Args) size += ExplicitTemplateArgumentList::sizeFor(*Args); void *Mem = C.Allocate(size); - return new (Mem) DependentScopeDeclRefExpr(C.DependentTy, - Qualifier, QualifierRange, + return new (Mem) DependentScopeDeclRefExpr(C.DependentTy, QualifierLoc, NameInfo, Args); } @@ -328,13 +328,16 @@ DependentScopeDeclRefExpr::CreateEmpty(ASTContext &C, size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs); void *Mem = C.Allocate(size); DependentScopeDeclRefExpr *E - = new (Mem) DependentScopeDeclRefExpr(QualType(), 0, SourceRange(), + = new (Mem) DependentScopeDeclRefExpr(QualType(), NestedNameSpecifierLoc(), DeclarationNameInfo(), 0); E->HasExplicitTemplateArgs = HasExplicitTemplateArgs; return E; } SourceRange CXXConstructExpr::getSourceRange() const { + if (isa<CXXTemporaryObjectExpr>(this)) + return cast<CXXTemporaryObjectExpr>(this)->getSourceRange(); + if (ParenRange.isValid()) return SourceRange(Loc, ParenRange.getEnd()); @@ -397,13 +400,6 @@ CXXRecordDecl *CXXMemberCallExpr::getRecordDecl() { return ThisArg->getType()->getAsCXXRecordDecl(); } -SourceRange CXXMemberCallExpr::getSourceRange() const { - SourceLocation LocStart = getCallee()->getLocStart(); - if (LocStart.isInvalid() && getNumArgs() > 0) - LocStart = getArg(0)->getLocStart(); - return SourceRange(LocStart, getRParenLoc()); -} - //===----------------------------------------------------------------------===// // Named casts diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp index 656bb99..3a5eb66 100644 --- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp @@ -2926,7 +2926,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { Exp->getOpcode() == BO_Rem) { // Evaluate gives an error for undefined Div/Rem, so make sure // we don't evaluate one. - if (LHSResult.Val != 2 && RHSResult.Val != 2) { + if (LHSResult.Val == 0 && RHSResult.Val == 0) { llvm::APSInt REval = Exp->getRHS()->EvaluateAsInt(Ctx); if (REval == 0) return ICEDiag(1, E->getLocStart()); diff --git a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp index d66c374..939ca7a 100644 --- a/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp +++ b/contrib/llvm/tools/clang/lib/AST/ItaniumMangle.cpp @@ -606,6 +606,9 @@ void CXXNameMangler::mangleUnresolvedScope(NestedNameSpecifier *Qualifier) { case NestedNameSpecifier::Namespace: mangleName(Qualifier->getAsNamespace()); break; + case NestedNameSpecifier::NamespaceAlias: + mangleName(Qualifier->getAsNamespaceAlias()->getNamespace()); + break; case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: { const Type *QTy = Qualifier->getAsType(); @@ -1647,8 +1650,11 @@ void CXXNameMangler::mangleType(const DecltypeType *T) { void CXXNameMangler::mangleType(const AutoType *T) { QualType D = T->getDeducedType(); - assert(!D.isNull() && "can't mangle undeduced auto type"); - mangleType(D); + // <builtin-type> ::= Da # dependent auto + if (D.isNull()) + Out << "Da"; + else + mangleType(D); } void CXXNameMangler::mangleIntegerLiteral(QualType T, diff --git a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp index 650321d..6f1ec05 100644 --- a/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp +++ b/contrib/llvm/tools/clang/lib/AST/NestedNameSpecifier.cpp @@ -14,8 +14,10 @@ #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" #include "llvm/Support/raw_ostream.h" #include <cassert> @@ -46,7 +48,7 @@ NestedNameSpecifier::Create(const ASTContext &Context, NestedNameSpecifier Mockup; Mockup.Prefix.setPointer(Prefix); - Mockup.Prefix.setInt(Identifier); + Mockup.Prefix.setInt(StoredIdentifier); Mockup.Specifier = II; return FindOrInsert(Context, Mockup); } @@ -60,19 +62,34 @@ NestedNameSpecifier::Create(const ASTContext &Context, "Broken nested name specifier"); NestedNameSpecifier Mockup; Mockup.Prefix.setPointer(Prefix); - Mockup.Prefix.setInt(Namespace); + Mockup.Prefix.setInt(StoredNamespaceOrAlias); Mockup.Specifier = NS; return FindOrInsert(Context, Mockup); } NestedNameSpecifier * NestedNameSpecifier::Create(const ASTContext &Context, + NestedNameSpecifier *Prefix, + NamespaceAliasDecl *Alias) { + assert(Alias && "Namespace alias cannot be NULL"); + assert((!Prefix || + (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) && + "Broken nested name specifier"); + NestedNameSpecifier Mockup; + Mockup.Prefix.setPointer(Prefix); + Mockup.Prefix.setInt(StoredNamespaceOrAlias); + Mockup.Specifier = Alias; + return FindOrInsert(Context, Mockup); +} + +NestedNameSpecifier * +NestedNameSpecifier::Create(const ASTContext &Context, NestedNameSpecifier *Prefix, bool Template, const Type *T) { assert(T && "Type cannot be NULL"); NestedNameSpecifier Mockup; Mockup.Prefix.setPointer(Prefix); - Mockup.Prefix.setInt(Template? TypeSpecWithTemplate : TypeSpec); + Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec); Mockup.Specifier = const_cast<Type*>(T); return FindOrInsert(Context, Mockup); } @@ -82,7 +99,7 @@ NestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) { assert(II && "Identifier cannot be NULL"); NestedNameSpecifier Mockup; Mockup.Prefix.setPointer(0); - Mockup.Prefix.setInt(Identifier); + Mockup.Prefix.setInt(StoredIdentifier); Mockup.Specifier = II; return FindOrInsert(Context, Mockup); } @@ -94,6 +111,47 @@ NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) { return Context.GlobalNestedNameSpecifier; } +NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { + if (Specifier == 0) + return Global; + + switch (Prefix.getInt()) { + case StoredIdentifier: + return Identifier; + + case StoredNamespaceOrAlias: + return isa<NamespaceDecl>(static_cast<NamedDecl *>(Specifier))? Namespace + : NamespaceAlias; + + case StoredTypeSpec: + return TypeSpec; + + case StoredTypeSpecWithTemplate: + return TypeSpecWithTemplate; + } + + return Global; +} + +/// \brief Retrieve the namespace stored in this nested name +/// specifier. +NamespaceDecl *NestedNameSpecifier::getAsNamespace() const { + if (Prefix.getInt() == StoredNamespaceOrAlias) + return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier)); + + return 0; +} + +/// \brief Retrieve the namespace alias stored in this nested name +/// specifier. +NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const { + if (Prefix.getInt() == StoredNamespaceOrAlias) + return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier)); + + return 0; +} + + /// \brief Whether this nested name specifier refers to a dependent /// type or not. bool NestedNameSpecifier::isDependent() const { @@ -103,6 +161,7 @@ bool NestedNameSpecifier::isDependent() const { return true; case Namespace: + case NamespaceAlias: case Global: return false; @@ -121,6 +180,7 @@ bool NestedNameSpecifier::containsUnexpandedParameterPack() const { return getPrefix() && getPrefix()->containsUnexpandedParameterPack(); case Namespace: + case NamespaceAlias: case Global: return false; @@ -147,7 +207,11 @@ NestedNameSpecifier::print(llvm::raw_ostream &OS, break; case Namespace: - OS << getAsNamespace()->getIdentifier()->getName(); + OS << getAsNamespace()->getName(); + break; + + case NamespaceAlias: + OS << getAsNamespaceAlias()->getName(); break; case Global: @@ -199,3 +263,111 @@ NestedNameSpecifier::print(llvm::raw_ostream &OS, void NestedNameSpecifier::dump(const LangOptions &LO) { print(llvm::errs(), PrintingPolicy(LO)); } + +unsigned +NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) { + assert(Qualifier && "Expected a non-NULL qualifier"); + + // Location of the trailing '::'. + unsigned Length = sizeof(unsigned); + + switch (Qualifier->getKind()) { + case NestedNameSpecifier::Global: + // Nothing more to add. + break; + + case NestedNameSpecifier::Identifier: + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: + // The location of the identifier or namespace name. + Length += sizeof(unsigned); + break; + + case NestedNameSpecifier::TypeSpecWithTemplate: + case NestedNameSpecifier::TypeSpec: + // The "void*" that points at the TypeLoc data. + // Note: the 'template' keyword is part of the TypeLoc. + Length += sizeof(void *); + break; + } + + return Length; +} + +unsigned +NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) { + unsigned Length = 0; + for (; Qualifier; Qualifier = Qualifier->getPrefix()) + Length += getLocalDataLength(Qualifier); + return Length; +} + +namespace { + /// \brief Load a (possibly unaligned) source location from a given address + /// and offset. + SourceLocation LoadSourceLocation(void *Data, unsigned Offset) { + unsigned Raw; + memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned)); + return SourceLocation::getFromRawEncoding(Raw); + } + + /// \brief Load a (possibly unaligned) pointer from a given address and + /// offset. + void *LoadPointer(void *Data, unsigned Offset) { + void *Result; + memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*)); + return Result; + } +} + +SourceRange NestedNameSpecifierLoc::getSourceRange() const { + if (!Qualifier) + return SourceRange(); + + NestedNameSpecifierLoc First = *this; + while (NestedNameSpecifierLoc Prefix = First.getPrefix()) + First = Prefix; + + return SourceRange(First.getLocalSourceRange().getBegin(), + getLocalSourceRange().getEnd()); +} + +SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { + if (!Qualifier) + return SourceRange(); + + unsigned Offset = getDataLength(Qualifier->getPrefix()); + switch (Qualifier->getKind()) { + case NestedNameSpecifier::Global: + return LoadSourceLocation(Data, Offset); + + case NestedNameSpecifier::Identifier: + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: + return SourceRange(LoadSourceLocation(Data, Offset), + LoadSourceLocation(Data, Offset + sizeof(unsigned))); + + case NestedNameSpecifier::TypeSpecWithTemplate: + case NestedNameSpecifier::TypeSpec: { + // The "void*" that points at the TypeLoc data. + // Note: the 'template' keyword is part of the TypeLoc. + void *TypeData = LoadPointer(Data, Offset); + TypeLoc TL(Qualifier->getAsType(), TypeData); + return SourceRange(TL.getBeginLoc(), + LoadSourceLocation(Data, Offset + sizeof(void*))); + } + } + + return SourceRange(); +} + +TypeLoc NestedNameSpecifierLoc::getTypeLoc() const { + assert((Qualifier->getKind() == NestedNameSpecifier::TypeSpec || + Qualifier->getKind() == NestedNameSpecifier::TypeSpecWithTemplate) && + "Nested-name-specifier location is not a type"); + + // The "void*" that points at the TypeLoc data. + unsigned Offset = getDataLength(Qualifier->getPrefix()); + void *TypeData = LoadPointer(Data, Offset); + return TypeLoc(Qualifier->getAsType(), TypeData); +} diff --git a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp index cf14eba..4ed031f 100644 --- a/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/AST/RecordLayoutBuilder.cpp @@ -698,6 +698,25 @@ protected: DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID); + CharUnits getSize() const { + assert(Size % Context.getCharWidth() == 0); + return Context.toCharUnitsFromBits(Size); + } + uint64_t getSizeInBits() const { return Size; } + + void setSize(CharUnits NewSize) { Size = Context.toBits(NewSize); } + void setSize(uint64_t NewSize) { Size = NewSize; } + + CharUnits getDataSize() const { + assert(DataSize % Context.getCharWidth() == 0); + return Context.toCharUnitsFromBits(DataSize); + } + uint64_t getDataSizeInBits() const { return DataSize; } + + void setDataSize(CharUnits NewSize) { DataSize = Context.toBits(NewSize); } + void setDataSize(uint64_t NewSize) { DataSize = NewSize; } + + RecordLayoutBuilder(const RecordLayoutBuilder&); // DO NOT IMPLEMENT void operator=(const RecordLayoutBuilder&); // DO NOT IMPLEMENT public: @@ -796,8 +815,8 @@ void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) { assert(DataSize == 0 && "Vtable pointer must be at offset zero!"); // Update the size. - Size += GetVirtualPointersSize(RD); - DataSize = Size; + setSize(getSizeInBits() + GetVirtualPointersSize(RD)); + setDataSize(getSizeInBits()); CharUnits UnpackedBaseAlign = Context.toCharUnitsFromBits(Context.Target.getPointerAlign(0)); @@ -1090,7 +1109,7 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { if (Base->Class->isEmpty() && EmptySubobjects->CanPlaceBaseAtOffset(Base, CharUnits::Zero())) { uint64_t RecordSizeInBits = Context.toBits(Layout.getSize()); - Size = std::max(Size, RecordSizeInBits); + setSize(std::max(getSizeInBits(), RecordSizeInBits)); return CharUnits::Zero(); } @@ -1106,7 +1125,7 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { // Round up the current record size to the base's alignment boundary. uint64_t Offset = - llvm::RoundUpToAlignment(DataSize, Context.toBits(BaseAlign)); + llvm::RoundUpToAlignment(getDataSizeInBits(), Context.toBits(BaseAlign)); // Try to place the base. while (!EmptySubobjects->CanPlaceBaseAtOffset(Base, @@ -1115,11 +1134,12 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { if (!Base->Class->isEmpty()) { // Update the data size. - DataSize = Offset + Context.toBits(Layout.getNonVirtualSize()); + setDataSize(Offset + Context.toBits(Layout.getNonVirtualSize())); - Size = std::max(Size, DataSize); + setSize(std::max(getSizeInBits(), getDataSizeInBits())); } else - Size = std::max(Size, Offset + Context.toBits(Layout.getSize())); + setSize(std::max(getSizeInBits(), + Offset + Context.toBits(Layout.getSize()))); // Remember max struct/class alignment. UpdateAlignment(BaseAlign, UnpackedBaseAlign); @@ -1167,7 +1187,8 @@ void RecordLayoutBuilder::Layout(const CXXRecordDecl *RD) { LayoutFields(RD); - NonVirtualSize = Context.toCharUnitsFromBits(Size); + // FIXME: Size isn't always an exact multiple of the char width. Round up? + NonVirtualSize = Context.toCharUnitsFromBits(getSizeInBits()); NonVirtualAlignment = Alignment; // Lay out the virtual bases and add the primary virtual base offsets. @@ -1211,8 +1232,8 @@ void RecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D) { // We start laying out ivars not at the end of the superclass // structure, but at the next byte following the last field. - Size = Context.toBits(SL.getDataSize()); - DataSize = Size; + setSize(SL.getDataSize()); + setDataSize(getSizeInBits()); } InitializeLayout(D); @@ -1270,20 +1291,20 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, UnfilledBitsInLastByte = 0; uint64_t FieldOffset; - uint64_t UnpaddedFieldOffset = DataSize - UnfilledBitsInLastByte; + uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastByte; if (IsUnion) { - DataSize = std::max(DataSize, FieldSize); + setDataSize(std::max(getDataSizeInBits(), FieldSize)); FieldOffset = 0; } else { // The bitfield is allocated starting at the next offset aligned appropriately // for T', with length n bits. - FieldOffset = llvm::RoundUpToAlignment(DataSize, TypeAlign); + FieldOffset = llvm::RoundUpToAlignment(getDataSizeInBits(), TypeAlign); uint64_t NewSizeInBits = FieldOffset + FieldSize; - DataSize = llvm::RoundUpToAlignment(NewSizeInBits, 8); - UnfilledBitsInLastByte = DataSize - NewSizeInBits; + setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, 8)); + UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits; } // Place this field at the current location. @@ -1293,7 +1314,7 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, TypeAlign, FieldPacked, D); // Update the size. - Size = std::max(Size, DataSize); + setSize(std::max(getSizeInBits(), getDataSizeInBits())); // Remember max struct/class alignment. UpdateAlignment(Context.toCharUnitsFromBits(TypeAlign)); @@ -1301,7 +1322,7 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { bool FieldPacked = Packed || D->hasAttr<PackedAttr>(); - uint64_t UnpaddedFieldOffset = DataSize - UnfilledBitsInLastByte; + uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastByte; uint64_t FieldOffset = IsUnion ? 0 : UnpaddedFieldOffset; uint64_t FieldSize = D->getBitWidth()->EvaluateAsInt(Context).getZExtValue(); @@ -1355,16 +1376,16 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // Update DataSize to include the last byte containing (part of) the bitfield. if (IsUnion) { // FIXME: I think FieldSize should be TypeSize here. - DataSize = std::max(DataSize, FieldSize); + setDataSize(std::max(getDataSizeInBits(), FieldSize)); } else { uint64_t NewSizeInBits = FieldOffset + FieldSize; - DataSize = llvm::RoundUpToAlignment(NewSizeInBits, 8); - UnfilledBitsInLastByte = DataSize - NewSizeInBits; + setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, 8)); + UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits; } // Update the size. - Size = std::max(Size, DataSize); + setSize(std::max(getSizeInBits(), getDataSizeInBits())); // Remember max struct/class alignment. UpdateAlignment(Context.toCharUnitsFromBits(FieldAlign), @@ -1377,14 +1398,14 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { return; } - uint64_t UnpaddedFieldOffset = DataSize - UnfilledBitsInLastByte; + uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastByte; // Reset the unfilled bits. UnfilledBitsInLastByte = 0; bool FieldPacked = Packed || D->hasAttr<PackedAttr>(); CharUnits FieldOffset = - IsUnion ? CharUnits::Zero() : Context.toCharUnitsFromBits(DataSize); + IsUnion ? CharUnits::Zero() : getDataSize(); CharUnits FieldSize; CharUnits FieldAlign; @@ -1464,12 +1485,12 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { // Reserve space for this field. uint64_t FieldSizeInBits = Context.toBits(FieldSize); if (IsUnion) - Size = std::max(Size, FieldSizeInBits); + setSize(std::max(getSizeInBits(), FieldSizeInBits)); else - Size = Context.toBits(FieldOffset) + FieldSizeInBits; + setSize(Context.toBits(FieldOffset) + FieldSizeInBits); // Update the data size. - DataSize = Size; + setDataSize(getSizeInBits()); // Remember max struct/class alignment. UpdateAlignment(FieldAlign, UnpackedFieldAlign); @@ -1477,29 +1498,30 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) { // In C++, records cannot be of size 0. - if (Context.getLangOptions().CPlusPlus && Size == 0) { + if (Context.getLangOptions().CPlusPlus && getSizeInBits() == 0) { if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { // Compatibility with gcc requires a class (pod or non-pod) // which is not empty but of size 0; such as having fields of // array of zero-length, remains of Size 0 if (RD->isEmpty()) - Size = 8; + setSize(8); } else - Size = 8; + setSize(8); } // Finally, round the size of the record up to the alignment of the // record itself. - uint64_t UnpaddedSize = Size - UnfilledBitsInLastByte; + uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastByte; uint64_t UnpackedSize = - llvm::RoundUpToAlignment(Size, Context.toBits(UnpackedAlignment)); - Size = llvm::RoundUpToAlignment(Size, Context.toBits(Alignment)); + llvm::RoundUpToAlignment(getSizeInBits(), + Context.toBits(UnpackedAlignment)); + setSize(llvm::RoundUpToAlignment(getSizeInBits(), Context.toBits(Alignment))); unsigned CharBitNum = Context.Target.getCharWidth(); if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) { // Warn if padding was introduced to the struct/class/union. - if (Size > UnpaddedSize) { - unsigned PadSize = Size - UnpaddedSize; + if (getSizeInBits() > UnpaddedSize) { + unsigned PadSize = getSizeInBits() - UnpaddedSize; bool InBits = true; if (PadSize % CharBitNum == 0) { PadSize = PadSize / CharBitNum; @@ -1513,7 +1535,8 @@ void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) { // Warn if we packed it unnecessarily. If the alignment is 1 byte don't // bother since there won't be alignment issues. - if (Packed && UnpackedAlignment > CharUnits::One() && Size == UnpackedSize) + if (Packed && UnpackedAlignment > CharUnits::One() && + getSizeInBits() == UnpackedSize) Diag(D->getLocation(), diag::warn_unnecessary_packed) << Context.getTypeDeclType(RD); } diff --git a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp index 7e73f02..8a80275 100644 --- a/contrib/llvm/tools/clang/lib/AST/Stmt.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Stmt.cpp @@ -218,6 +218,10 @@ unsigned AsmStmt::getNumPlusOperands() const { Expr *AsmStmt::getInputExpr(unsigned i) { return cast<Expr>(Exprs[i + NumOutputs]); } +void AsmStmt::setInputExpr(unsigned i, Expr *E) { + Exprs[i + NumOutputs] = E; +} + /// getInputConstraint - Return the specified input constraint. Unlike output /// constraints, these can be empty. diff --git a/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp b/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp index 846bd4c..5c7dbb3 100644 --- a/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp +++ b/contrib/llvm/tools/clang/lib/AST/StmtDumper.cpp @@ -279,8 +279,8 @@ void StmtDumper::DumpDeclarator(Decl *D) { // print using decl (e.g. "using std::string;") const char *tn = UD->isTypeName() ? "typename " : ""; OS << '"' << UD->getDeclKindName() << tn; - UD->getTargetNestedNameDecl()->print(OS, - PrintingPolicy(UD->getASTContext().getLangOptions())); + UD->getQualifier()->print(OS, + PrintingPolicy(UD->getASTContext().getLangOptions())); OS << ";\""; } else if (LabelDecl *LD = dyn_cast<LabelDecl>(D)) { OS << "label " << LD->getNameAsString(); diff --git a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp index 5ab5f46..1764f4a 100644 --- a/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp +++ b/contrib/llvm/tools/clang/lib/AST/TemplateBase.cpp @@ -24,8 +24,6 @@ #include "llvm/ADT/FoldingSet.h" #include <algorithm> #include <cctype> -#include <iomanip> -#include <sstream> using namespace clang; @@ -42,17 +40,11 @@ static void printIntegral(const TemplateArgument &TemplArg, if (T->isBooleanType()) { Out << (Val->getBoolValue() ? "true" : "false"); } else if (T->isCharType()) { - char Ch = Val->getSExtValue(); - if (std::isprint(Ch)) { - Out << "'"; - if (Ch == '\'' || Ch == '\\') - Out << '\\'; - Out << Ch << "'"; - } else { - std::ostringstream Str; - Str << std::setw(2) << std::setfill('0') << std::hex << (int)Ch; - Out << "'\\x" << Str.str() << "'"; - } + const unsigned char Ch = Val->getZExtValue(); + const std::string Str(1, Ch); + Out << ((Ch == '\'') ? "'\\" : "'"); + Out.write_escaped(Str, /*UseHexEscapes=*/ true); + Out << "'"; } else { Out << Val->toString(10); } diff --git a/contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp b/contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp index 5233d3b..62097ef 100644 --- a/contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp +++ b/contrib/llvm/tools/clang/lib/Analysis/AnalysisContext.cpp @@ -19,8 +19,10 @@ #include "clang/AST/StmtVisitor.h" #include "clang/Analysis/Analyses/LiveVariables.h" #include "clang/Analysis/Analyses/PseudoConstantAnalysis.h" +#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" #include "clang/Analysis/AnalysisContext.h" #include "clang/Analysis/CFG.h" +#include "clang/Analysis/CFGStmtMap.h" #include "clang/Analysis/Support/BumpVector.h" #include "llvm/ADT/SmallSet.h" #include "llvm/Support/ErrorHandling.h" @@ -86,6 +88,30 @@ CFG *AnalysisContext::getUnoptimizedCFG() { return completeCFG; } +CFGStmtMap *AnalysisContext::getCFGStmtMap() { + if (cfgStmtMap) + return cfgStmtMap; + + if (CFG *c = getCFG()) { + cfgStmtMap = CFGStmtMap::Build(c, &getParentMap()); + return cfgStmtMap; + } + + return 0; +} + +CFGReachabilityAnalysis *AnalysisContext::getCFGReachablityAnalysis() { + if (CFA) + return CFA; + + if (CFG *c = getCFG()) { + CFA = new CFGReachabilityAnalysis(*c); + return CFA; + } + + return 0; +} + void AnalysisContext::dumpCFG() { getCFG()->dump(getASTContext().getLangOptions()); } @@ -346,10 +372,12 @@ AnalysisContext::getReferencedBlockVars(const BlockDecl *BD) { AnalysisContext::~AnalysisContext() { delete cfg; delete completeCFG; + delete cfgStmtMap; delete liveness; delete relaxedLiveness; delete PM; delete PCA; + delete CFA; delete ReferencedBlockVars; } diff --git a/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp b/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp index a0ec5fe..cc6e9c5 100644 --- a/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp +++ b/contrib/llvm/tools/clang/lib/Analysis/CFG.cpp @@ -17,6 +17,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/PrettyPrinter.h" +#include "clang/AST/CharUnits.h" #include "llvm/Support/GraphWriter.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Format.h" @@ -413,9 +414,16 @@ private: Expr::EvalResult Result; if (!S->isTypeDependent() && !S->isValueDependent() && - S->Evaluate(Result, *Context) && Result.Val.isInt()) - return Result.Val.getInt().getBoolValue(); - + S->Evaluate(Result, *Context)) { + if (Result.Val.isInt()) + return Result.Val.getInt().getBoolValue(); + if (Result.Val.isLValue()) { + Expr *e = Result.Val.getLValueBase(); + const CharUnits &c = Result.Val.getLValueOffset(); + if (!e && c.isZero()) + return false; + } + } return TryResult(); } }; @@ -928,11 +936,13 @@ CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) { /// VisitChildren - Visit the children of a Stmt. CFGBlock *CFGBuilder::VisitChildren(Stmt* Terminator) { - CFGBlock *B = Block; - for (Stmt::child_range I = Terminator->children(); I; ++I) { - if (*I) B = Visit(*I); - } - return B; + CFGBlock *lastBlock = Block; + for (Stmt::child_range I = Terminator->children(); I; ++I) + if (Stmt *child = *I) + if (CFGBlock *b = Visit(child)) + lastBlock = b; + + return lastBlock; } CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A, @@ -1207,6 +1217,8 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C, return 0; Block = NULL; } + else + LHSBlock = ConfluenceBlock; // Create the block for the RHS expression. Succ = ConfluenceBlock; @@ -1219,23 +1231,23 @@ CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C, // See if this is a known constant. const TryResult& KnownVal = tryEvaluateBool(C->getCond()); - if (LHSBlock) - addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); + addSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock); addSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock); Block->setTerminator(C); Expr *condExpr = C->getCond(); - CFGBlock *result = 0; - - // Run the condition expression if it's not trivially expressed in - // terms of the opaque value (or if there is no opaque value). - if (condExpr != opaqueValue) result = addStmt(condExpr); - - // Before that, run the common subexpression if there was one. - // At least one of this or the above will be run. - if (opaqueValue) result = addStmt(BCO->getCommon()); + if (opaqueValue) { + // Run the condition expression if it's not trivially expressed in + // terms of the opaque value (or if there is no opaque value). + if (condExpr != opaqueValue) + addStmt(condExpr); - return result; + // Before that, run the common subexpression if there was one. + // At least one of this or the above will be run. + return addStmt(BCO->getCommon()); + } + + return addStmt(condExpr); } CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) { @@ -1819,6 +1831,7 @@ CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) { if (badCFG) return 0; LoopSuccessor = Block; + Block = 0; } else LoopSuccessor = Succ; diff --git a/contrib/llvm/tools/clang/lib/Analysis/CFGReachabilityAnalysis.cpp b/contrib/llvm/tools/clang/lib/Analysis/CFGReachabilityAnalysis.cpp new file mode 100644 index 0000000..7786584 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Analysis/CFGReachabilityAnalysis.cpp @@ -0,0 +1,76 @@ +//==- CFGReachabilityAnalysis.cpp - Basic reachability analysis --*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a flow-sensitive, (mostly) path-insensitive reachability +// analysis based on Clang's CFGs. Clients can query if a given basic block +// is reachable within the CFG. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallVector.h" +#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" +#include "clang/Analysis/CFG.h" + +using namespace clang; + +CFGReachabilityAnalysis::CFGReachabilityAnalysis(const CFG &cfg) + : analyzed(cfg.getNumBlockIDs(), false) {} + +bool CFGReachabilityAnalysis::isReachable(const CFGBlock *Src, + const CFGBlock *Dst) { + + const unsigned DstBlockID = Dst->getBlockID(); + + // If we haven't analyzed the destination node, run the analysis now + if (!analyzed[DstBlockID]) { + mapReachability(Dst); + analyzed[DstBlockID] = true; + } + + // Return the cached result + return reachable[DstBlockID][Src->getBlockID()]; +} + +// Maps reachability to a common node by walking the predecessors of the +// destination node. +void CFGReachabilityAnalysis::mapReachability(const CFGBlock *Dst) { + llvm::SmallVector<const CFGBlock *, 11> worklist; + llvm::BitVector visited(analyzed.size()); + + ReachableSet &DstReachability = reachable[Dst->getBlockID()]; + DstReachability.resize(analyzed.size(), false); + + // Start searching from the destination node, since we commonly will perform + // multiple queries relating to a destination node. + worklist.push_back(Dst); + bool firstRun = true; + + while (!worklist.empty()) { + const CFGBlock *block = worklist.back(); + worklist.pop_back(); + + if (visited[block->getBlockID()]) + continue; + visited[block->getBlockID()] = true; + + // Update reachability information for this node -> Dst + if (!firstRun) { + // Don't insert Dst -> Dst unless it was a predecessor of itself + DstReachability[block->getBlockID()] = true; + } + else + firstRun = false; + + // Add the predecessors to the worklist. + for (CFGBlock::const_pred_iterator i = block->pred_begin(), + e = block->pred_end(); i != e; ++i) { + worklist.push_back(*i); + } + } +} diff --git a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp index 8725e7f..553e4c9 100644 --- a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp @@ -288,14 +288,15 @@ const char *DiagnosticIDs::getDescription(unsigned DiagID) const { /// the DiagnosticClient. DiagnosticIDs::Level DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, - const Diagnostic &Diag) const { + const Diagnostic &Diag, + diag::Mapping *mapping) const { // Handle custom diagnostics, which cannot be mapped. if (DiagID >= diag::DIAG_UPPER_LIMIT) return CustomDiagInfo->getLevel(DiagID); unsigned DiagClass = getBuiltinDiagClass(DiagID); assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!"); - return getDiagnosticLevel(DiagID, DiagClass, Loc, Diag); + return getDiagnosticLevel(DiagID, DiagClass, Loc, Diag, mapping); } /// \brief Based on the way the client configured the Diagnostic @@ -307,7 +308,8 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, DiagnosticIDs::Level DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass, SourceLocation Loc, - const Diagnostic &Diag) const { + const Diagnostic &Diag, + diag::Mapping *mapping) const { // Specific non-error diagnostics may be mapped to various levels from ignored // to error. Errors can only be mapped to fatal. DiagnosticIDs::Level Result = DiagnosticIDs::Fatal; @@ -323,6 +325,9 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass, MappingInfo = GetDefaultDiagMapping(DiagID); Diag.setDiagnosticMappingInternal(DiagID, MappingInfo, State, false, false); } + + if (mapping) + *mapping = (diag::Mapping) (MappingInfo & 7); switch (MappingInfo & 7) { default: assert(0 && "Unknown mapping!"); diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp index 044c88d..e2783ba 100644 --- a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp @@ -823,6 +823,12 @@ unsigned SourceManager::getInstantiationColumnNumber(SourceLocation Loc, return getColumnNumber(LocInfo.first, LocInfo.second, Invalid); } +unsigned SourceManager::getPresumedColumnNumber(SourceLocation Loc, + bool *Invalid) const { + if (isInvalid(Loc, Invalid)) return 0; + return getPresumedLoc(Loc).getColumn(); +} + static LLVM_ATTRIBUTE_NOINLINE void ComputeLineNumbers(Diagnostic &Diag, ContentCache *FI, llvm::BumpPtrAllocator &Alloc, @@ -985,17 +991,22 @@ unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos, return LineNo; } +unsigned SourceManager::getSpellingLineNumber(SourceLocation Loc, + bool *Invalid) const { + if (isInvalid(Loc, Invalid)) return 0; + std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc); + return getLineNumber(LocInfo.first, LocInfo.second); +} unsigned SourceManager::getInstantiationLineNumber(SourceLocation Loc, bool *Invalid) const { if (isInvalid(Loc, Invalid)) return 0; std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc); return getLineNumber(LocInfo.first, LocInfo.second); } -unsigned SourceManager::getSpellingLineNumber(SourceLocation Loc, +unsigned SourceManager::getPresumedLineNumber(SourceLocation Loc, bool *Invalid) const { if (isInvalid(Loc, Invalid)) return 0; - std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc); - return getLineNumber(LocInfo.first, LocInfo.second); + return getPresumedLoc(Loc).getLine(); } /// getFileCharacteristic - return the file characteristic of the specified diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp index a8198e4..55321f24 100644 --- a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp @@ -152,6 +152,7 @@ public: DarwinTargetInfo(const std::string& triple) : OSTargetInfo<Target>(triple) { this->TLSSupported = llvm::Triple(triple).getDarwinMajorNumber() > 10; + this->MCountName = "\01mcount"; } virtual std::string isValidSectionSpecifier(llvm::StringRef SR) const { diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp index a35648d..9587de2 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.cpp @@ -895,12 +895,9 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, QualType selfTy = getContext().VoidPtrTy; IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor"); - // FIXME: this leaks, and we only need it very temporarily. - ImplicitParamDecl *selfDecl = - ImplicitParamDecl::Create(getContext(), - const_cast<BlockDecl*>(blockDecl), - SourceLocation(), II, selfTy); - args.push_back(std::make_pair(selfDecl, selfTy)); + ImplicitParamDecl selfDecl(const_cast<BlockDecl*>(blockDecl), + SourceLocation(), II, selfTy); + args.push_back(std::make_pair(&selfDecl, selfTy)); // Now add the rest of the parameters. for (BlockDecl::param_const_iterator i = blockDecl->param_begin(), @@ -928,12 +925,11 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, blockInfo.getBlockExpr()->getBody()->getLocEnd()); CurFuncDecl = outerFnDecl; // StartFunction sets this to blockDecl - // Okay. Undo some of what StartFunction did. We really don't need - // an alloca for the block address; in theory we could remove it, - // but that might do unpleasant things to debug info. - llvm::AllocaInst *blockAddrAlloca - = cast<llvm::AllocaInst>(LocalDeclMap[selfDecl]); - llvm::Value *blockAddr = Builder.CreateLoad(blockAddrAlloca); + // Okay. Undo some of what StartFunction did. + + // Pull the 'self' reference out of the local decl map. + llvm::Value *blockAddr = LocalDeclMap[&selfDecl]; + LocalDeclMap.erase(&selfDecl); BlockPointer = Builder.CreateBitCast(blockAddr, blockInfo.StructureType->getPointerTo(), "block"); @@ -1010,7 +1006,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, continue; } - DI->EmitDeclareOfBlockDeclRefVariable(variable, blockAddrAlloca, + DI->EmitDeclareOfBlockDeclRefVariable(variable, BlockPointer, Builder, blockInfo); } } @@ -1376,10 +1372,9 @@ llvm::Constant *CodeGenModule::BuildbyrefCopyHelper(const llvm::Type *T, BlockFieldFlags flags, unsigned align, const VarDecl *var) { - // All alignments below that of pointer alignment collapse down to just - // pointer alignment, as we always have at least that much alignment to begin - // with. - align /= unsigned(getTarget().getPointerAlign(0) / 8); + // All alignments below pointer alignment are bumped up, as we + // always have at least that much alignment to begin with. + if (align < PointerAlignInBytes) align = PointerAlignInBytes; // As an optimization, we only generate a single function of each kind we // might need. We need a different one for each alignment and for each @@ -1396,10 +1391,9 @@ llvm::Constant *CodeGenModule::BuildbyrefDestroyHelper(const llvm::Type *T, BlockFieldFlags flags, unsigned align, const VarDecl *var) { - // All alignments below that of pointer alignment collpase down to just - // pointer alignment, as we always have at least that much alignment to begin - // with. - align /= unsigned(getTarget().getPointerAlign(0) / 8); + // All alignments below pointer alignment are bumped up, as we + // always have at least that much alignment to begin with. + if (align < PointerAlignInBytes) align = PointerAlignInBytes; // As an optimization, we only generate a single function of each kind we // might need. We need a different one for each alignment and for each diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h index bee729d..0bc8bca 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGBlocks.h @@ -177,7 +177,6 @@ public: const BlockExpr *Block; CharUnits BlockSize; CharUnits BlockAlign; - llvm::SmallVector<const Expr*, 8> BlockLayout; const Capture &getCapture(const VarDecl *var) const { llvm::DenseMap<const VarDecl*, Capture>::const_iterator diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp index 8e88beb..cd28bbe 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp @@ -17,6 +17,7 @@ #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtCXX.h" +#include "clang/Frontend/CodeGenOptions.h" using namespace clang; using namespace CodeGen; @@ -1140,6 +1141,16 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, llvm::Value *This, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd) { + + CGDebugInfo *DI = getDebugInfo(); + if (DI && CGM.getCodeGenOpts().LimitDebugInfo) { + // If debug info for this class has been emitted then this is the right time + // to do so. + const CXXRecordDecl *Parent = D->getParent(); + DI->getOrCreateRecordType(CGM.getContext().getTypeDeclType(Parent), + Parent->getLocation()); + } + if (D->isTrivial()) { if (ArgBeg == ArgEnd) { // Trivial default constructor, no codegen required. diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp index 374ede8..1d7901a 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp @@ -876,7 +876,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { /// /// As a side-effect, this method clears the insertion point. void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) { - assert(Dest.getScopeDepth().encloses(EHStack.getInnermostNormalCleanup()) + assert(Dest.getScopeDepth().encloses(EHStack.stable_begin()) && "stale jump destination"); if (!HaveInsertPoint()) diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp index 469b460..dfd9f56 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp @@ -156,14 +156,14 @@ CGDebugInfo::getClassName(RecordDecl *RD) { llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) { if (!Loc.isValid()) // If Location is not valid then use main input file. - return DBuilder.CreateFile(TheCU.getFilename(), TheCU.getDirectory()); + return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory()); SourceManager &SM = CGM.getContext().getSourceManager(); PresumedLoc PLoc = SM.getPresumedLoc(Loc); if (PLoc.isInvalid() || llvm::StringRef(PLoc.getFilename()).empty()) // If the location is not valid then use main input file. - return DBuilder.CreateFile(TheCU.getFilename(), TheCU.getDirectory()); + return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory()); // Cache the results. const char *fname = PLoc.getFilename(); @@ -176,7 +176,7 @@ llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) { return llvm::DIFile(cast<llvm::MDNode>(it->second)); } - llvm::DIFile F = DBuilder.CreateFile(PLoc.getFilename(), getCurrentDirname()); + llvm::DIFile F = DBuilder.createFile(PLoc.getFilename(), getCurrentDirname()); DIFileCache[fname] = F; return F; @@ -185,7 +185,7 @@ llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) { /// getOrCreateMainFile - Get the file info for main compile unit. llvm::DIFile CGDebugInfo::getOrCreateMainFile() { - return DBuilder.CreateFile(TheCU.getFilename(), TheCU.getDirectory()); + return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory()); } /// getLineNumber - Get line number for the location. If location is invalid @@ -264,7 +264,7 @@ void CGDebugInfo::CreateCompileUnit() { RuntimeVers = LO.ObjCNonFragileABI ? 2 : 1; // Create new compile unit. - DBuilder.CreateCompileUnit( + DBuilder.createCompileUnit( LangTag, Filename, getCurrentDirname(), Producer, LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers); @@ -282,7 +282,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) { case BuiltinType::Void: return llvm::DIType(); case BuiltinType::ObjCClass: - return DBuilder.CreateStructType(TheCU, "objc_class", + return DBuilder.createStructType(TheCU, "objc_class", getOrCreateMainFile(), 0, 0, 0, llvm::DIDescriptor::FlagFwdDecl, llvm::DIArray()); @@ -293,28 +293,28 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) { // } *id; llvm::DIType OCTy = - DBuilder.CreateStructType(TheCU, "objc_class", + DBuilder.createStructType(TheCU, "objc_class", getOrCreateMainFile(), 0, 0, 0, llvm::DIDescriptor::FlagFwdDecl, llvm::DIArray()); unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); - llvm::DIType ISATy = DBuilder.CreatePointerType(OCTy, Size); + llvm::DIType ISATy = DBuilder.createPointerType(OCTy, Size); llvm::SmallVector<llvm::Value *, 16> EltTys; llvm::DIType FieldTy = - DBuilder.CreateMemberType("isa", getOrCreateMainFile(), + DBuilder.createMemberType("isa", getOrCreateMainFile(), 0,Size, 0, 0, 0, ISATy); EltTys.push_back(FieldTy); llvm::DIArray Elements = - DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size()); + DBuilder.getOrCreateArray(EltTys.data(), EltTys.size()); - return DBuilder.CreateStructType(TheCU, "objc_object", + return DBuilder.createStructType(TheCU, "objc_object", getOrCreateMainFile(), 0, 0, 0, 0, Elements); } case BuiltinType::ObjCSel: { - return DBuilder.CreateStructType(TheCU, "objc_selector", + return DBuilder.createStructType(TheCU, "objc_selector", getOrCreateMainFile(), 0, 0, 0, llvm::DIDescriptor::FlagFwdDecl, llvm::DIArray()); @@ -350,7 +350,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) { uint64_t Size = CGM.getContext().getTypeSize(BT); uint64_t Align = CGM.getContext().getTypeAlign(BT); llvm::DIType DbgTy = - DBuilder.CreateBasicType(BTName, Size, Align, Encoding); + DBuilder.createBasicType(BTName, Size, Align, Encoding); return DbgTy; } @@ -363,7 +363,7 @@ llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty) { uint64_t Size = CGM.getContext().getTypeSize(Ty); uint64_t Align = CGM.getContext().getTypeAlign(Ty); llvm::DIType DbgTy = - DBuilder.CreateBasicType("complex", Size, Align, Encoding); + DBuilder.createBasicType("complex", Size, Align, Encoding); return DbgTy; } @@ -399,7 +399,7 @@ llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) { // No need to fill in the Name, Line, Size, Alignment, Offset in case of // CVR derived types. - llvm::DIType DbgTy = DBuilder.CreateQualifiedType(Tag, FromTy); + llvm::DIType DbgTy = DBuilder.createQualifiedType(Tag, FromTy); return DbgTy; } @@ -430,19 +430,19 @@ llvm::DIType CGDebugInfo::CreatePointeeType(QualType PointeeTy, llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation()); unsigned Line = getLineNumber(RD->getLocation()); llvm::DIDescriptor FDContext = - getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext())); + getContextDescriptor(cast<Decl>(RD->getDeclContext())); if (RD->isStruct()) - return DBuilder.CreateStructType(FDContext, RD->getName(), DefUnit, + return DBuilder.createStructType(FDContext, RD->getName(), DefUnit, Line, 0, 0, llvm::DIType::FlagFwdDecl, llvm::DIArray()); else if (RD->isUnion()) - return DBuilder.CreateUnionType(FDContext, RD->getName(), DefUnit, + return DBuilder.createUnionType(FDContext, RD->getName(), DefUnit, Line, 0, 0, llvm::DIType::FlagFwdDecl, llvm::DIArray()); else { assert(RD->isClass() && "Unknown RecordType!"); - return DBuilder.CreateClassType(FDContext, RD->getName(), DefUnit, + return DBuilder.createClassType(FDContext, RD->getName(), DefUnit, Line, 0, 0, 0, llvm::DIType::FlagFwdDecl, llvm::DIType(), llvm::DIArray()); } @@ -457,7 +457,7 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag, llvm::DIFile Unit) { if (Tag == llvm::dwarf::DW_TAG_reference_type) - return DBuilder.CreateReferenceType(CreatePointeeType(PointeeTy, Unit)); + return DBuilder.createReferenceType(CreatePointeeType(PointeeTy, Unit)); // Bit size, align and offset of the type. // Size is always the size of a pointer. We can't use getTypeSize here @@ -467,7 +467,7 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag, uint64_t Align = CGM.getContext().getTypeAlign(Ty); return - DBuilder.CreatePointerType(CreatePointeeType(PointeeTy, Unit), Size, Align); + DBuilder.createPointerType(CreatePointeeType(PointeeTy, Unit), Size, Align); } llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, @@ -488,20 +488,20 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, EltTys.push_back(CreateMemberType(Unit, FType, "reserved", &FieldOffset)); EltTys.push_back(CreateMemberType(Unit, FType, "Size", &FieldOffset)); - Elements = DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size()); + Elements = DBuilder.getOrCreateArray(EltTys.data(), EltTys.size()); EltTys.clear(); unsigned Flags = llvm::DIDescriptor::FlagAppleBlock; unsigned LineNo = getLineNumber(CurLoc); - EltTy = DBuilder.CreateStructType(Unit, "__block_descriptor", + EltTy = DBuilder.createStructType(Unit, "__block_descriptor", Unit, LineNo, FieldOffset, 0, Flags, Elements); // Bit size, align and offset of the type. uint64_t Size = CGM.getContext().getTypeSize(Ty); - DescTy = DBuilder.CreatePointerType(EltTy, Size); + DescTy = DBuilder.createPointerType(EltTy, Size); FieldOffset = 0; FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy); @@ -516,20 +516,20 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, FieldTy = DescTy; FieldSize = CGM.getContext().getTypeSize(Ty); FieldAlign = CGM.getContext().getTypeAlign(Ty); - FieldTy = DBuilder.CreateMemberType("__descriptor", Unit, + FieldTy = DBuilder.createMemberType("__descriptor", Unit, LineNo, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); FieldOffset += FieldSize; - Elements = DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size()); + Elements = DBuilder.getOrCreateArray(EltTys.data(), EltTys.size()); - EltTy = DBuilder.CreateStructType(Unit, "__block_literal_generic", + EltTy = DBuilder.createStructType(Unit, "__block_literal_generic", Unit, LineNo, FieldOffset, 0, Flags, Elements); BlockLiteralGenericSet = true; - BlockLiteralGeneric = DBuilder.CreatePointerType(EltTy, Size); + BlockLiteralGeneric = DBuilder.createPointerType(EltTy, Size); return BlockLiteralGeneric; } @@ -543,7 +543,7 @@ llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, // We don't set size information, but do specify where the typedef was // declared. unsigned Line = getLineNumber(Ty->getDecl()->getLocation()); - llvm::DIType DbgTy = DBuilder.CreateTypedef(Src, Ty->getDecl()->getName(), + llvm::DIType DbgTy = DBuilder.createTypedef(Src, Ty->getDecl()->getName(), Unit, Line); return DbgTy; } @@ -558,66 +558,76 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty, // Set up remainder of arguments if there is a prototype. // FIXME: IF NOT, HOW IS THIS REPRESENTED? llvm-gcc doesn't represent '...'! if (isa<FunctionNoProtoType>(Ty)) - EltTys.push_back(DBuilder.CreateUnspecifiedParameter()); + EltTys.push_back(DBuilder.createUnspecifiedParameter()); else if (const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(Ty)) { for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i) EltTys.push_back(getOrCreateType(FTP->getArgType(i), Unit)); } llvm::DIArray EltTypeArray = - DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size()); + DBuilder.getOrCreateArray(EltTys.data(), EltTys.size()); - llvm::DIType DbgTy = DBuilder.CreateSubroutineType(Unit, EltTypeArray); + llvm::DIType DbgTy = DBuilder.createSubroutineType(Unit, EltTypeArray); return DbgTy; } +llvm::DIType CGDebugInfo::createFieldType(llvm::StringRef name, + QualType type, + Expr *bitWidth, + SourceLocation loc, + AccessSpecifier AS, + uint64_t offsetInBits, + llvm::DIFile tunit) { + llvm::DIType debugType = getOrCreateType(type, tunit); + + // Get the location for the field. + llvm::DIFile file = getOrCreateFile(loc); + unsigned line = getLineNumber(loc); + + uint64_t sizeInBits = 0; + unsigned alignInBits = 0; + if (!type->isIncompleteArrayType()) { + llvm::tie(sizeInBits, alignInBits) = CGM.getContext().getTypeInfo(type); + + if (bitWidth) + sizeInBits = bitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue(); + } + + unsigned flags = 0; + if (AS == clang::AS_private) + flags |= llvm::DIDescriptor::FlagPrivate; + else if (AS == clang::AS_protected) + flags |= llvm::DIDescriptor::FlagProtected; + + return DBuilder.createMemberType(name, file, line, sizeInBits, alignInBits, + offsetInBits, flags, debugType); +} + /// CollectRecordFields - A helper function to collect debug info for /// record fields. This is used while creating debug info entry for a Record. void CGDebugInfo:: -CollectRecordFields(const RecordDecl *RD, llvm::DIFile Unit, - llvm::SmallVectorImpl<llvm::Value *> &EltTys) { - unsigned FieldNo = 0; - const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); - for (RecordDecl::field_iterator I = RD->field_begin(), - E = RD->field_end(); - I != E; ++I, ++FieldNo) { - FieldDecl *Field = *I; - llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit); - llvm::StringRef FieldName = Field->getName(); - - // Ignore unnamed fields. Do not ignore unnamed records. - if (FieldName.empty() && !isa<RecordType>(Field->getType())) +CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit, + llvm::SmallVectorImpl<llvm::Value *> &elements) { + unsigned fieldNo = 0; + const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record); + for (RecordDecl::field_iterator I = record->field_begin(), + E = record->field_end(); + I != E; ++I, ++fieldNo) { + FieldDecl *field = *I; + + llvm::StringRef name = field->getName(); + QualType type = field->getType(); + + // Ignore unnamed fields unless they're anonymous structs/unions. + if (name.empty() && !type->isRecordType()) continue; - // Get the location for the field. - llvm::DIFile FieldDefUnit = getOrCreateFile(Field->getLocation()); - unsigned FieldLine = getLineNumber(Field->getLocation()); - QualType FType = Field->getType(); - uint64_t FieldSize = 0; - unsigned FieldAlign = 0; - if (!FType->isIncompleteArrayType()) { - - // Bit size, align and offset of the type. - FieldSize = CGM.getContext().getTypeSize(FType); - Expr *BitWidth = Field->getBitWidth(); - if (BitWidth) - FieldSize = BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue(); - FieldAlign = CGM.getContext().getTypeAlign(FType); - } + llvm::DIType fieldType + = createFieldType(name, type, field->getBitWidth(), + field->getLocation(), field->getAccess(), + layout.getFieldOffset(fieldNo), tunit); - uint64_t FieldOffset = RL.getFieldOffset(FieldNo); - - unsigned Flags = 0; - AccessSpecifier Access = I->getAccess(); - if (Access == clang::AS_private) - Flags |= llvm::DIDescriptor::FlagPrivate; - else if (Access == clang::AS_protected) - Flags |= llvm::DIDescriptor::FlagProtected; - - FieldTy = DBuilder.CreateMemberType(FieldName, FieldDefUnit, - FieldLine, FieldSize, FieldAlign, - FieldOffset, Flags, FieldTy); - EltTys.push_back(FieldTy); + elements.push_back(fieldType); } } @@ -649,7 +659,7 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, QualType ThisPtr = Context.getPointerType(Context.getTagDeclType(Method->getParent())); llvm::DIType ThisPtrType = - DBuilder.CreateArtificialType(getOrCreateType(ThisPtr, Unit)); + DBuilder.createArtificialType(getOrCreateType(ThisPtr, Unit)); TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType; Elts.push_back(ThisPtrType); @@ -660,9 +670,9 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, Elts.push_back(Args.getElement(i)); llvm::DIArray EltTypeArray = - DBuilder.GetOrCreateArray(Elts.data(), Elts.size()); + DBuilder.getOrCreateArray(Elts.data(), Elts.size()); - return DBuilder.CreateSubroutineType(Unit, EltTypeArray); + return DBuilder.createSubroutineType(Unit, EltTypeArray); } /// isFunctionLocalClass - Return true if CXXRecordDecl is defined @@ -736,7 +746,7 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method, Flags |= llvm::DIDescriptor::FlagPrototyped; llvm::DISubprogram SP = - DBuilder.CreateMethod(RecordTy , MethodName, MethodLinkageName, + DBuilder.createMethod(RecordTy , MethodName, MethodLinkageName, MethodDefUnit, MethodLine, MethodTy, /*isLocalToUnit=*/false, /* isDefinition=*/ false, @@ -780,7 +790,7 @@ CollectCXXFriends(const CXXRecordDecl *RD, llvm::DIFile Unit, for (CXXRecordDecl::friend_iterator BI = RD->friend_begin(), BE = RD->friend_end(); BI != BE; ++BI) { if (TypeSourceInfo *TInfo = (*BI)->getFriendType()) - EltTys.push_back(DBuilder.CreateFriend(RecordTy, + EltTys.push_back(DBuilder.createFriend(RecordTy, getOrCreateType(TInfo->getType(), Unit))); } @@ -818,7 +828,7 @@ CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit, BFlags |= llvm::DIDescriptor::FlagProtected; llvm::DIType DTy = - DBuilder.CreateInheritance(RecordTy, + DBuilder.createInheritance(RecordTy, getOrCreateType(BI->getType(), Unit), BaseOffset, BFlags); EltTys.push_back(DTy); @@ -834,12 +844,12 @@ llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile Unit) { /* Function type */ llvm::Value *STy = getOrCreateType(Context.IntTy, Unit); - llvm::DIArray SElements = DBuilder.GetOrCreateArray(&STy, 1); - llvm::DIType SubTy = DBuilder.CreateSubroutineType(Unit, SElements); + llvm::DIArray SElements = DBuilder.getOrCreateArray(&STy, 1); + llvm::DIType SubTy = DBuilder.createSubroutineType(Unit, SElements); unsigned Size = Context.getTypeSize(Context.VoidPtrTy); - llvm::DIType vtbl_ptr_type = DBuilder.CreatePointerType(SubTy, Size, 0, + llvm::DIType vtbl_ptr_type = DBuilder.createPointerType(SubTy, Size, 0, "__vtbl_ptr_type"); - VTablePtrType = DBuilder.CreatePointerType(vtbl_ptr_type, Size); + VTablePtrType = DBuilder.createPointerType(vtbl_ptr_type, Size); return VTablePtrType; } @@ -872,7 +882,7 @@ CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit, unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); llvm::DIType VPTR - = DBuilder.CreateMemberType(getVTableName(RD), Unit, + = DBuilder.createMemberType(getVTableName(RD), Unit, 0, Size, 0, 0, 0, getOrCreateVTablePtrType(Unit)); EltTys.push_back(VPTR); @@ -882,7 +892,7 @@ CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit, llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy, SourceLocation Loc) { llvm::DIType T = getOrCreateType(RTy, getOrCreateFile(Loc)); - DBuilder.RetainType(T); + DBuilder.retainType(T); return T; } @@ -902,13 +912,13 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { // may refer to the forward decl if the struct is recursive) and replace all // uses of the forward declaration with the final definition. llvm::DIDescriptor FDContext = - getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext())); + getContextDescriptor(cast<Decl>(RD->getDeclContext())); // If this is just a forward declaration, construct an appropriately // marked node and just return it. if (!RD->getDefinition()) { llvm::DIType FwdDecl = - DBuilder.CreateStructType(FDContext, RD->getName(), + DBuilder.createStructType(FDContext, RD->getName(), DefUnit, Line, 0, 0, llvm::DIDescriptor::FlagFwdDecl, llvm::DIArray()); @@ -916,7 +926,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { return FwdDecl; } - llvm::DIType FwdDecl = DBuilder.CreateTemporaryType(DefUnit); + llvm::DIType FwdDecl = DBuilder.createTemporaryType(DefUnit); llvm::MDNode *MN = FwdDecl; llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN; @@ -952,7 +962,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { llvm::DIType VTy = getOrCreateType(V->getType(), VUnit); // Do not use DIGlobalVariable for enums. if (VTy.getTag() != llvm::dwarf::DW_TAG_enumeration_type) { - DBuilder.CreateStaticVariable(FwdDecl, VName, VName, VUnit, + DBuilder.createStaticVariable(FwdDecl, VName, VName, VUnit, getLineNumber(V->getLocation()), VTy, true, CI); } @@ -973,13 +983,13 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { if (TA.getKind() == TemplateArgument::Type) { llvm::DIType TTy = getOrCreateType(TA.getAsType(), Unit); llvm::DITemplateTypeParameter TTP = - DBuilder.CreateTemplateTypeParameter(TheCU, TTy.getName(), TTy); + DBuilder.createTemplateTypeParameter(TheCU, TTy.getName(), TTy); TemplateParams.push_back(TTP); } else if (TA.getKind() == TemplateArgument::Integral) { llvm::DIType TTy = getOrCreateType(TA.getIntegralType(), Unit); // FIXME: Get parameter name, instead of parameter type name. llvm::DITemplateValueParameter TVP = - DBuilder.CreateTemplateValueParameter(TheCU, TTy.getName(), TTy, + DBuilder.createTemplateValueParameter(TheCU, TTy.getName(), TTy, TA.getAsIntegral()->getZExtValue()); TemplateParams.push_back(TVP); } @@ -994,19 +1004,19 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { RegionMap.erase(RI); llvm::DIDescriptor RDContext = - getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext())); + getContextDescriptor(cast<Decl>(RD->getDeclContext())); llvm::StringRef RDName = RD->getName(); uint64_t Size = CGM.getContext().getTypeSize(Ty); uint64_t Align = CGM.getContext().getTypeAlign(Ty); llvm::DIArray Elements = - DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size()); + DBuilder.getOrCreateArray(EltTys.data(), EltTys.size()); llvm::MDNode *RealDecl = NULL; if (RD->isStruct()) - RealDecl = DBuilder.CreateStructType(RDContext, RDName, DefUnit, Line, + RealDecl = DBuilder.createStructType(RDContext, RDName, DefUnit, Line, Size, Align, 0, Elements); else if (RD->isUnion()) - RealDecl = DBuilder.CreateUnionType(RDContext, RDName, DefUnit, Line, + RealDecl = DBuilder.createUnionType(RDContext, RDName, DefUnit, Line, Size, Align, 0, Elements); else { assert(RD->isClass() && "Unknown RecordType!"); @@ -1030,8 +1040,8 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { else if (CXXDecl->isDynamicClass()) ContainingType = FwdDecl; llvm::DIArray TParamsArray = - DBuilder.GetOrCreateArray(TemplateParams.data(), TemplateParams.size()); - RealDecl = DBuilder.CreateClassType(RDContext, RDName, DefUnit, Line, + DBuilder.getOrCreateArray(TemplateParams.data(), TemplateParams.size()); + RealDecl = DBuilder.createClassType(RDContext, RDName, DefUnit, Line, Size, Align, 0, 0, llvm::DIType(), Elements, ContainingType, TParamsArray); @@ -1067,7 +1077,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, // debug type. if (ID->isForwardDecl()) { llvm::DIType FwdDecl = - DBuilder.CreateStructType(Unit, ID->getName(), + DBuilder.createStructType(Unit, ID->getName(), DefUnit, Line, 0, 0, 0, llvm::DIArray(), RuntimeLang); return FwdDecl; @@ -1079,7 +1089,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, // its members. Finally, we create a descriptor for the complete type (which // may refer to the forward decl if the struct is recursive) and replace all // uses of the forward declaration with the final definition. - llvm::DIType FwdDecl = DBuilder.CreateTemporaryType(DefUnit); + llvm::DIType FwdDecl = DBuilder.createTemporaryType(DefUnit); llvm::MDNode *MN = FwdDecl; llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN; @@ -1101,7 +1111,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, return llvm::DIType(); llvm::DIType InhTag = - DBuilder.CreateInheritance(FwdDecl, SClassTy, 0, 0); + DBuilder.createInheritance(FwdDecl, SClassTy, 0, 0); EltTys.push_back(InhTag); } @@ -1146,14 +1156,14 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, else if (Field->getAccessControl() == ObjCIvarDecl::Private) Flags = llvm::DIDescriptor::FlagPrivate; - FieldTy = DBuilder.CreateMemberType(FieldName, FieldDefUnit, + FieldTy = DBuilder.createMemberType(FieldName, FieldDefUnit, FieldLine, FieldSize, FieldAlign, FieldOffset, Flags, FieldTy); EltTys.push_back(FieldTy); } llvm::DIArray Elements = - DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size()); + DBuilder.getOrCreateArray(EltTys.data(), EltTys.size()); RegionStack.pop_back(); llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator RI = @@ -1166,7 +1176,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, uint64_t Align = CGM.getContext().getTypeAlign(Ty); llvm::DIType RealDecl = - DBuilder.CreateStructType(Unit, ID->getName(), DefUnit, + DBuilder.createStructType(Unit, ID->getName(), DefUnit, Line, Size, Align, 0, Elements, RuntimeLang); @@ -1194,14 +1204,14 @@ llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty, if (NumElems > 0) --NumElems; - llvm::Value *Subscript = DBuilder.GetOrCreateSubrange(0, NumElems); - llvm::DIArray SubscriptArray = DBuilder.GetOrCreateArray(&Subscript, 1); + llvm::Value *Subscript = DBuilder.getOrCreateSubrange(0, NumElems); + llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(&Subscript, 1); uint64_t Size = CGM.getContext().getTypeSize(Ty); uint64_t Align = CGM.getContext().getTypeAlign(Ty); return - DBuilder.CreateVectorType(Size, Align, ElementTy, SubscriptArray); + DBuilder.createVectorType(Size, Align, ElementTy, SubscriptArray); } llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty, @@ -1238,16 +1248,16 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty, if (CAT->getSize().getZExtValue()) Upper = CAT->getSize().getZExtValue() - 1; // FIXME: Verify this is right for VLAs. - Subscripts.push_back(DBuilder.GetOrCreateSubrange(0, Upper)); + Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Upper)); EltTy = Ty->getElementType(); } } llvm::DIArray SubscriptArray = - DBuilder.GetOrCreateArray(Subscripts.data(), Subscripts.size()); + DBuilder.getOrCreateArray(Subscripts.data(), Subscripts.size()); llvm::DIType DbgTy = - DBuilder.CreateArrayType(Size, Align, getOrCreateType(EltTy, Unit), + DBuilder.createArrayType(Size, Align, getOrCreateType(EltTy, Unit), SubscriptArray); return DbgTy; } @@ -1283,21 +1293,21 @@ llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty, // FIXME: This should probably be a function type instead. ElementTypes[0] = - DBuilder.CreateMemberType("ptr", U, 0, + DBuilder.createMemberType("ptr", U, 0, Info.first, Info.second, FieldOffset, 0, PointerDiffDITy); FieldOffset += Info.first; ElementTypes[1] = - DBuilder.CreateMemberType("ptr", U, 0, + DBuilder.createMemberType("ptr", U, 0, Info.first, Info.second, FieldOffset, 0, PointerDiffDITy); llvm::DIArray Elements = - DBuilder.GetOrCreateArray(&ElementTypes[0], + DBuilder.getOrCreateArray(&ElementTypes[0], llvm::array_lengthof(ElementTypes)); - return DBuilder.CreateStructType(U, llvm::StringRef("test"), + return DBuilder.createStructType(U, llvm::StringRef("test"), U, 0, FieldOffset, 0, 0, Elements); } @@ -1312,13 +1322,13 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) { Enum = ED->enumerator_begin(), EnumEnd = ED->enumerator_end(); Enum != EnumEnd; ++Enum) { Enumerators.push_back( - DBuilder.CreateEnumerator(Enum->getName(), + DBuilder.createEnumerator(Enum->getName(), Enum->getInitVal().getZExtValue())); } // Return a CompositeType for the enum itself. llvm::DIArray EltArray = - DBuilder.GetOrCreateArray(Enumerators.data(), Enumerators.size()); + DBuilder.getOrCreateArray(Enumerators.data(), Enumerators.size()); llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation()); unsigned Line = getLineNumber(ED->getLocation()); @@ -1329,9 +1339,9 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) { Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl()); } llvm::DIDescriptor EnumContext = - getContextDescriptor(dyn_cast<Decl>(ED->getDeclContext())); + getContextDescriptor(cast<Decl>(ED->getDeclContext())); llvm::DIType DbgTy = - DBuilder.CreateEnumerationType(EnumContext, ED->getName(), DefUnit, Line, + DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit, Line, Size, Align, EltArray); return DbgTy; } @@ -1485,7 +1495,7 @@ llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType, llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); uint64_t FieldSize = CGM.getContext().getTypeSize(FType); unsigned FieldAlign = CGM.getContext().getTypeAlign(FType); - llvm::DIType Ty = DBuilder.CreateMemberType(Name, Unit, 0, + llvm::DIType Ty = DBuilder.createMemberType(Name, Unit, 0, FieldSize, FieldAlign, *Offset, 0, FieldTy); *Offset += FieldSize; @@ -1548,7 +1558,7 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, if (D->isImplicit()) Flags |= llvm::DIDescriptor::FlagArtificial; llvm::DISubprogram SP = - DBuilder.CreateFunction(FDContext, Name, LinkageName, Unit, + DBuilder.createFunction(FDContext, Name, LinkageName, Unit, LineNo, getOrCreateType(FnType, Unit), Fn->hasInternalLinkage(), true/*definition*/, Flags, CGM.getLangOptions().Optimize, Fn); @@ -1640,7 +1650,7 @@ void CGDebugInfo::UpdateLineDirectiveRegion(CGBuilderTy &Builder) { /// region - "llvm.dbg.region.start.". void CGDebugInfo::EmitRegionStart(CGBuilderTy &Builder) { llvm::DIDescriptor D = - DBuilder.CreateLexicalBlock(RegionStack.empty() ? + DBuilder.createLexicalBlock(RegionStack.empty() ? llvm::DIDescriptor() : llvm::DIDescriptor(RegionStack.back()), getOrCreateFile(CurLoc), @@ -1725,18 +1735,18 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD, FieldAlign = Align.getQuantity()*8; *XOffset = FieldOffset; - FieldTy = DBuilder.CreateMemberType(VD->getName(), Unit, + FieldTy = DBuilder.createMemberType(VD->getName(), Unit, 0, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); FieldOffset += FieldSize; llvm::DIArray Elements = - DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size()); + DBuilder.getOrCreateArray(EltTys.data(), EltTys.size()); unsigned Flags = llvm::DIDescriptor::FlagBlockByrefStruct; - return DBuilder.CreateStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags, + return DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags, Elements); } @@ -1762,13 +1772,13 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, // If Storage is an aggregate returned as 'sret' then let debugger know // about this. if (Arg->hasStructRetAttr()) - Ty = DBuilder.CreateReferenceType(Ty); + Ty = DBuilder.createReferenceType(Ty); else if (CXXRecordDecl *Record = VD->getType()->getAsCXXRecordDecl()) { // If an aggregate variable has non trivial destructor or non trivial copy // constructor than it is pass indirectly. Let debug info know about this // by using reference of the aggregate type as a argument type. if (!Record->hasTrivialCopyConstructor() || !Record->hasTrivialDestructor()) - Ty = DBuilder.CreateReferenceType(Ty); + Ty = DBuilder.createReferenceType(Ty); } } @@ -1799,27 +1809,27 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, // Create the descriptor for the variable. llvm::DIVariable D = - DBuilder.CreateComplexVariable(Tag, + DBuilder.createComplexVariable(Tag, llvm::DIDescriptor(RegionStack.back()), VD->getName(), Unit, Line, Ty, addr.data(), addr.size()); // Insert an llvm.dbg.declare into the current block. llvm::Instruction *Call = - DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock()); + DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock()); Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope)); return; } // Create the descriptor for the variable. llvm::DIVariable D = - DBuilder.CreateLocalVariable(Tag, llvm::DIDescriptor(Scope), + DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope), Name, Unit, Line, Ty, CGM.getLangOptions().Optimize, Flags); // Insert an llvm.dbg.declare into the current block. llvm::Instruction *Call = - DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock()); + DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock()); Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope)); return; @@ -1827,33 +1837,34 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, // If VD is an anonymous union then Storage represents value for // all union fields. - if (const RecordType *RT = dyn_cast<RecordType>(VD->getType())) - if (const RecordDecl *RD = dyn_cast<RecordDecl>(RT->getDecl())) - if (RD->isUnion()) { - for (RecordDecl::field_iterator I = RD->field_begin(), - E = RD->field_end(); - I != E; ++I) { - FieldDecl *Field = *I; - llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit); - llvm::StringRef FieldName = Field->getName(); + if (const RecordType *RT = dyn_cast<RecordType>(VD->getType())) { + const RecordDecl *RD = cast<RecordDecl>(RT->getDecl()); + if (RD->isUnion()) { + for (RecordDecl::field_iterator I = RD->field_begin(), + E = RD->field_end(); + I != E; ++I) { + FieldDecl *Field = *I; + llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit); + llvm::StringRef FieldName = Field->getName(); - // Ignore unnamed fields. Do not ignore unnamed records. - if (FieldName.empty() && !isa<RecordType>(Field->getType())) - continue; + // Ignore unnamed fields. Do not ignore unnamed records. + if (FieldName.empty() && !isa<RecordType>(Field->getType())) + continue; - // Use VarDecl's Tag, Scope and Line number. - llvm::DIVariable D = - DBuilder.CreateLocalVariable(Tag, llvm::DIDescriptor(Scope), - FieldName, Unit, Line, FieldTy, - CGM.getLangOptions().Optimize, Flags); + // Use VarDecl's Tag, Scope and Line number. + llvm::DIVariable D = + DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope), + FieldName, Unit, Line, FieldTy, + CGM.getLangOptions().Optimize, Flags); - // Insert an llvm.dbg.declare into the current block. - llvm::Instruction *Call = - DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock()); + // Insert an llvm.dbg.declare into the current block. + llvm::Instruction *Call = + DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock()); - Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope)); - } + Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope)); } + } + } } /// EmitDeclare - Emit local variable declaration debug info. @@ -1887,7 +1898,6 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, llvm::SmallVector<llvm::Value *, 9> addr; const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(CGM.getLLVMContext()); - addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref)); addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus)); addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity())); if (isByRef) { @@ -1905,12 +1915,12 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, // Create the descriptor for the variable. llvm::DIVariable D = - DBuilder.CreateComplexVariable(Tag, llvm::DIDescriptor(RegionStack.back()), + DBuilder.createComplexVariable(Tag, llvm::DIDescriptor(RegionStack.back()), VD->getName(), Unit, Line, Ty, addr.data(), addr.size()); // Insert an llvm.dbg.declare into the current block. llvm::Instruction *Call = - DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock()); + DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock()); llvm::MDNode *Scope = RegionStack.back(); Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope)); @@ -1936,7 +1946,146 @@ void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI, EmitDeclare(VD, llvm::dwarf::DW_TAG_arg_variable, AI, Builder); } +namespace { + struct BlockLayoutChunk { + uint64_t OffsetInBits; + const BlockDecl::Capture *Capture; + }; + bool operator<(const BlockLayoutChunk &l, const BlockLayoutChunk &r) { + return l.OffsetInBits < r.OffsetInBits; + } +} + +void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, + llvm::Value *addr, + CGBuilderTy &Builder) { + ASTContext &C = CGM.getContext(); + const BlockDecl *blockDecl = block.getBlockDecl(); + + // Collect some general information about the block's location. + SourceLocation loc = blockDecl->getCaretLocation(); + llvm::DIFile tunit = getOrCreateFile(loc); + unsigned line = getLineNumber(loc); + unsigned column = getColumnNumber(loc); + + // Build the debug-info type for the block literal. + llvm::DIDescriptor enclosingContext = + getContextDescriptor(cast<Decl>(blockDecl->getDeclContext())); + + const llvm::StructLayout *blockLayout = + CGM.getTargetData().getStructLayout(block.StructureType); + + llvm::SmallVector<llvm::Value*, 16> fields; + fields.push_back(createFieldType("__isa", C.VoidPtrTy, 0, loc, AS_public, + blockLayout->getElementOffsetInBits(0), + tunit)); + fields.push_back(createFieldType("__flags", C.IntTy, 0, loc, AS_public, + blockLayout->getElementOffsetInBits(1), + tunit)); + fields.push_back(createFieldType("__reserved", C.IntTy, 0, loc, AS_public, + blockLayout->getElementOffsetInBits(2), + tunit)); + fields.push_back(createFieldType("__FuncPtr", C.VoidPtrTy, 0, loc, AS_public, + blockLayout->getElementOffsetInBits(3), + tunit)); + fields.push_back(createFieldType("__descriptor", + C.getPointerType(block.NeedsCopyDispose ? + C.getBlockDescriptorExtendedType() : + C.getBlockDescriptorType()), + 0, loc, AS_public, + blockLayout->getElementOffsetInBits(4), + tunit)); + + // We want to sort the captures by offset, not because DWARF + // requires this, but because we're paranoid about debuggers. + llvm::SmallVector<BlockLayoutChunk, 8> chunks; + + // 'this' capture. + if (blockDecl->capturesCXXThis()) { + BlockLayoutChunk chunk; + chunk.OffsetInBits = + blockLayout->getElementOffsetInBits(block.CXXThisIndex); + chunk.Capture = 0; + chunks.push_back(chunk); + } + + // Variable captures. + for (BlockDecl::capture_const_iterator + i = blockDecl->capture_begin(), e = blockDecl->capture_end(); + i != e; ++i) { + const BlockDecl::Capture &capture = *i; + const VarDecl *variable = capture.getVariable(); + const CGBlockInfo::Capture &captureInfo = block.getCapture(variable); + // Ignore constant captures. + if (captureInfo.isConstant()) + continue; + + BlockLayoutChunk chunk; + chunk.OffsetInBits = + blockLayout->getElementOffsetInBits(captureInfo.getIndex()); + chunk.Capture = &capture; + chunks.push_back(chunk); + } + + // Sort by offset. + llvm::array_pod_sort(chunks.begin(), chunks.end()); + + for (llvm::SmallVectorImpl<BlockLayoutChunk>::iterator + i = chunks.begin(), e = chunks.end(); i != e; ++i) { + uint64_t offsetInBits = i->OffsetInBits; + const BlockDecl::Capture *capture = i->Capture; + + // If we have a null capture, this must be the C++ 'this' capture. + if (!capture) { + const CXXMethodDecl *method = + cast<CXXMethodDecl>(blockDecl->getNonClosureContext()); + QualType type = method->getThisType(C); + + fields.push_back(createFieldType("this", type, 0, loc, AS_public, + offsetInBits, tunit)); + continue; + } + + const VarDecl *variable = capture->getVariable(); + QualType type = (capture->isByRef() ? C.VoidPtrTy : variable->getType()); + llvm::StringRef name = variable->getName(); + fields.push_back(createFieldType(name, type, 0, loc, AS_public, + offsetInBits, tunit)); + } + + llvm::SmallString<36> typeName; + llvm::raw_svector_ostream(typeName) + << "__block_literal_" << CGM.getUniqueBlockCount(); + + llvm::DIArray fieldsArray = + DBuilder.getOrCreateArray(fields.data(), fields.size()); + + llvm::DIType type = + DBuilder.createStructType(tunit, typeName.str(), tunit, line, + CGM.getContext().toBits(block.BlockSize), + CGM.getContext().toBits(block.BlockAlign), + 0, fieldsArray); + type = DBuilder.createPointerType(type, CGM.PointerWidthInBits); + + // Get overall information about the block. + unsigned flags = llvm::DIDescriptor::FlagArtificial; + llvm::MDNode *scope = RegionStack.back(); + llvm::StringRef name = ".block_descriptor"; + + // Create the descriptor for the parameter. + llvm::DIVariable debugVar = + DBuilder.createLocalVariable(llvm::dwarf::DW_TAG_arg_variable, + llvm::DIDescriptor(scope), + name, tunit, line, type, + CGM.getLangOptions().Optimize, flags); + + // Insert an llvm.dbg.value into the current block. + llvm::Instruction *declare = + DBuilder.insertDbgValueIntrinsic(addr, 0, debugVar, + Builder.GetInsertBlock()); + declare->setDebugLoc(llvm::DebugLoc::get(line, column, scope)); +} /// EmitGlobalVariable - Emit information about a global variable. void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, @@ -1967,7 +2116,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, LinkageName = llvm::StringRef(); llvm::DIDescriptor DContext = getContextDescriptor(dyn_cast<Decl>(D->getDeclContext())); - DBuilder.CreateStaticVariable(DContext, DeclName, LinkageName, + DBuilder.createStaticVariable(DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit), Var->hasInternalLinkage(), Var); } @@ -1994,7 +2143,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, ArrayType::Normal, 0); } - DBuilder.CreateGlobalVariable(Name, Unit, LineNo, + DBuilder.createGlobalVariable(Name, Unit, LineNo, getOrCreateType(T, Unit), Var->hasInternalLinkage(), Var); } @@ -2013,7 +2162,7 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, // Do not use DIGlobalVariable for enums. if (Ty.getTag() == llvm::dwarf::DW_TAG_enumeration_type) return; - DBuilder.CreateStaticVariable(Unit, Name, Name, Unit, + DBuilder.createStaticVariable(Unit, Name, Name, Unit, getLineNumber(VD->getLocation()), Ty, true, Init); } @@ -2032,7 +2181,7 @@ CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) { llvm::DIDescriptor Context = getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext())); llvm::DINameSpace NS = - DBuilder.CreateNameSpace(Context, NSDecl->getName(), FileD, LineNo); + DBuilder.createNameSpace(Context, NSDecl->getName(), FileD, LineNo); NameSpaceCache[NSDecl] = llvm::WeakVH(NS); return NS; } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h index 6a9ab9c..a390788 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.h @@ -123,7 +123,10 @@ class CGDebugInfo { llvm::SmallVectorImpl<llvm::Value *> &EltTys, llvm::DIType RecordTy); - + llvm::DIType createFieldType(llvm::StringRef name, QualType type, + Expr *bitWidth, SourceLocation loc, + AccessSpecifier AS, uint64_t offsetInBits, + llvm::DIFile tunit); void CollectRecordFields(const RecordDecl *Decl, llvm::DIFile F, llvm::SmallVectorImpl<llvm::Value *> &E); @@ -180,6 +183,13 @@ public: void EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI, CGBuilderTy &Builder); + /// EmitDeclareOfBlockLiteralArgVariable - Emit call to + /// llvm.dbg.declare for the block-literal argument to a block + /// invocation function. + void EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, + llvm::Value *addr, + CGBuilderTy &Builder); + /// EmitGlobalVariable - Emit information about a global variable. void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp index a87dfae..f4db01d 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDecl.cpp @@ -474,14 +474,19 @@ namespace { struct CallCleanupFunction : EHScopeStack::Cleanup { llvm::Constant *CleanupFn; const CGFunctionInfo &FnInfo; - llvm::Value *Addr; const VarDecl &Var; CallCleanupFunction(llvm::Constant *CleanupFn, const CGFunctionInfo *Info, - llvm::Value *Addr, const VarDecl *Var) - : CleanupFn(CleanupFn), FnInfo(*Info), Addr(Addr), Var(*Var) {} + const VarDecl *Var) + : CleanupFn(CleanupFn), FnInfo(*Info), Var(*Var) {} void Emit(CodeGenFunction &CGF, bool IsForEH) { + DeclRefExpr DRE(const_cast<VarDecl*>(&Var), Var.getType(), VK_LValue, + SourceLocation()); + // Compute the address of the local variable, in case it's a byref + // or something. + llvm::Value *Addr = CGF.EmitDeclRefLValue(&DRE).getAddress(); + // In some cases, the type of the function argument will be different from // the type of the pointer. An example of this is // void f(void* arg); @@ -543,7 +548,7 @@ static bool canEmitInitWithFewStoresAfterMemset(llvm::Constant *Init, /// canEmitInitWithFewStoresAfterMemset returned true for, emit the scalar /// stores that would be required. static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc, - CGBuilderTy &Builder) { + bool isVolatile, CGBuilderTy &Builder) { // Zero doesn't require any stores. if (isa<llvm::ConstantAggregateZero>(Init) || isa<llvm::ConstantPointerNull>(Init) || @@ -554,7 +559,7 @@ static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc, isa<llvm::ConstantVector>(Init) || isa<llvm::BlockAddress>(Init) || isa<llvm::ConstantExpr>(Init)) { if (!Init->isNullValue()) - Builder.CreateStore(Init, Loc); + Builder.CreateStore(Init, Loc, isVolatile); return; } @@ -567,7 +572,7 @@ static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc, // Otherwise, get a pointer to the element and emit it. emitStoresForInitAfterMemset(Elt, Builder.CreateConstGEP2_32(Loc, 0, i), - Builder); + isVolatile, Builder); } } @@ -597,37 +602,55 @@ static bool shouldUseMemSetPlusStoresToInitialize(llvm::Constant *Init, /// EmitAutoVarDecl - Emit code and set up an entry in LocalDeclMap for a /// variable declaration with auto, register, or no storage class specifier. /// These turn into simple stack objects, or GlobalValues depending on target. -void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D, - SpecialInitFn *SpecialInit) { +void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D) { + AutoVarEmission emission = EmitAutoVarAlloca(D); + EmitAutoVarInit(emission); + EmitAutoVarCleanups(emission); +} + +/// EmitAutoVarAlloca - Emit the alloca and debug information for a +/// local variable. Does not emit initalization or destruction. +CodeGenFunction::AutoVarEmission +CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { QualType Ty = D.getType(); - unsigned Alignment = getContext().getDeclAlign(&D).getQuantity(); + + AutoVarEmission emission(D); + bool isByRef = D.hasAttr<BlocksAttr>(); - bool needsDispose = false; - CharUnits Align = CharUnits::Zero(); - bool IsSimpleConstantInitializer = false; + emission.IsByRef = isByRef; + + CharUnits alignment = getContext().getDeclAlign(&D); + emission.Alignment = alignment; - bool NRVO = false; - llvm::Value *NRVOFlag = 0; llvm::Value *DeclPtr; if (Ty->isConstantSizeType()) { if (!Target.useGlobalsForAutomaticVariables()) { - NRVO = getContext().getLangOptions().ElideConstructors && - D.isNRVOVariable(); - // If this value is an array or struct, is POD, and if the initializer is - // a staticly determinable constant, try to optimize it (unless the NRVO - // is already optimizing this). - if (!NRVO && D.getInit() && !isByRef && - (Ty->isArrayType() || Ty->isRecordType()) && - Ty->isPODType() && + bool NRVO = getContext().getLangOptions().ElideConstructors && + D.isNRVOVariable(); + + // If this value is a POD array or struct with a statically + // determinable constant initializer, there are optimizations we + // can do. + // TODO: we can potentially constant-evaluate non-POD structs and + // arrays as long as the initialization is trivial (e.g. if they + // have a non-trivial destructor, but not a non-trivial constructor). + if (D.getInit() && + (Ty->isArrayType() || Ty->isRecordType()) && Ty->isPODType() && D.getInit()->isConstantInitializer(getContext(), false)) { - // If this variable is marked 'const', emit the value as a global. - if (CGM.getCodeGenOpts().MergeAllConstants && - Ty.isConstant(getContext())) { - EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage); - return; + + // If the variable's a const type, and it's neither an NRVO + // candidate nor a __block variable, emit it as a global instead. + if (CGM.getCodeGenOpts().MergeAllConstants && Ty.isConstQualified() && + !NRVO && !isByRef) { + EmitStaticVarDecl(D, llvm::GlobalValue::PrivateLinkage); + + emission.Address = 0; // signal this condition to later callbacks + assert(emission.wasEmittedAsGlobal()); + return emission; } - - IsSimpleConstantInitializer = true; + + // Otherwise, tell the initialization code that we're in this case. + emission.IsConstantAggregate = true; } // A normal fixed sized variable becomes an alloca in the entry block, @@ -646,12 +669,13 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D, // to this variable. Set it to zero to indicate that NRVO was not // applied. llvm::Value *Zero = Builder.getFalse(); - NRVOFlag = CreateTempAlloca(Zero->getType(), "nrvo"); + llvm::Value *NRVOFlag = CreateTempAlloca(Zero->getType(), "nrvo"); EnsureInsertPoint(); Builder.CreateStore(Zero, NRVOFlag); // Record the NRVO flag for this variable. NRVOFlags[&D] = NRVOFlag; + emission.NRVOFlag = NRVOFlag; } } } else { @@ -661,11 +685,11 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D, llvm::AllocaInst *Alloc = CreateTempAlloca(LTy); Alloc->setName(D.getNameAsString()); - Align = getContext().getDeclAlign(&D); + CharUnits allocaAlignment = alignment; if (isByRef) - Align = std::max(Align, + allocaAlignment = std::max(allocaAlignment, getContext().toCharUnitsFromBits(Target.getPointerAlign(0))); - Alloc->setAlignment(Align.getQuantity()); + Alloc->setAlignment(allocaAlignment.getQuantity()); DeclPtr = Alloc; } } else { @@ -707,7 +731,7 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D, // Allocate memory for the array. llvm::AllocaInst *VLA = Builder.CreateAlloca(llvm::Type::getInt8Ty(getLLVMContext()), VLASize, "vla"); - VLA->setAlignment(getContext().getDeclAlign(&D).getQuantity()); + VLA->setAlignment(alignment.getQuantity()); DeclPtr = Builder.CreateBitCast(VLA, LElemPtrTy, "tmp"); } @@ -715,6 +739,7 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D, llvm::Value *&DMEntry = LocalDeclMap[&D]; assert(DMEntry == 0 && "Decl already exists in localdeclmap!"); DMEntry = DeclPtr; + emission.Address = DeclPtr; // Emit debug info for local var declaration. if (CGDebugInfo *DI = getDebugInfo()) { @@ -727,53 +752,92 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D, DI->EmitDeclareOfAutoVariable(&D, DeclPtr, Builder); } + return emission; +} + +/// Determines whether the given __block variable is potentially +/// captured by the given expression. +static bool isCapturedBy(const VarDecl &var, const Expr *e) { + // Skip the most common kinds of expressions that make + // hierarchy-walking expensive. + e = e->IgnoreParenCasts(); + + if (const BlockExpr *be = dyn_cast<BlockExpr>(e)) { + const BlockDecl *block = be->getBlockDecl(); + for (BlockDecl::capture_const_iterator i = block->capture_begin(), + e = block->capture_end(); i != e; ++i) { + if (i->getVariable() == &var) + return true; + } + + // No need to walk into the subexpressions. + return false; + } + + for (Stmt::const_child_range children = e->children(); children; ++children) + if (isCapturedBy(var, cast<Expr>(*children))) + return true; + + return false; +} + +void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { + assert(emission.Variable && "emission was not valid!"); + + // If this was emitted as a global constant, we're done. + if (emission.wasEmittedAsGlobal()) return; + + const VarDecl &D = *emission.Variable; + QualType type = D.getType(); + // If this local has an initializer, emit it now. const Expr *Init = D.getInit(); // If we are at an unreachable point, we don't need to emit the initializer // unless it contains a label. if (!HaveInsertPoint()) { - if (!ContainsLabel(Init)) - Init = 0; - else - EnsureInsertPoint(); + if (!Init || !ContainsLabel(Init)) return; + EnsureInsertPoint(); } - if (isByRef) { - EnsureInsertPoint(); + CharUnits alignment = emission.Alignment; + + if (emission.IsByRef) { llvm::Value *V; BlockFieldFlags fieldFlags; bool fieldNeedsCopyDispose = false; - needsDispose = true; - - if (Ty->isBlockPointerType()) { + if (type->isBlockPointerType()) { fieldFlags |= BLOCK_FIELD_IS_BLOCK; fieldNeedsCopyDispose = true; - } else if (getContext().isObjCNSObjectType(Ty) || - Ty->isObjCObjectPointerType()) { + } else if (getContext().isObjCNSObjectType(type) || + type->isObjCObjectPointerType()) { fieldFlags |= BLOCK_FIELD_IS_OBJECT; fieldNeedsCopyDispose = true; } else if (getLangOptions().CPlusPlus) { if (getContext().getBlockVarCopyInits(&D)) fieldNeedsCopyDispose = true; - else if (const CXXRecordDecl *record = D.getType()->getAsCXXRecordDecl()) + else if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) fieldNeedsCopyDispose = !record->hasTrivialDestructor(); } + llvm::Value *addr = emission.Address; + // FIXME: Someone double check this. - if (Ty.isObjCGCWeak()) + if (type.isObjCGCWeak()) fieldFlags |= BLOCK_FIELD_IS_WEAK; + // Initialize the 'isa', which is just 0 or 1. int isa = 0; if (fieldFlags & BLOCK_FIELD_IS_WEAK) isa = 1; V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa"); - Builder.CreateStore(V, Builder.CreateStructGEP(DeclPtr, 0, "byref.isa")); + Builder.CreateStore(V, Builder.CreateStructGEP(addr, 0, "byref.isa")); - Builder.CreateStore(DeclPtr, Builder.CreateStructGEP(DeclPtr, 1, - "byref.forwarding")); + // Store the address of the variable into its own forwarding pointer. + Builder.CreateStore(addr, + Builder.CreateStructGEP(addr, 1, "byref.forwarding")); // Blocks ABI: // c) the flags field is set to either 0 if no helper functions are @@ -781,150 +845,157 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D, BlockFlags flags; if (fieldNeedsCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE; Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()), - Builder.CreateStructGEP(DeclPtr, 2, "byref.flags")); + Builder.CreateStructGEP(addr, 2, "byref.flags")); const llvm::Type *V1; - V1 = cast<llvm::PointerType>(DeclPtr->getType())->getElementType(); + V1 = cast<llvm::PointerType>(addr->getType())->getElementType(); V = llvm::ConstantInt::get(IntTy, CGM.GetTargetTypeStoreSize(V1).getQuantity()); - Builder.CreateStore(V, Builder.CreateStructGEP(DeclPtr, 3, "byref.size")); + Builder.CreateStore(V, Builder.CreateStructGEP(addr, 3, "byref.size")); if (fieldNeedsCopyDispose) { - llvm::Value *copy_helper = Builder.CreateStructGEP(DeclPtr, 4); - Builder.CreateStore(CGM.BuildbyrefCopyHelper(DeclPtr->getType(), - fieldFlags, - Align.getQuantity(), &D), + llvm::Value *copy_helper = Builder.CreateStructGEP(addr, 4); + Builder.CreateStore(CGM.BuildbyrefCopyHelper(addr->getType(), fieldFlags, + alignment.getQuantity(), &D), copy_helper); - llvm::Value *destroy_helper = Builder.CreateStructGEP(DeclPtr, 5); - Builder.CreateStore(CGM.BuildbyrefDestroyHelper(DeclPtr->getType(), + llvm::Value *destroy_helper = Builder.CreateStructGEP(addr, 5); + Builder.CreateStore(CGM.BuildbyrefDestroyHelper(addr->getType(), fieldFlags, - Align.getQuantity(), &D), + alignment.getQuantity(), + &D), destroy_helper); } } - if (SpecialInit) { - SpecialInit(*this, D, DeclPtr); - } else if (Init) { - llvm::Value *Loc = DeclPtr; - - bool isVolatile = getContext().getCanonicalType(Ty).isVolatileQualified(); + if (!Init) return; + + // Check whether this is a byref variable that's potentially + // captured and moved by its own initializer. If so, we'll need to + // emit the initializer first, then copy into the variable. + bool capturedByInit = emission.IsByRef && isCapturedBy(D, Init); + + llvm::Value *Loc = + capturedByInit ? emission.Address : emission.getObjectAddress(*this); + + bool isVolatile = type.isVolatileQualified(); - // If the initializer was a simple constant initializer, we can optimize it - // in various ways. - if (IsSimpleConstantInitializer) { - llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), Ty,this); - assert(Init != 0 && "Wasn't a simple constant init?"); - - llvm::Value *SizeVal = - llvm::ConstantInt::get(IntPtrTy, - getContext().getTypeSizeInChars(Ty).getQuantity()); - - const llvm::Type *BP = Int8PtrTy; - if (Loc->getType() != BP) - Loc = Builder.CreateBitCast(Loc, BP, "tmp"); + // If this is a simple aggregate initialization, we can optimize it + // in various ways. + if (emission.IsConstantAggregate) { + assert(!capturedByInit && "constant init contains a capturing block?"); + + llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), type, this); + assert(Init != 0 && "Wasn't a simple constant init?"); - // If the initializer is all or mostly zeros, codegen with memset then do - // a few stores afterward. - if (shouldUseMemSetPlusStoresToInitialize(Init, + llvm::Value *SizeVal = + llvm::ConstantInt::get(IntPtrTy, + getContext().getTypeSizeInChars(type).getQuantity()); + + const llvm::Type *BP = Int8PtrTy; + if (Loc->getType() != BP) + Loc = Builder.CreateBitCast(Loc, BP, "tmp"); + + // If the initializer is all or mostly zeros, codegen with memset then do + // a few stores afterward. + if (shouldUseMemSetPlusStoresToInitialize(Init, CGM.getTargetData().getTypeAllocSize(Init->getType()))) { - Builder.CreateMemSet(Loc, Builder.getInt8(0), SizeVal, - Align.getQuantity(), false); - if (!Init->isNullValue()) { - Loc = Builder.CreateBitCast(Loc, Init->getType()->getPointerTo()); - emitStoresForInitAfterMemset(Init, Loc, Builder); - } - - } else { - // Otherwise, create a temporary global with the initializer then - // memcpy from the global to the alloca. - std::string Name = GetStaticDeclName(*this, D, "."); - llvm::GlobalVariable *GV = + Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal, + alignment.getQuantity(), isVolatile); + if (!Init->isNullValue()) { + Loc = Builder.CreateBitCast(Loc, Init->getType()->getPointerTo()); + emitStoresForInitAfterMemset(Init, Loc, isVolatile, Builder); + } + } else { + // Otherwise, create a temporary global with the initializer then + // memcpy from the global to the alloca. + std::string Name = GetStaticDeclName(*this, D, "."); + llvm::GlobalVariable *GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), true, llvm::GlobalValue::InternalLinkage, Init, Name, 0, false, 0); - GV->setAlignment(Align.getQuantity()); + GV->setAlignment(alignment.getQuantity()); - llvm::Value *SrcPtr = GV; - if (SrcPtr->getType() != BP) - SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp"); + llvm::Value *SrcPtr = GV; + if (SrcPtr->getType() != BP) + SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp"); - Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, Align.getQuantity(), false); - } - } else if (Ty->isReferenceType()) { - RValue RV = EmitReferenceBindingToExpr(Init, &D); - if (isByRef) - Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D), - D.getNameAsString()); - EmitStoreOfScalar(RV.getScalarVal(), Loc, false, Alignment, Ty); - } else if (!hasAggregateLLVMType(Init->getType())) { - llvm::Value *V = EmitScalarExpr(Init); - if (isByRef) { - // When RHS has side-effect, must go through "forwarding' field - // to get to the address of the __block variable descriptor. - if (Init->HasSideEffects(getContext())) - Loc = BuildBlockByrefAddress(DeclPtr, &D); - else - Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D), - D.getNameAsString()); - } - EmitStoreOfScalar(V, Loc, isVolatile, Alignment, Ty); - } else if (Init->getType()->isAnyComplexType()) { - if (isByRef) - Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D), - D.getNameAsString()); - EmitComplexExprIntoAddr(Init, Loc, isVolatile); - } else { - if (isByRef) - Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D), - D.getNameAsString()); - EmitAggExpr(Init, AggValueSlot::forAddr(Loc, isVolatile, true, false)); + Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, alignment.getQuantity(), + isVolatile); } + } else if (type->isReferenceType()) { + RValue RV = EmitReferenceBindingToExpr(Init, &D); + if (capturedByInit) Loc = BuildBlockByrefAddress(Loc, &D); + EmitStoreOfScalar(RV.getScalarVal(), Loc, false, alignment.getQuantity(), + type); + } else if (!hasAggregateLLVMType(type)) { + llvm::Value *V = EmitScalarExpr(Init); + if (capturedByInit) Loc = BuildBlockByrefAddress(Loc, &D); + EmitStoreOfScalar(V, Loc, isVolatile, alignment.getQuantity(), type); + } else if (type->isAnyComplexType()) { + ComplexPairTy complex = EmitComplexExpr(Init); + if (capturedByInit) Loc = BuildBlockByrefAddress(Loc, &D); + StoreComplexToAddr(complex, Loc, isVolatile); + } else { + // TODO: how can we delay here if D is captured by its initializer? + EmitAggExpr(Init, AggValueSlot::forAddr(Loc, isVolatile, true, false)); } +} - // Handle CXX destruction of variables. - QualType DtorTy(Ty); - while (const ArrayType *Array = getContext().getAsArrayType(DtorTy)) - DtorTy = getContext().getBaseElementType(Array); - if (const RecordType *RT = DtorTy->getAs<RecordType>()) - if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) { +void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) { + assert(emission.Variable && "emission was not valid!"); + + // If this was emitted as a global constant, we're done. + if (emission.wasEmittedAsGlobal()) return; + + const VarDecl &D = *emission.Variable; + + // Handle C++ destruction of variables. + if (getLangOptions().CPlusPlus) { + QualType type = D.getType(); + QualType baseType = getContext().getBaseElementType(type); + if (const RecordType *RT = baseType->getAs<RecordType>()) { + CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl()); if (!ClassDecl->hasTrivialDestructor()) { // Note: We suppress the destructor call when the corresponding NRVO // flag has been set. - llvm::Value *Loc = DeclPtr; - if (isByRef) - Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D), - D.getNameAsString()); + + // Note that for __block variables, we want to destroy the + // original stack object, not the possible forwarded object. + llvm::Value *Loc = emission.getObjectAddress(*this); const CXXDestructorDecl *D = ClassDecl->getDestructor(); assert(D && "EmitLocalBlockVarDecl - destructor is nul"); - if (const ConstantArrayType *Array = - getContext().getAsConstantArrayType(Ty)) { + if (type != baseType) { + const ConstantArrayType *Array = + getContext().getAsConstantArrayType(type); + assert(Array && "types changed without array?"); EHStack.pushCleanup<CallArrayDtor>(NormalAndEHCleanup, D, Array, Loc); } else { EHStack.pushCleanup<CallVarDtor>(NormalAndEHCleanup, - D, NRVOFlag, Loc); + D, emission.NRVOFlag, Loc); } } + } } - // Handle the cleanup attribute + // Handle the cleanup attribute. if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) { const FunctionDecl *FD = CA->getFunctionDecl(); - llvm::Constant* F = CGM.GetAddrOfFunction(FD); + llvm::Constant *F = CGM.GetAddrOfFunction(FD); assert(F && "Could not find function!"); const CGFunctionInfo &Info = CGM.getTypes().getFunctionInfo(FD); - EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup, - F, &Info, DeclPtr, &D); + EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup, F, &Info, &D); } - // If this is a block variable, clean it up. - if (needsDispose && CGM.getLangOptions().getGCMode() != LangOptions::GCOnly) - EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup, DeclPtr); + // If this is a block variable, call _Block_object_destroy + // (on the unforwarded address). + if (emission.IsByRef && + CGM.getLangOptions().getGCMode() != LangOptions::GCOnly) + EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup, emission.Address); } /// Emit an alloca (or GlobalValue depending on target) @@ -933,6 +1004,24 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) { // FIXME: Why isn't ImplicitParamDecl a ParmVarDecl? assert((isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)) && "Invalid argument to EmitParmDecl"); + + Arg->setName(D.getName()); + + // Use better IR generation for certain implicit parameters. + if (isa<ImplicitParamDecl>(D)) { + // The only implicit argument a block has is its literal. + if (BlockInfo) { + LocalDeclMap[&D] = Arg; + + if (CGDebugInfo *DI = getDebugInfo()) { + DI->setLocation(D.getLocation()); + DI->EmitDeclareOfBlockLiteralArgVariable(*BlockInfo, Arg, Builder); + } + + return; + } + } + QualType Ty = D.getType(); llvm::Value *DeclPtr; @@ -949,7 +1038,6 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) { getContext().getDeclAlign(&D).getQuantity(), Ty, CGM.getTBAAInfo(Ty)); } - Arg->setName(D.getName()); llvm::Value *&DMEntry = LocalDeclMap[&D]; assert(DMEntry == 0 && "Decl already exists in localdeclmap!"); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp index 6181965..4bce081 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp @@ -1086,14 +1086,14 @@ static void BeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *S) { // 3. Enter __cxa_end_catch cleanup // 4. Enter dtor cleanup // - // We do this by initializing the exception variable with a - // "special initializer", InitCatchParam. Delegation sequence: + // We do this by using a slightly abnormal initialization process. + // Delegation sequence: // - ExitCXXTryStmt opens a RunCleanupsScope - // - EmitLocalBlockVarDecl creates the variable and debug info + // - EmitAutoVarAlloca creates the variable and debug info // - InitCatchParam initializes the variable from the exception - // - CallBeginCatch calls __cxa_begin_catch - // - CallBeginCatch enters the __cxa_end_catch cleanup - // - EmitLocalBlockVarDecl enters the variable destructor cleanup + // - CallBeginCatch calls __cxa_begin_catch + // - CallBeginCatch enters the __cxa_end_catch cleanup + // - EmitAutoVarCleanups enters the variable destructor cleanup // - EmitCXXTryStmt emits the code for the catch body // - EmitCXXTryStmt close the RunCleanupsScope @@ -1105,7 +1105,9 @@ static void BeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *S) { } // Emit the local. - CGF.EmitAutoVarDecl(*CatchParam, &InitCatchParam); + CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam); + InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF)); + CGF.EmitAutoVarCleanups(var); } namespace { diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp index 1b7e7a0..2abaadf 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp @@ -260,6 +260,10 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E, } } + if (const OpaqueValueExpr *opaque = dyn_cast<OpaqueValueExpr>(E)) + if (opaque->getType()->isRecordType()) + return CGF.EmitOpaqueValueLValue(opaque).getAddress(); + // Nothing changed. break; } @@ -1606,39 +1610,67 @@ LValue CodeGenFunction::EmitLValueForAnonRecordField(llvm::Value *BaseValue, } } -LValue CodeGenFunction::EmitLValueForField(llvm::Value *BaseValue, - const FieldDecl *Field, - unsigned CVRQualifiers) { - if (Field->isBitField()) - return EmitLValueForBitfield(BaseValue, Field, CVRQualifiers); +LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr, + const FieldDecl *field, + unsigned cvr) { + if (field->isBitField()) + return EmitLValueForBitfield(baseAddr, field, cvr); - const CGRecordLayout &RL = - CGM.getTypes().getCGRecordLayout(Field->getParent()); - unsigned idx = RL.getLLVMFieldNo(Field); - llvm::Value *V = Builder.CreateStructGEP(BaseValue, idx, "tmp"); + const RecordDecl *rec = field->getParent(); + QualType type = field->getType(); + + bool mayAlias = rec->hasAttr<MayAliasAttr>(); - // Match union field type. - if (Field->getParent()->isUnion()) { - const llvm::Type *FieldTy = - CGM.getTypes().ConvertTypeForMem(Field->getType()); - const llvm::PointerType *BaseTy = - cast<llvm::PointerType>(BaseValue->getType()); - unsigned AS = BaseTy->getAddressSpace(); - V = Builder.CreateBitCast(V, - llvm::PointerType::get(FieldTy, AS), - "tmp"); + llvm::Value *addr; + if (rec->isUnion()) { + // For unions, we just cast to the appropriate type. + assert(!type->isReferenceType() && "union has reference member"); + + const llvm::Type *llvmType = CGM.getTypes().ConvertTypeForMem(type); + unsigned AS = + cast<llvm::PointerType>(baseAddr->getType())->getAddressSpace(); + addr = Builder.CreateBitCast(baseAddr, llvmType->getPointerTo(AS), + field->getName()); + } else { + // For structs, we GEP to the field that the record layout suggests. + unsigned idx = CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field); + addr = Builder.CreateStructGEP(baseAddr, idx, field->getName()); + + // If this is a reference field, load the reference right now. + if (const ReferenceType *refType = type->getAs<ReferenceType>()) { + llvm::LoadInst *load = Builder.CreateLoad(addr, "ref"); + if (cvr & Qualifiers::Volatile) load->setVolatile(true); + + if (CGM.shouldUseTBAA()) { + llvm::MDNode *tbaa; + if (mayAlias) + tbaa = CGM.getTBAAInfo(getContext().CharTy); + else + tbaa = CGM.getTBAAInfo(type); + CGM.DecorateInstruction(load, tbaa); + } + + addr = load; + mayAlias = false; + type = refType->getPointeeType(); + cvr = 0; // qualifiers don't recursively apply to referencee + } } - if (Field->getType()->isReferenceType()) - V = Builder.CreateLoad(V, "tmp"); - unsigned Alignment = getContext().getDeclAlign(Field).getQuantity(); - LValue LV = MakeAddrLValue(V, Field->getType(), Alignment); - LV.getQuals().addCVRQualifiers(CVRQualifiers); + unsigned alignment = getContext().getDeclAlign(field).getQuantity(); + LValue LV = MakeAddrLValue(addr, type, alignment); + LV.getQuals().addCVRQualifiers(cvr); // __weak attribute on a field is ignored. if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak) LV.getQuals().removeObjCGCAttr(); - + + // Fields of may_alias structs act like 'char' for TBAA purposes. + // FIXME: this should get propagated down through anonymous structs + // and unions. + if (mayAlias && LV.getTBAAInfo()) + LV.setTBAAInfo(CGM.getTBAAInfo(getContext().CharTy)); + return LV; } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp index 08c458b..5d34907 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjC.cpp @@ -663,6 +663,11 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ return; } + // The local variable comes into scope immediately. + AutoVarEmission variable = AutoVarEmission::invalid(); + if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) + variable = EmitAutoVarAlloca(*cast<VarDecl>(SD->getSingleDecl())); + CGDebugInfo *DI = getDebugInfo(); if (DI) { DI->setLocation(S.getSourceRange().getBegin()); @@ -799,22 +804,23 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ // Initialize the element variable. RunCleanupsScope elementVariableScope(*this); - bool elementIsDecl; + bool elementIsVariable; LValue elementLValue; QualType elementType; if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) { - EmitStmt(SD); - const VarDecl* D = cast<VarDecl>(SD->getSingleDecl()); + // Initialize the variable, in case it's a __block variable or something. + EmitAutoVarInit(variable); + const VarDecl* D = cast<VarDecl>(SD->getSingleDecl()); DeclRefExpr tempDRE(const_cast<VarDecl*>(D), D->getType(), VK_LValue, SourceLocation()); elementLValue = EmitLValue(&tempDRE); elementType = D->getType(); - elementIsDecl = true; + elementIsVariable = true; } else { elementLValue = LValue(); // suppress warning elementType = cast<Expr>(S.getElement())->getType(); - elementIsDecl = false; + elementIsVariable = false; } const llvm::Type *convertedElementType = ConvertType(elementType); @@ -837,11 +843,16 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ // Make sure we have an l-value. Yes, this gets evaluated every // time through the loop. - if (!elementIsDecl) + if (!elementIsVariable) elementLValue = EmitLValue(cast<Expr>(S.getElement())); EmitStoreThroughLValue(RValue::get(CurrentItem), elementLValue, elementType); + // If we do have an element variable, this assignment is the end of + // its initialization. + if (elementIsVariable) + EmitAutoVarCleanups(variable); + // Perform the loop body, setting up break and continue labels. BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody)); { @@ -891,7 +902,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ // No more elements. EmitBlock(EmptyBB); - if (!elementIsDecl) { + if (!elementIsVariable) { // If the element was not a declaration, set it to be null. llvm::Value *null = llvm::Constant::getNullValue(convertedElementType); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp index d481e77..5f19dc6 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp @@ -949,7 +949,12 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure( Elements.push_back(MakeConstantString(Name, ".class_name")); Elements.push_back(Zero); Elements.push_back(llvm::ConstantInt::get(LongTy, info)); - Elements.push_back(InstanceSize); + if (isMeta) { + llvm::TargetData td(&TheModule); + Elements.push_back(llvm::ConstantInt::get(LongTy, + td.getTypeSizeInBits(ClassTy)/8)); + } else + Elements.push_back(InstanceSize); Elements.push_back(IVars); Elements.push_back(Methods); Elements.push_back(NULLPtr); @@ -1831,9 +1836,9 @@ llvm::Function *CGObjCGNU::GetPropertyGetFunction() { std::vector<const llvm::Type*> Params; Params.push_back(IdTy); Params.push_back(SelectorTy); - Params.push_back(IntTy); + Params.push_back(SizeTy); Params.push_back(BoolTy); - // void objc_getProperty (id, SEL, int, bool) + // void objc_getProperty (id, SEL, ptrdiff_t, bool) const llvm::FunctionType *FTy = llvm::FunctionType::get(IdTy, Params, false); return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy, @@ -1844,11 +1849,11 @@ llvm::Function *CGObjCGNU::GetPropertySetFunction() { std::vector<const llvm::Type*> Params; Params.push_back(IdTy); Params.push_back(SelectorTy); - Params.push_back(IntTy); + Params.push_back(SizeTy); Params.push_back(IdTy); Params.push_back(BoolTy); Params.push_back(BoolTy); - // void objc_setProperty (id, SEL, int, id, bool, bool) + // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool) const llvm::FunctionType *FTy = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false); return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy, diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp index 7c679b9..8dbd85f 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCMac.cpp @@ -46,6 +46,15 @@ using namespace CodeGen; // don't belong in CGObjCRuntime either so we will live with it for // now. +static void EmitNullReturnInitialization(CodeGenFunction &CGF, + ReturnValueSlot &returnSlot, + QualType resultType) { + // Force the return slot to exist. + if (!returnSlot.getValue()) + returnSlot = ReturnValueSlot(CGF.CreateMemTemp(resultType), false); + CGF.EmitNullInitialization(returnSlot.getValue(), resultType); +} + static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM, const ObjCInterfaceDecl *OID, const ObjCImplementationDecl *ID, @@ -1639,6 +1648,7 @@ CGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF, llvm::Constant *Fn = NULL; if (CGM.ReturnTypeUsesSRet(FnInfo)) { + EmitNullReturnInitialization(CGF, Return, ResultType); Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper) : ObjCTypes.getSendStretFn(IsSuper); } else if (CGM.ReturnTypeUsesFPRet(ResultType)) { @@ -5629,6 +5639,7 @@ CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend( llvm::Constant *Fn = 0; std::string Name("\01l_"); if (CGM.ReturnTypeUsesSRet(FnInfo)) { + EmitNullReturnInitialization(CGF, Return, ResultType); if (IsSuper) { Fn = ObjCTypes.getMessageSendSuper2StretFixupFn(); Name += "objc_msgSendSuper2_stret_fixup"; diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp index 4b19aef..ceae66f 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -207,8 +207,9 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types, uint64_t ContainingTypeSizeInBits, unsigned ContainingTypeAlign) { const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(FD->getType()); - uint64_t TypeSizeInBytes = Types.getTargetData().getTypeAllocSize(Ty); - uint64_t TypeSizeInBits = TypeSizeInBytes * 8; + CharUnits TypeSizeInBytes = + CharUnits::fromQuantity(Types.getTargetData().getTypeAllocSize(Ty)); + uint64_t TypeSizeInBits = Types.getContext().toBits(TypeSizeInBytes); bool IsSigned = FD->getType()->isSignedIntegerType(); @@ -249,7 +250,7 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types, uint64_t AccessStart = FieldOffset - (FieldOffset % AccessWidth); // Adjust initial access size to fit within record. - while (AccessWidth > 8 && + while (AccessWidth > Types.getTarget().getCharWidth() && AccessStart + AccessWidth > ContainingTypeSizeInBits) { AccessWidth >>= 1; AccessStart = FieldOffset - (FieldOffset % AccessWidth); @@ -262,7 +263,8 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types, if (AccessStart + AccessWidth > ContainingTypeSizeInBits) { // If so, reduce access size to the next smaller power-of-two and retry. AccessWidth >>= 1; - assert(AccessWidth >= 8 && "Cannot access under byte size!"); + assert(AccessWidth >= Types.getTarget().getCharWidth() + && "Cannot access under byte size!"); continue; } @@ -329,7 +331,7 @@ void CGRecordLayoutBuilder::LayoutBitField(const FieldDecl *D, if (fieldSize == 0) return; - uint64_t nextFieldOffsetInBits = NextFieldOffset.getQuantity() * 8; + uint64_t nextFieldOffsetInBits = Types.getContext().toBits(NextFieldOffset); unsigned numBytesToAppend; if (fieldOffset < nextFieldOffsetInBits) { @@ -378,8 +380,10 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D, CheckZeroInitializable(D->getType()); - assert(fieldOffset % 8 == 0 && "FieldOffset is not on a byte boundary!"); - CharUnits fieldOffsetInBytes = CharUnits::fromQuantity(fieldOffset / 8); + assert(fieldOffset % Types.getTarget().getCharWidth() == 0 + && "field offset is not on a byte boundary!"); + CharUnits fieldOffsetInBytes + = Types.getContext().toCharUnitsFromBits(fieldOffset); const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(D->getType()); CharUnits typeAlignment = getTypeAlignment(Ty); @@ -396,7 +400,7 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D, const RecordDecl *RD = cast<RecordDecl>(RT->getDecl()); if (const MaxFieldAlignmentAttr *MFAA = RD->getAttr<MaxFieldAlignmentAttr>()) { - if (MFAA->getAlignment() != typeAlignment.getQuantity() * 8) + if (MFAA->getAlignment() != Types.getContext().toBits(typeAlignment)) return false; } } @@ -728,7 +732,8 @@ bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { void CGRecordLayoutBuilder::AppendTailPadding(uint64_t RecordSize) { assert(RecordSize % 8 == 0 && "Invalid record size!"); - CharUnits RecordSizeInBytes = CharUnits::fromQuantity(RecordSize / 8); + CharUnits RecordSizeInBytes = + Types.getContext().toCharUnitsFromBits(RecordSize); assert(NextFieldOffset <= RecordSizeInBytes && "Size mismatch!"); CharUnits AlignedNextFieldOffset = @@ -920,7 +925,8 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) { // Verify that every component access is within the structure. uint64_t FieldOffset = SL->getElementOffsetInBits(AI.FieldIndex); - uint64_t AccessBitOffset = FieldOffset + AI.FieldByteOffset * 8; + uint64_t AccessBitOffset = FieldOffset + + getContext().toBits(CharUnits::fromQuantity(AI.FieldByteOffset)); assert(AccessBitOffset + AI.AccessWidth <= TypeSizeInBits && "Invalid bit-field access (out of range)!"); } diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h index 67ef414..be646fb 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.h @@ -1555,7 +1555,55 @@ public: /// EmitAutoVarDecl - Emit an auto variable declaration. /// /// This function can be called with a null (unreachable) insert point. - void EmitAutoVarDecl(const VarDecl &D, SpecialInitFn *SpecialInit = 0); + void EmitAutoVarDecl(const VarDecl &D); + + class AutoVarEmission { + friend class CodeGenFunction; + + const VarDecl *Variable; + + /// The alignment of the variable. + CharUnits Alignment; + + /// The address of the alloca. Null if the variable was emitted + /// as a global constant. + llvm::Value *Address; + + llvm::Value *NRVOFlag; + + /// True if the variable is a __block variable. + bool IsByRef; + + /// True if the variable is of aggregate type and has a constant + /// initializer. + bool IsConstantAggregate; + + struct Invalid {}; + AutoVarEmission(Invalid) : Variable(0) {} + + AutoVarEmission(const VarDecl &variable) + : Variable(&variable), Address(0), NRVOFlag(0), + IsByRef(false), IsConstantAggregate(false) {} + + bool wasEmittedAsGlobal() const { return Address == 0; } + + public: + static AutoVarEmission invalid() { return AutoVarEmission(Invalid()); } + + /// Returns the address of the object within this declaration. + /// Note that this does not chase the forwarding pointer for + /// __block decls. + llvm::Value *getObjectAddress(CodeGenFunction &CGF) const { + if (!IsByRef) return Address; + + return CGF.Builder.CreateStructGEP(Address, + CGF.getByRefValueLLVMField(Variable), + Variable->getNameAsString()); + } + }; + AutoVarEmission EmitAutoVarAlloca(const VarDecl &var); + void EmitAutoVarInit(const AutoVarEmission &emission); + void EmitAutoVarCleanups(const AutoVarEmission &emission); void EmitStaticVarDecl(const VarDecl &D, llvm::GlobalValue::LinkageTypes Linkage); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp index 9e5d7cf..a8453c3 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp @@ -97,6 +97,8 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, Int32Ty = llvm::Type::getInt32Ty(LLVMContext); Int64Ty = llvm::Type::getInt64Ty(LLVMContext); PointerWidthInBits = C.Target.getPointerWidth(0); + PointerAlignInBytes = + C.toCharUnitsFromBits(C.Target.getPointerAlign(0)).getQuantity(); IntTy = llvm::IntegerType::get(LLVMContext, C.Target.getIntWidth()); IntPtrTy = llvm::IntegerType::get(LLVMContext, PointerWidthInBits); Int8PtrTy = Int8Ty->getPointerTo(0); diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h index b6bd37c..73e6ece 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenModule.h @@ -120,8 +120,11 @@ namespace CodeGen { const llvm::PointerType *Int8PtrPtrTy; }; - /// The width of an address-zero pointer. + /// The width of a pointer into the generic address space. unsigned char PointerWidthInBits; + + /// The alignment of a pointer into the generic address space. + unsigned char PointerAlignInBytes; }; /// CodeGenModule - This class organizes the cross-function state that is used @@ -292,6 +295,8 @@ public: const TargetCodeGenInfo &getTargetCodeGenInfo(); bool isTargetDarwin() const; + bool shouldUseTBAA() const { return TBAA != 0; } + llvm::MDNode *getTBAAInfo(QualType QTy); static void DecorateInstruction(llvm::Instruction *Inst, @@ -386,8 +391,8 @@ public: unsigned Align, const VarDecl *variable); - /// getGlobalUniqueCount - Fetches the global unique block count. - int getGlobalUniqueCount() { return ++Block.GlobalUniqueCount; } + /// getUniqueBlockCount - Fetches the global unique block count. + int getUniqueBlockCount() { return ++Block.GlobalUniqueCount; } /// getBlockDescriptorType - Fetches the type of a generic block /// descriptor. diff --git a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp index d74b3f3..2ffc840 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp @@ -2105,8 +2105,15 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty) const { RT->getDecl()->hasFlexibleArrayMember()) return ABIArgInfo::getIndirect(0, /*ByVal=*/false); - // FIXME: mingw64-gcc emits 128-bit struct as i128 - if (Size <= 128 && + // FIXME: mingw-w64-gcc emits 128-bit struct as i128 + if (Size == 128 && + getContext().Target.getTriple().getOS() == llvm::Triple::MinGW32) + return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), + Size)); + + // MS x64 ABI requirement: "Any argument that doesn't fit in 8 bytes, or is + // not 1, 2, 4, or 8 bytes, must be passed by reference." + if (Size <= 64 && (Size & (Size - 1)) == 0) return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Size)); diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp index e4051a1..e305683 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp @@ -198,7 +198,8 @@ void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &Args, switch (Type) { case ToolChain::CST_Libcxx: - CmdArgs.push_back("-cxx-system-include"); + CmdArgs.push_back("-nostdinc++"); + CmdArgs.push_back("-cxx-isystem"); CmdArgs.push_back("/usr/include/c++/v1"); break; diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp index d94de20..422c572 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp @@ -46,7 +46,7 @@ Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple) // Compute the initial Darwin version based on the host. bool HadExtra; std::string OSName = Triple.getOSName(); - if (!Driver::GetReleaseVersion(&OSName[6], + if (!Driver::GetReleaseVersion(&OSName.c_str()[6], DarwinVersion[0], DarwinVersion[1], DarwinVersion[2], HadExtra)) getDriver().Diag(clang::diag::err_drv_invalid_darwin_version) << OSName; @@ -1271,6 +1271,7 @@ Tool &AuroraUX::SelectTool(const Compilation &C, const JobAction &JA) const { /// Linux toolchain (very bare-bones at the moment). enum LinuxDistro { + ArchLinux, DebianLenny, DebianSqueeze, Exherbo, @@ -1367,6 +1368,9 @@ static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) { if (!llvm::sys::fs::exists("/etc/exherbo-release", Exists) && Exists) return Exherbo; + if (!llvm::sys::fs::exists("/etc/arch-release", Exists) && Exists) + return ArchLinux; + return UnknownDistro; } @@ -1436,8 +1440,9 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) GccTriple = "i586-suse-linux"; } - const char* GccVersions[] = {"4.5.1", "4.5", "4.4.5", "4.4.4", "4.4.3", "4.4", - "4.3.4", "4.3.3", "4.3.2"}; + const char* GccVersions[] = {"4.5.2", "4.5.1", "4.5", "4.4.5", "4.4.4", + "4.4.3", "4.4", "4.3.4", "4.3.3", "4.3.2", + "4.3"}; std::string Base = ""; for (unsigned i = 0; i < sizeof(GccVersions)/sizeof(char*); ++i) { std::string Suffix = GccTriple + "/" + GccVersions[i]; @@ -1498,6 +1503,9 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) Distro == UbuntuKarmic) ExtraOpts.push_back("--build-id"); + if (Distro == ArchLinux) + Lib = "lib"; + Paths.push_back(Base + Suffix); if (HasMultilib(Arch, Distro)) { if (IsOpenSuse(Distro) && Is32Bits) diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp index 0697d54..a2c95fc 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp @@ -1552,10 +1552,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fobjc-default-synthesize-properties"); } - // -fobjc-exceptions is default. - if (!Args.hasFlag(options::OPT_fobjc_exceptions, - options::OPT_fno_objc_exceptions)) - CmdArgs.push_back("-fno-objc-exceptions"); + // -fno-objc-exceptions is default. + if (IsRewriter || Args.hasFlag(options::OPT_fobjc_exceptions, + options::OPT_fno_objc_exceptions)) + CmdArgs.push_back("-fobjc-exceptions"); } if (!Args.hasFlag(options::OPT_fassume_sane_operator_new, @@ -3091,7 +3091,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-lgcc"); if (Args.hasArg(options::OPT_pthread)) - CmdArgs.push_back("-pthread"); + CmdArgs.push_back("-lpthread"); if (!Args.hasArg(options::OPT_shared)) CmdArgs.push_back("-lc"); CmdArgs.push_back("-lgcc"); diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp index 4a5a51d..a7942e6 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp @@ -389,7 +389,8 @@ public: virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, llvm::StringRef OriginalFileName, - std::string &SuggestedPredefines) { + std::string &SuggestedPredefines, + FileManager &FileMgr) { Predefines = Buffers[0].Data; for (unsigned I = 1, N = Buffers.size(); I != N; ++I) { Predefines += Buffers[I].Data; diff --git a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp index beb5ad2..4b44c48 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp @@ -78,6 +78,8 @@ static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts, std::vector<std::string> &Res) { for (unsigned i = 0, e = Opts.AnalysisList.size(); i != e; ++i) Res.push_back(getAnalysisName(Opts.AnalysisList[i])); + if (Opts.ShowCheckerHelp) + Res.push_back("-analyzer-checker-help"); if (Opts.AnalysisStoreOpt != BasicStoreModel) { Res.push_back("-analyzer-store"); Res.push_back(getAnalysisStoreName(Opts.AnalysisStoreOpt)); @@ -114,8 +116,6 @@ static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts, Res.push_back("-analyzer-viz-egraph-ubigraph"); if (Opts.EnableExperimentalChecks) Res.push_back("-analyzer-experimental-checks"); - if (Opts.EnableExperimentalInternalChecks) - Res.push_back("-analyzer-experimental-internal-checks"); if (Opts.BufferOverflows) Res.push_back("-analyzer-check-buffer-overflows"); @@ -473,11 +473,6 @@ static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts, Res.push_back(Opts.Sysroot); } - for (unsigned i = 0, e = Opts.CXXSystemIncludes.size(); i != e; ++i) { - Res.push_back("-cxx-system-include"); - Res.push_back(Opts.CXXSystemIncludes[i]); - } - /// User specified include entries. for (unsigned i = 0, e = Opts.UserEntries.size(); i != e; ++i) { const HeaderSearchOptions::Entry &E = Opts.UserEntries[i]; @@ -490,6 +485,8 @@ static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts, Res.push_back("-iquote"); } else if (E.Group == frontend::System) { Res.push_back("-isystem"); + } else if (E.Group == frontend::CXXSystem) { + Res.push_back("-cxx-isystem"); } else { assert(E.Group == frontend::Angled && "Invalid group!"); Res.push_back(E.IsFramework ? "-F" : "-I"); @@ -588,10 +585,12 @@ static void LangOptsToArgs(const LangOptions &Opts, Res.push_back("-faltivec"); if (Opts.Exceptions) Res.push_back("-fexceptions"); + if (Opts.ObjCExceptions) + Res.push_back("-fobjc-exceptions"); + if (Opts.CXXExceptions) + Res.push_back("-fcxx-exceptions"); if (Opts.SjLjExceptions) Res.push_back("-fsjlj-exceptions"); - if (!Opts.ObjCExceptions) - Res.push_back("-fno-objc-exceptions"); if (!Opts.RTTI) Res.push_back("-fno-rtti"); if (Opts.MSBitfields) @@ -864,6 +863,7 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, Opts.AnalysisDiagOpt = Value; } + Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help); Opts.VisualizeEGDot = Args.hasArg(OPT_analyzer_viz_egraph_graphviz); Opts.VisualizeEGUbi = Args.hasArg(OPT_analyzer_viz_egraph_ubigraph); Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers); @@ -878,8 +878,6 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, Opts.CFGAddImplicitDtors = Args.hasArg(OPT_analysis_CFGAddImplicitDtors); Opts.CFGAddInitializers = Args.hasArg(OPT_analysis_CFGAddInitializers); Opts.EnableExperimentalChecks = Args.hasArg(OPT_analyzer_experimental_checks); - Opts.EnableExperimentalInternalChecks = - Args.hasArg(OPT_analyzer_experimental_internal_checks); Opts.TrimGraph = Args.hasArg(OPT_trim_egraph); Opts.MaxNodes = Args.getLastArgIntValue(OPT_analyzer_max_nodes, 150000,Diags); Opts.MaxLoop = Args.getLastArgIntValue(OPT_analyzer_max_loop, 4, Diags); @@ -894,8 +892,13 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, const Arg *A = *it; A->claim(); bool enable = (A->getOption().getID() == OPT_analyzer_checker); - Opts.CheckersControlList.push_back(std::make_pair(A->getValue(Args), - enable)); + // We can have a list of comma separated checker names, e.g: + // '-analyzer-checker=cocoa,unix' + llvm::StringRef checkerList = A->getValue(Args); + llvm::SmallVector<llvm::StringRef, 4> checkers; + checkerList.split(checkers, ","); + for (unsigned i = 0, e = checkers.size(); i != e; ++i) + Opts.CheckersControlList.push_back(std::make_pair(checkers[i], enable)); } } @@ -1238,7 +1241,6 @@ std::string CompilerInvocation::GetResourcesPath(const char *Argv0, static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) { using namespace cc1options; - Opts.CXXSystemIncludes = Args.getAllArgValues(OPT_cxx_system_include); Opts.Sysroot = Args.getLastArgValue(OPT_isysroot, "/"); Opts.Verbose = Args.hasArg(OPT_v); Opts.UseBuiltinIncludes = !Args.hasArg(OPT_nobuiltininc); @@ -1274,10 +1276,12 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) { for (arg_iterator it = Args.filtered_begin(OPT_iquote), ie = Args.filtered_end(); it != ie; ++it) Opts.AddPath((*it)->getValue(Args), frontend::Quoted, true, false, true); - for (arg_iterator it = Args.filtered_begin(OPT_isystem, OPT_iwithsysroot), - ie = Args.filtered_end(); it != ie; ++it) - Opts.AddPath((*it)->getValue(Args), frontend::System, true, false, - (*it)->getOption().matches(OPT_iwithsysroot)); + for (arg_iterator it = Args.filtered_begin(OPT_cxx_isystem, OPT_isystem, + OPT_iwithsysroot), ie = Args.filtered_end(); it != ie; ++it) + Opts.AddPath((*it)->getValue(Args), + ((*it)->getOption().matches(OPT_cxx_isystem) ? + frontend::CXXSystem : frontend::System), + true, false, (*it)->getOption().matches(OPT_iwithsysroot)); // FIXME: Need options for the various environment variables! } @@ -1459,7 +1463,10 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, if (Args.hasArg(OPT_fno_threadsafe_statics)) Opts.ThreadsafeStatics = 0; Opts.Exceptions = Args.hasArg(OPT_fexceptions); - Opts.ObjCExceptions = !Args.hasArg(OPT_fno_objc_exceptions); + Opts.ObjCExceptions = Args.hasArg(OPT_fobjc_exceptions); + Opts.CXXExceptions = Args.hasArg(OPT_fcxx_exceptions); + Opts.SjLjExceptions = Args.hasArg(OPT_fsjlj_exceptions); + Opts.RTTI = !Args.hasArg(OPT_fno_rtti); Opts.Blocks = Args.hasArg(OPT_fblocks); Opts.CharIsSigned = !Args.hasArg(OPT_fno_signed_char); @@ -1489,8 +1496,6 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.CatchUndefined = Args.hasArg(OPT_fcatch_undefined_behavior); Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls); Opts.PICLevel = Args.getLastArgIntValue(OPT_pic_level, 0, Diags); - Opts.SjLjExceptions = Args.hasArg(OPT_fsjlj_exceptions); - Opts.ObjCExceptions = !Args.hasArg(OPT_fno_objc_exceptions); Opts.Static = Args.hasArg(OPT_static_define); Opts.DumpRecordLayouts = Args.hasArg(OPT_fdump_record_layouts); Opts.DumpVTableLayouts = Args.hasArg(OPT_fdump_vtable_layouts); @@ -1661,8 +1666,11 @@ void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), *Args, Diags); ParseCodeGenArgs(Res.getCodeGenOpts(), *Args, DashX, Diags); ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), *Args); - if (DashX != IK_AST && DashX != IK_LLVM_IR) + if (DashX != IK_AST && DashX != IK_LLVM_IR) { ParseLangArgs(Res.getLangOpts(), *Args, DashX, Diags); + if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC) + Res.getLangOpts().ObjCExceptions = 1; + } // FIXME: ParsePreprocessorArgs uses the FileManager to read the contents of // PCH file and find the original header name. Remove the need to do that in // ParsePreprocessorArgs and remove the FileManager diff --git a/contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp b/contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp index b24ece5..a09db0b 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/DocumentXML.cpp @@ -14,6 +14,7 @@ #include "clang/Frontend/DocumentXML.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/StringExtras.h" @@ -218,6 +219,10 @@ void DocumentXML::addPtrAttribute(const char* pAttributeName, addPtrAttribute(pAttributeName, pNNS->getAsNamespace()); break; } + case NestedNameSpecifier::NamespaceAlias: { + addPtrAttribute(pAttributeName, pNNS->getAsNamespaceAlias()); + break; + } case NestedNameSpecifier::TypeSpec: { addPtrAttribute(pAttributeName, pNNS->getAsType()); break; diff --git a/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp b/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp index 69199e2..566b96c 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp @@ -46,7 +46,9 @@ namespace { /// a HeaderSearch object. InitHeaderSearch stores several search path lists /// internally, which can be sent to a HeaderSearch object in one swoop. class InitHeaderSearch { - std::vector<DirectoryLookup> IncludeGroup[4]; + std::vector<std::pair<IncludeDirGroup, DirectoryLookup> > IncludePath; + typedef std::vector<std::pair<IncludeDirGroup, + DirectoryLookup> >::const_iterator path_iterator; HeaderSearch& Headers; bool Verbose; std::string IncludeSysroot; @@ -98,7 +100,7 @@ public: /// Realize - Merges all search path lists into one list and send it to /// HeaderSearch. - void Realize(); + void Realize(const LangOptions &Lang); }; } @@ -135,8 +137,8 @@ void InitHeaderSearch::AddPath(const llvm::Twine &Path, // If the directory exists, add it. if (const DirectoryEntry *DE = FM.getDirectory(MappedPathStr)) { - IncludeGroup[Group].push_back(DirectoryLookup(DE, Type, isUserSupplied, - isFramework)); + IncludePath.push_back(std::make_pair(Group, DirectoryLookup(DE, Type, + isUserSupplied, isFramework))); return; } @@ -146,7 +148,8 @@ void InitHeaderSearch::AddPath(const llvm::Twine &Path, if (const FileEntry *FE = FM.getFile(MappedPathStr)) { if (const HeaderMap *HM = Headers.CreateHeaderMap(FE)) { // It is a headermap, add it to the search path. - IncludeGroup[Group].push_back(DirectoryLookup(HM, Type,isUserSupplied)); + IncludePath.push_back(std::make_pair(Group, DirectoryLookup(HM, Type, + isUserSupplied))); return; } } @@ -183,29 +186,29 @@ void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(llvm::StringRef Base, llvm::StringRef Dir64, const llvm::Triple &triple) { // Add the base dir - AddPath(Base, System, true, false, false); + AddPath(Base, CXXSystem, true, false, false); // Add the multilib dirs llvm::Triple::ArchType arch = triple.getArch(); bool is64bit = arch == llvm::Triple::ppc64 || arch == llvm::Triple::x86_64; if (is64bit) - AddPath(Base + "/" + ArchDir + "/" + Dir64, System, true, false, false); + AddPath(Base + "/" + ArchDir + "/" + Dir64, CXXSystem, true, false, false); else - AddPath(Base + "/" + ArchDir + "/" + Dir32, System, true, false, false); + AddPath(Base + "/" + ArchDir + "/" + Dir32, CXXSystem, true, false, false); // Add the backward dir - AddPath(Base + "/backward", System, true, false, false); + AddPath(Base + "/backward", CXXSystem, true, false, false); } void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base, llvm::StringRef Arch, llvm::StringRef Version) { AddPath(Base + "/" + Arch + "/" + Version + "/include/c++", - System, true, false, false); + CXXSystem, true, false, false); AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/" + Arch, - System, true, false, false); + CXXSystem, true, false, false); AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/backward", - System, true, false, false); + CXXSystem, true, false, false); } // FIXME: This probably should goto to some platform utils place. @@ -576,13 +579,17 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) { break; case llvm::Triple::MinGW32: // mingw-w64-20110207 - AddPath("c:/MinGW/include/c++/4.5.3", System, true, false, false); - AddPath("c:/MinGW/include/c++/4.5.3/x86_64-w64-mingw32", System, true, false, false); - AddPath("c:/MinGW/include/c++/4.5.3/backward", System, true, false, false); + AddPath("c:/MinGW/include/c++/4.5.3", CXXSystem, true, false, false); + AddPath("c:/MinGW/include/c++/4.5.3/x86_64-w64-mingw32", CXXSystem, true, + false, false); + AddPath("c:/MinGW/include/c++/4.5.3/backward", CXXSystem, true, false, + false); // mingw-w64-20101129 - AddPath("c:/MinGW/include/c++/4.5.2", System, true, false, false); - AddPath("c:/MinGW/include/c++/4.5.2/x86_64-w64-mingw32", System, true, false, false); - AddPath("c:/MinGW/include/c++/4.5.2/backward", System, true, false, false); + AddPath("c:/MinGW/include/c++/4.5.2", CXXSystem, true, false, false); + AddPath("c:/MinGW/include/c++/4.5.2/x86_64-w64-mingw32", CXXSystem, true, + false, false); + AddPath("c:/MinGW/include/c++/4.5.2/backward", CXXSystem, true, false, + false); // Try gcc 4.5.0 AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.5.0"); // Try gcc 4.4.0 @@ -622,7 +629,7 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) { } break; case llvm::Triple::DragonFly: - AddPath("/usr/include/c++/4.1", System, true, false, false); + AddPath("/usr/include/c++/4.1", CXXSystem, true, false, false); break; case llvm::Triple::Linux: //===------------------------------------------------------------------===// @@ -821,13 +828,8 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) { void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang, const llvm::Triple &triple, const HeaderSearchOptions &HSOpts) { - if (Lang.CPlusPlus && HSOpts.UseStandardCXXIncludes) { - if (!HSOpts.CXXSystemIncludes.empty()) { - for (unsigned i = 0, e = HSOpts.CXXSystemIncludes.size(); i != e; ++i) - AddPath(HSOpts.CXXSystemIncludes[i], System, true, false, false); - } else - AddDefaultCPlusPlusIncludePaths(triple); - } + if (Lang.CPlusPlus && HSOpts.UseStandardCXXIncludes) + AddDefaultCPlusPlusIncludePaths(triple); AddDefaultCIncludePaths(triple, HSOpts); @@ -841,11 +843,11 @@ void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang, /// RemoveDuplicates - If there are duplicate directory entries in the specified /// search list, remove the later (dead) ones. static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList, - bool Verbose) { + unsigned First, bool Verbose) { llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs; llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs; llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps; - for (unsigned i = 0; i != SearchList.size(); ++i) { + for (unsigned i = First; i != SearchList.size(); ++i) { unsigned DirToRemove = i; const DirectoryLookup &CurEntry = SearchList[i]; @@ -920,32 +922,49 @@ static void RemoveDuplicates(std::vector<DirectoryLookup> &SearchList, } -void InitHeaderSearch::Realize() { +void InitHeaderSearch::Realize(const LangOptions &Lang) { // Concatenate ANGLE+SYSTEM+AFTER chains together into SearchList. std::vector<DirectoryLookup> SearchList; - SearchList = IncludeGroup[Angled]; - SearchList.insert(SearchList.end(), IncludeGroup[System].begin(), - IncludeGroup[System].end()); - SearchList.insert(SearchList.end(), IncludeGroup[After].begin(), - IncludeGroup[After].end()); - RemoveDuplicates(SearchList, Verbose); - RemoveDuplicates(IncludeGroup[Quoted], Verbose); + SearchList.reserve(IncludePath.size()); + + /* Quoted arguments go first. */ + for (path_iterator it = IncludePath.begin(), ie = IncludePath.end(); + it != ie; ++it) { + if (it->first == Quoted) + SearchList.push_back(it->second); + } + /* Deduplicate and remember index */ + RemoveDuplicates(SearchList, 0, Verbose); + unsigned quoted = SearchList.size(); + + for (path_iterator it = IncludePath.begin(), ie = IncludePath.end(); + it != ie; ++it) { + if (it->first == Angled) + SearchList.push_back(it->second); + } - // Prepend QUOTED list on the search list. - SearchList.insert(SearchList.begin(), IncludeGroup[Quoted].begin(), - IncludeGroup[Quoted].end()); + for (path_iterator it = IncludePath.begin(), ie = IncludePath.end(); + it != ie; ++it) { + if (it->first == System || (Lang.CPlusPlus && it->first == CXXSystem)) + SearchList.push_back(it->second); + } + + for (path_iterator it = IncludePath.begin(), ie = IncludePath.end(); + it != ie; ++it) { + if (it->first == After) + SearchList.push_back(it->second); + } + RemoveDuplicates(SearchList, quoted, Verbose); bool DontSearchCurDir = false; // TODO: set to true if -I- is set? - Headers.SetSearchPaths(SearchList, IncludeGroup[Quoted].size(), - DontSearchCurDir); + Headers.SetSearchPaths(SearchList, quoted, DontSearchCurDir); // If verbose, print the list of directories that will be searched. if (Verbose) { llvm::errs() << "#include \"...\" search starts here:\n"; - unsigned QuotedIdx = IncludeGroup[Quoted].size(); for (unsigned i = 0, e = SearchList.size(); i != e; ++i) { - if (i == QuotedIdx) + if (i == quoted) llvm::errs() << "#include <...> search starts here:\n"; const char *Name = SearchList[i].getName(); const char *Suffix; @@ -990,5 +1009,5 @@ void clang::ApplyHeaderSearchOptions(HeaderSearch &HS, if (HSOpts.UseStandardIncludes) Init.AddDefaultSystemIncludePaths(Lang, Triple, HSOpts); - Init.Realize(); + Init.Realize(Lang); } diff --git a/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp b/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp index d0111a5..91b5280 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp @@ -48,12 +48,13 @@ static void DefineBuiltinMacro(MacroBuilder &Builder, llvm::StringRef Macro, } } -std::string clang::NormalizeDashIncludePath(llvm::StringRef File) { +std::string clang::NormalizeDashIncludePath(llvm::StringRef File, + FileManager &FileMgr) { // Implicit include paths should be resolved relative to the current // working directory first, and then use the regular header search // mechanism. The proper way to handle this is to have the // predefines buffer located at the current working directory, but - // it has not file entry. For now, workaround this by using an + // it has no file entry. For now, workaround this by using an // absolute path if we find the file here, and otherwise letting // header search handle it. llvm::SmallString<128> Path(File); @@ -61,21 +62,25 @@ std::string clang::NormalizeDashIncludePath(llvm::StringRef File) { bool exists; if (llvm::sys::fs::exists(Path.str(), exists) || !exists) Path = File; + else if (exists) + FileMgr.getFile(File); return Lexer::Stringify(Path.str()); } /// AddImplicitInclude - Add an implicit #include of the specified file to the /// predefines buffer. -static void AddImplicitInclude(MacroBuilder &Builder, llvm::StringRef File) { +static void AddImplicitInclude(MacroBuilder &Builder, llvm::StringRef File, + FileManager &FileMgr) { Builder.append("#include \"" + - llvm::Twine(NormalizeDashIncludePath(File)) + "\""); + llvm::Twine(NormalizeDashIncludePath(File, FileMgr)) + "\""); } static void AddImplicitIncludeMacros(MacroBuilder &Builder, - llvm::StringRef File) { + llvm::StringRef File, + FileManager &FileMgr) { Builder.append("#__include_macros \"" + - llvm::Twine(NormalizeDashIncludePath(File)) + "\""); + llvm::Twine(NormalizeDashIncludePath(File, FileMgr)) + "\""); // Marker token to stop the __include_macros fetch loop. Builder.append("##"); // ##? } @@ -94,7 +99,7 @@ static void AddImplicitIncludePTH(MacroBuilder &Builder, Preprocessor &PP, return; } - AddImplicitInclude(Builder, OriginalFile); + AddImplicitInclude(Builder, OriginalFile, PP.getFileManager()); } /// PickFP - This is used to pick a value based on the FP semantics of the @@ -169,15 +174,10 @@ static void DefineFloatMacros(MacroBuilder &Builder, llvm::StringRef Prefix, /// signedness of 'isSigned' and with a value suffix of 'ValSuffix' (e.g. LL). static void DefineTypeSize(llvm::StringRef MacroName, unsigned TypeWidth, llvm::StringRef ValSuffix, bool isSigned, - MacroBuilder& Builder) { - long long MaxVal; - if (isSigned) { - assert(TypeWidth != 1); - MaxVal = ~0ULL >> (65-TypeWidth); - } else - MaxVal = ~0ULL >> (64-TypeWidth); - - Builder.defineMacro(MacroName, llvm::Twine(MaxVal) + ValSuffix); + MacroBuilder &Builder) { + llvm::APInt MaxVal = isSigned ? llvm::APInt::getSignedMaxValue(TypeWidth) + : llvm::APInt::getMaxValue(TypeWidth); + Builder.defineMacro(MacroName, MaxVal.toString(10, isSigned) + ValSuffix); } /// DefineTypeSize - An overloaded helper that uses TargetInfo to determine @@ -590,7 +590,8 @@ void clang::InitializePreprocessor(Preprocessor &PP, // If -imacros are specified, include them now. These are processed before // any -include directives. for (unsigned i = 0, e = InitOpts.MacroIncludes.size(); i != e; ++i) - AddImplicitIncludeMacros(Builder, InitOpts.MacroIncludes[i]); + AddImplicitIncludeMacros(Builder, InitOpts.MacroIncludes[i], + PP.getFileManager()); // Process -include directives. for (unsigned i = 0, e = InitOpts.Includes.size(); i != e; ++i) { @@ -598,7 +599,7 @@ void clang::InitializePreprocessor(Preprocessor &PP, if (Path == InitOpts.ImplicitPTHInclude) AddImplicitIncludePTH(Builder, PP, Path); else - AddImplicitInclude(Builder, Path); + AddImplicitInclude(Builder, Path, PP.getFileManager()); } // Exit the command line and go back to <built-in> (2 is LC_LEAVE). diff --git a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp index 04c6a68..0849153 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp @@ -905,9 +905,21 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, std::string OptionName; if (DiagOpts->ShowOptionNames) { + // Was this a warning mapped to an error using -Werror or pragma? + if (Level == Diagnostic::Error && + DiagnosticIDs::isBuiltinWarningOrExtension(Info.getID())) { + diag::Mapping mapping = diag::MAP_IGNORE; + Info.getDiags()->getDiagnosticLevel(Info.getID(), Info.getLocation(), + &mapping); + if (mapping == diag::MAP_WARNING) + OptionName += "-Werror"; + } + if (const char * Opt = DiagnosticIDs::getWarningOptionForDiag(Info.getID())) { - OptionName = "-W"; + if (!OptionName.empty()) + OptionName += ','; + OptionName += "-W"; OptionName += Opt; } else if (Info.getID() == diag::fatal_too_many_errors) { OptionName = "-ferror-limit="; diff --git a/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticsClient.cpp b/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticsClient.cpp index 51b351f..fff417e 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticsClient.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/VerifyDiagnosticsClient.cpp @@ -369,7 +369,7 @@ static unsigned PrintProblem(Diagnostic &Diags, SourceManager *SourceMgr, if (I->first.isInvalid() || !SourceMgr) OS << "\n (frontend)"; else - OS << "\n Line " << SourceMgr->getInstantiationLineNumber(I->first); + OS << "\n Line " << SourceMgr->getPresumedLineNumber(I->first); OS << ": " << I->second; } @@ -391,7 +391,7 @@ static unsigned PrintProblem(Diagnostic &Diags, SourceManager *SourceMgr, if (D.Location.isInvalid() || !SourceMgr) OS << "\n (frontend)"; else - OS << "\n Line " << SourceMgr->getInstantiationLineNumber(D.Location); + OS << "\n Line " << SourceMgr->getPresumedLineNumber(D.Location); OS << ": " << D.Text; } @@ -413,12 +413,12 @@ static unsigned CheckLists(Diagnostic &Diags, SourceManager &SourceMgr, for (DirectiveList::iterator I = Left.begin(), E = Left.end(); I != E; ++I) { Directive& D = **I; - unsigned LineNo1 = SourceMgr.getInstantiationLineNumber(D.Location); + unsigned LineNo1 = SourceMgr.getPresumedLineNumber(D.Location); for (unsigned i = 0; i < D.Count; ++i) { DiagList::iterator II, IE; for (II = Right.begin(), IE = Right.end(); II != IE; ++II) { - unsigned LineNo2 = SourceMgr.getInstantiationLineNumber(II->first); + unsigned LineNo2 = SourceMgr.getPresumedLineNumber(II->first); if (LineNo1 != LineNo2) continue; diff --git a/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 4bb85e7..65fad6d 100644 --- a/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -108,6 +108,12 @@ bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) { return 0; } + // Honor -analyzer-checker-help. + if (Clang->getAnalyzerOpts().ShowCheckerHelp) { + ento::printCheckerHelp(llvm::outs()); + return 0; + } + // Honor -version. // // FIXME: Use a better -version message? diff --git a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp index 0f0d25b..3e871ae 100644 --- a/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/PPDirectives.cpp @@ -86,6 +86,7 @@ void Preprocessor::DiscardUntilEndOfDirective() { Token Tmp; do { LexUnexpandedToken(Tmp); + assert(Tmp.isNot(tok::eof) && "EOF seen while discarding directive tokens"); } while (Tmp.isNot(tok::eom)); } @@ -167,10 +168,12 @@ void Preprocessor::CheckEndOfDirective(const char *DirType, bool EnableMacros) { if (Tmp.isNot(tok::eom)) { // Add a fixit in GNU/C99/C++ mode. Don't offer a fixit for strict-C89, - // because it is more trouble than it is worth to insert /**/ and check that - // there is no /**/ in the range also. + // or if this is a macro-style preprocessing directive, because it is more + // trouble than it is worth to insert /**/ and check that there is no /**/ + // in the range also. FixItHint Hint; - if (Features.GNUMode || Features.C99 || Features.CPlusPlus) + if ((Features.GNUMode || Features.C99 || Features.CPlusPlus) && + !CurTokenLexer) Hint = FixItHint::CreateInsertion(Tmp.getLocation(),"//"); Diag(Tmp, diag::ext_pp_extra_tokens_at_eol) << DirType << Hint; DiscardUntilEndOfDirective(); diff --git a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp index f0475bc..80d3bb1 100644 --- a/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/Pragma.cpp @@ -110,7 +110,8 @@ void Preprocessor::HandlePragmaDirective(unsigned Introducer) { PragmaHandlers->HandlePragma(*this, PragmaIntroducerKind(Introducer), Tok); // If the pragma handler didn't read the rest of the line, consume it now. - if (CurPPLexer && CurPPLexer->ParsingPreprocessorDirective) + if ((CurTokenLexer && CurTokenLexer->isParsingPreprocessorDirective()) + || (CurPPLexer && CurPPLexer->ParsingPreprocessorDirective)) DiscardUntilEndOfDirective(); } @@ -174,7 +175,22 @@ void Preprocessor::Handle_Pragma(Token &Tok) { } } - Handle_Pragma(PIK__Pragma, StrVal, PragmaLoc, RParenLoc); + // Plop the string (including the newline and trailing null) into a buffer + // where we can lex it. + Token TmpTok; + TmpTok.startToken(); + CreateString(&StrVal[0], StrVal.size(), TmpTok); + SourceLocation TokLoc = TmpTok.getLocation(); + + // Make and enter a lexer object so that we lex and expand the tokens just + // like any others. + Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, PragmaLoc, RParenLoc, + StrVal.size(), *this); + + EnterSourceFileWithLexer(TL, 0); + + // With everything set up, lex this as a #pragma directive. + HandlePragmaDirective(PIK__Pragma); // Finally, return whatever came after the pragma directive. return Lex(Tok); @@ -193,16 +209,16 @@ void Preprocessor::HandleMicrosoft__pragma(Token &Tok) { return; } - // Get the tokens enclosed within the __pragma(). + // Get the tokens enclosed within the __pragma(), as well as the final ')'. llvm::SmallVector<Token, 32> PragmaToks; int NumParens = 0; Lex(Tok); while (Tok.isNot(tok::eof)) { + PragmaToks.push_back(Tok); if (Tok.is(tok::l_paren)) NumParens++; else if (Tok.is(tok::r_paren) && NumParens-- == 0) break; - PragmaToks.push_back(Tok); Lex(Tok); } @@ -211,45 +227,23 @@ void Preprocessor::HandleMicrosoft__pragma(Token &Tok) { return; } - // Build the pragma string. - std::string StrVal = " "; - for (llvm::SmallVector<Token, 32>::iterator I = - PragmaToks.begin(), E = PragmaToks.end(); I != E; ++I) { - StrVal += getSpelling(*I); - } - - SourceLocation RParenLoc = Tok.getLocation(); - - Handle_Pragma(PIK___pragma, StrVal, PragmaLoc, RParenLoc); + PragmaToks.front().setFlag(Token::LeadingSpace); - // Finally, return whatever came after the pragma directive. - return Lex(Tok); -} + // Replace the ')' with an EOM to mark the end of the pragma. + PragmaToks.back().setKind(tok::eom); -void Preprocessor::Handle_Pragma(unsigned Introducer, - const std::string &StrVal, - SourceLocation PragmaLoc, - SourceLocation RParenLoc) { + Token *TokArray = new Token[PragmaToks.size()]; + std::copy(PragmaToks.begin(), PragmaToks.end(), TokArray); - // Plop the string (including the newline and trailing null) into a buffer - // where we can lex it. - Token TmpTok; - TmpTok.startToken(); - CreateString(&StrVal[0], StrVal.size(), TmpTok); - SourceLocation TokLoc = TmpTok.getLocation(); - - // Make and enter a lexer object so that we lex and expand the tokens just - // like any others. - Lexer *TL = Lexer::Create_PragmaLexer(TokLoc, PragmaLoc, RParenLoc, - StrVal.size(), *this); - - EnterSourceFileWithLexer(TL, 0); + // Push the tokens onto the stack. + EnterTokenStream(TokArray, PragmaToks.size(), true, true); // With everything set up, lex this as a #pragma directive. - HandlePragmaDirective(Introducer); -} - + HandlePragmaDirective(PIK___pragma); + // Finally, return whatever came after the pragma directive. + return Lex(Tok); +} /// HandlePragmaOnce - Handle #pragma once. OnceTok is the 'once'. /// diff --git a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp index ea39b47..caa44bf 100644 --- a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp +++ b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp @@ -543,6 +543,11 @@ unsigned TokenLexer::isNextTokenLParen() const { return Tokens[CurToken].is(tok::l_paren); } +/// isParsingPreprocessorDirective - Return true if we are in the middle of a +/// preprocessor directive. +bool TokenLexer::isParsingPreprocessorDirective() const { + return Tokens[NumTokens-1].is(tok::eom) && !isAtEnd(); +} /// HandleMicrosoftCommentPaste - In microsoft compatibility mode, /##/ pastes /// together to form a comment that comments out everything in the current diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp index 5a7fc7e..077edd7 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp @@ -667,6 +667,8 @@ Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D, Actions.ActOnUninitializedDecl(ThisDecl, TypeContainsAuto); } + Actions.FinalizeDeclaration(ThisDecl); + return ThisDecl; } @@ -954,8 +956,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, goto DoneWithDeclSpec; CXXScopeSpec SS; - SS.setScopeRep((NestedNameSpecifier*) Tok.getAnnotationValue()); - SS.setRange(Tok.getAnnotationRange()); + Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(), + Tok.getAnnotationRange(), + SS); // We are looking for a qualified typename. Token Next = NextToken(); @@ -1244,9 +1247,18 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, DiagID, getLang()); break; case tok::kw_auto: - if (getLang().CPlusPlus0x) - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec, - DiagID); + if (getLang().CPlusPlus0x || getLang().ObjC2) { + if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { + isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec, + DiagID, getLang()); + if (!isInvalid) + Diag(Tok, diag::auto_storage_class) + << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc()); + } + else + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec, + DiagID); + } else isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec, DiagID, getLang()); @@ -1459,6 +1471,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, else Diag(Tok, DiagID) << PrevSpec; } + DS.SetRangeEnd(Tok.getLocation()); ConsumeToken(); } @@ -1973,6 +1986,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, } } + bool AllowFixedUnderlyingType = getLang().CPlusPlus0x || getLang().Microsoft; bool IsScopedEnum = false; bool IsScopedUsingClassTag = false; @@ -1984,7 +1998,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, } // Must have either 'enum name' or 'enum {...}'. - if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace)) { + if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace) && + (AllowFixedUnderlyingType && Tok.isNot(tok::colon))) { Diag(Tok, diag::err_expected_ident_lbrace); // Skip the rest of this declarator, up until the comma or semicolon. @@ -2011,7 +2026,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, TypeResult BaseType; // Parse the fixed underlying type. - if (getLang().CPlusPlus0x && Tok.is(tok::colon)) { + if (AllowFixedUnderlyingType && Tok.is(tok::colon)) { bool PossibleBitfield = false; if (getCurScope()->getFlags() & Scope::ClassScope) { // If we're in class scope, this can either be an enum declaration with @@ -2043,7 +2058,9 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // Consume the ':'. ConsumeToken(); - if (isCXXDeclarationSpecifier() != TPResult::True()) { + if ((getLang().CPlusPlus && + isCXXDeclarationSpecifier() != TPResult::True()) || + (!getLang().CPlusPlus && !isDeclarationSpecifier(true))) { // We'll parse this as a bitfield later. PossibleBitfield = true; TPA.Revert(); @@ -2060,6 +2077,10 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, if (!PossibleBitfield) { SourceRange Range; BaseType = ParseTypeName(&Range); + + if (!getLang().CPlusPlus0x) + Diag(StartLoc, diag::ext_ms_enum_fixed_underlying_type) + << Range; } } @@ -2090,6 +2111,14 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, return; } + if (!Name && TUK != Sema::TUK_Definition) { + Diag(Tok, diag::err_enumerator_unnamed_no_def); + + // Skip the rest of this declarator, up until the comma or semicolon. + SkipUntil(tok::comma, true); + return; + } + bool Owned = false; bool IsDependent = false; SourceLocation TSTLoc = NameLoc.isValid()? NameLoc : StartLoc; @@ -2734,6 +2763,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D, if (Kind == tok::star) // Remember that we parsed a pointer type, and remember the type-quals. D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc, + DS.getConstSpecLoc(), + DS.getVolatileSpecLoc(), + DS.getRestrictSpecLoc(), DS.takeAttributes()), SourceLocation()); else @@ -3730,4 +3762,3 @@ bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc, } return false; } - diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp index e73578f..d8db711 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp @@ -65,8 +65,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, "Call sites of this function should be guarded by checking for C++"); if (Tok.is(tok::annot_cxxscope)) { - SS.setScopeRep(static_cast<NestedNameSpecifier*>(Tok.getAnnotationValue())); - SS.setRange(Tok.getAnnotationRange()); + Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(), + Tok.getAnnotationRange(), + SS); ConsumeToken(); return false; } @@ -80,10 +81,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, return false; // '::' - Global scope qualifier. - SourceLocation CCLoc = ConsumeToken(); - SS.setBeginLoc(CCLoc); - SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(getCurScope(), CCLoc)); - SS.setEndLoc(CCLoc); + if (Actions.ActOnCXXGlobalScopeSpecifier(getCurScope(), ConsumeToken(), SS)) + return true; + HasScopeSpecifier = true; } @@ -208,20 +208,20 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!"); SourceLocation CCLoc = ConsumeToken(); - if (!HasScopeSpecifier) { - SS.setBeginLoc(TypeToken.getLocation()); + if (!HasScopeSpecifier) HasScopeSpecifier = true; - } if (ParsedType T = getTypeAnnotation(TypeToken)) { - CXXScopeTy *Scope = - Actions.ActOnCXXNestedNameSpecifier(getCurScope(), SS, T, - TypeToken.getAnnotationRange(), - CCLoc); - SS.setScopeRep(Scope); - } else - SS.setScopeRep(0); - SS.setEndLoc(CCLoc); + if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), T, CCLoc, SS)) + SS.SetInvalid(SourceRange(SS.getBeginLoc(), CCLoc)); + + continue; + } else { + SourceLocation Start = SS.getBeginLoc().isValid()? SS.getBeginLoc() + : CCLoc; + SS.SetInvalid(SourceRange(Start, CCLoc)); + } + continue; } @@ -245,7 +245,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // If we get foo:bar, this is almost certainly a typo for foo::bar. Recover // and emit a fixit hint for it. if (Next.is(tok::colon) && !ColonIsSacred) { - if (Actions.IsInvalidUnlessNestedName(getCurScope(), SS, II, ObjectType, + if (Actions.IsInvalidUnlessNestedName(getCurScope(), SS, II, + Tok.getLocation(), + Next.getLocation(), ObjectType, EnteringContext) && // If the token after the colon isn't an identifier, it's still an // error, but they probably meant something else strange so don't @@ -274,16 +276,11 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, "NextToken() not working properly!"); SourceLocation CCLoc = ConsumeToken(); - if (!HasScopeSpecifier) { - SS.setBeginLoc(IdLoc); - HasScopeSpecifier = true; - } - - if (!SS.isInvalid()) - SS.setScopeRep( - Actions.ActOnCXXNestedNameSpecifier(getCurScope(), SS, IdLoc, CCLoc, II, - ObjectType, EnteringContext)); - SS.setEndLoc(CCLoc); + HasScopeSpecifier = true; + if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), II, IdLoc, CCLoc, + ObjectType, EnteringContext, SS)) + SS.SetInvalid(SourceRange(IdLoc, CCLoc)); + continue; } @@ -836,6 +833,8 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, // FIXME: Build a reference to this declaration? Convert it to bool? // (This is currently handled by Sema). + + Actions.FinalizeDeclaration(DeclOut); return false; } diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp index 8387c88..59ced8b 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp @@ -829,7 +829,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, TemplateId->RAngleLoc = RAngleLoc; ParsedTemplateArgument *Args = TemplateId->getTemplateArgs(); for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg) - Args[Arg] = TemplateArgs[Arg]; + Args[Arg] = ParsedTemplateArgument(TemplateArgs[Arg]); Tok.setAnnotationValue(TemplateId); if (TemplateKWLoc.isValid()) Tok.setLocation(TemplateKWLoc); diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp index a50763a..07e592c 100644 --- a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp @@ -296,6 +296,10 @@ bool Parser::SkipUntil(const tok::TokenKind *Toks, unsigned NumToks, case tok::wide_string_literal: ConsumeStringToken(); break; + + case tok::at: + return false; + case tok::semi: if (StopAtSemi) return false; @@ -1159,7 +1163,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) { else PP.EnterToken(Tok); Tok.setKind(tok::annot_cxxscope); - Tok.setAnnotationValue(SS.getScopeRep()); + Tok.setAnnotationValue(Actions.SaveNestedNameSpecifierAnnotation(SS)); Tok.setAnnotationRange(SS.getRange()); // In case the tokens were cached, have Preprocessor replace them @@ -1196,7 +1200,7 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) { else PP.EnterToken(Tok); Tok.setKind(tok::annot_cxxscope); - Tok.setAnnotationValue(SS.getScopeRep()); + Tok.setAnnotationValue(Actions.SaveNestedNameSpecifierAnnotation(SS)); Tok.setAnnotationRange(SS.getRange()); // In case the tokens were cached, have Preprocessor replace them with the diff --git a/contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp b/contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp index 875a0c7..0263f65 100644 --- a/contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Rewrite/RewriteObjC.cpp @@ -298,6 +298,7 @@ namespace { Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S); Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, SourceLocation OrigEnd); + bool IsDeclStmtInForeachHeader(DeclStmt *DS); CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD, Expr **args, unsigned nargs, SourceLocation StartLoc=SourceLocation(), @@ -1348,13 +1349,13 @@ Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(Expr *PropOrGetterRefExpr) { MsgExpr = ObjCMessageExpr::Create(*Context, Ty.getNonReferenceType(), Expr::getValueKindForType(Ty), - /*FIXME?*/SourceLocation(), + PropOrGetterRefExpr->getLocStart(), SuperLocation, /*IsInstanceSuper=*/true, SuperTy, Sel, SelectorLoc, OMD, 0, 0, - /*FIXME:*/SourceLocation()); + PropOrGetterRefExpr->getLocEnd()); else { assert (Receiver && "RewritePropertyOrImplicitGetter - Receiver is null"); if (Expr *Exp = dyn_cast<Expr>(Receiver)) @@ -1364,14 +1365,15 @@ Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(Expr *PropOrGetterRefExpr) { MsgExpr = ObjCMessageExpr::Create(*Context, Ty.getNonReferenceType(), Expr::getValueKindForType(Ty), - /*FIXME:*/SourceLocation(), + PropOrGetterRefExpr->getLocStart(), cast<Expr>(Receiver), Sel, SelectorLoc, OMD, 0, 0, - /*FIXME:*/SourceLocation()); + PropOrGetterRefExpr->getLocEnd()); } - Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr); + Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr, MsgExpr->getLocStart(), + MsgExpr->getLocEnd()); if (!PropParentMap) PropParentMap = new ParentMap(CurrentBody); @@ -2986,9 +2988,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, // Make all implicit casts explicit...ICE comes in handy:-) if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) { // Reuse the ICE type, it is exactly what the doctor ordered. - QualType type = ICE->getType()->isObjCQualifiedIdType() - ? Context->getObjCIdType() - : ICE->getType(); + QualType type = ICE->getType(); + if (needToScanForQualifiers(type)) + type = Context->getObjCIdType(); // Make sure we convert "type (^)(...)" to "type (*)(...)". (void)convertBlockPointerToFunctionPointer(type); userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK_BitCast, @@ -5459,6 +5461,13 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, return NewRep; } +bool RewriteObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) { + if (const ObjCForCollectionStmt * CS = + dyn_cast<ObjCForCollectionStmt>(Stmts.back())) + return CS->getElement() == DS; + return false; +} + //===----------------------------------------------------------------------===// // Function Body / Expression rewriting //===----------------------------------------------------------------------===// @@ -5681,7 +5690,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { // for (id <FooProtocol> index in someArray) ; // This is because RewriteObjCForCollectionStmt() does textual rewriting // and it depends on the original text locations/positions. - if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back())) + if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS)) RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin()); // Blocks rewrite rules. diff --git a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp index 63f561d..6a42224 100644 --- a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -15,6 +15,7 @@ #include "clang/Sema/AnalysisBasedWarnings.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/ScopeInfo.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Preprocessor.h" #include "clang/AST/DeclObjC.h" @@ -26,6 +27,8 @@ #include "clang/Analysis/AnalysisContext.h" #include "clang/Analysis/CFG.h" #include "clang/Analysis/Analyses/ReachableCode.h" +#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" +#include "clang/Analysis/CFGStmtMap.h" #include "clang/Analysis/Analyses/UninitializedValuesV2.h" #include "llvm/ADT/BitVector.h" #include "llvm/Support/Casting.h" @@ -289,7 +292,7 @@ struct CheckFallThroughDiagnostics { /// of a noreturn function. We assume that functions and blocks not marked /// noreturn will return. static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, - QualType BlockTy, + const BlockExpr *blkExpr, const CheckFallThroughDiagnostics& CD, AnalysisContext &AC) { @@ -306,6 +309,7 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, HasNoReturn = MD->hasAttr<NoReturnAttr>(); } else if (isa<BlockDecl>(D)) { + QualType BlockTy = blkExpr->getType(); if (const FunctionType *FT = BlockTy->getPointeeType()->getAs<FunctionType>()) { if (FT->getResultType()->isVoidType()) @@ -477,11 +481,20 @@ clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) : S(s) { Diagnostic::Ignored); } +static void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) { + for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator + i = fscope->PossiblyUnreachableDiags.begin(), + e = fscope->PossiblyUnreachableDiags.end(); + i != e; ++i) { + const sema::PossiblyUnreachableDiag &D = *i; + S.Diag(D.Loc, D.PD); + } +} + void clang::sema:: AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, - const Decl *D, QualType BlockTy) { - - assert(BlockTy.isNull() || isa<BlockDecl>(D)); + sema::FunctionScopeInfo *fscope, + const Decl *D, const BlockExpr *blkExpr) { // We avoid doing analysis-based warnings when there are errors for // two reasons: @@ -491,9 +504,6 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, // time. Diagnostic &Diags = S.getDiagnostics(); - if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) - return; - // Do not do any analysis for declarations in system headers if we are // going to just ignore them. if (Diags.getSuppressSystemWarnings() && @@ -504,6 +514,12 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, if (cast<DeclContext>(D)->isDependentContext()) return; + if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) { + // Flush out any possibly unreachable diagnostics. + flushDiagnostics(S, fscope); + return; + } + const Stmt *Body = D->getBody(); assert(Body); @@ -512,12 +528,40 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, AnalysisContext AC(D, 0, /*useUnoptimizedCFG=*/false, /*addehedges=*/false, /*addImplicitDtors=*/true, /*addInitializers=*/true); + // Emit delayed diagnostics. + if (!fscope->PossiblyUnreachableDiags.empty()) { + bool analyzed = false; + if (CFGReachabilityAnalysis *cra = AC.getCFGReachablityAnalysis()) + if (CFGStmtMap *csm = AC.getCFGStmtMap()) { + analyzed = true; + for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator + i = fscope->PossiblyUnreachableDiags.begin(), + e = fscope->PossiblyUnreachableDiags.end(); + i != e; ++i) { + const sema::PossiblyUnreachableDiag &D = *i; + if (const CFGBlock *blk = csm->getBlock(D.stmt)) { + // Can this block be reached from the entrance? + if (cra->isReachable(&AC.getCFG()->getEntry(), blk)) + S.Diag(D.Loc, D.PD); + } + else { + // Emit the warning anyway if we cannot map to a basic block. + S.Diag(D.Loc, D.PD); + } + } + } + + if (!analyzed) + flushDiagnostics(S, fscope); + } + + // Warning: check missing 'return' if (P.enableCheckFallThrough) { const CheckFallThroughDiagnostics &CD = (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock() : CheckFallThroughDiagnostics::MakeForFunction(D)); - CheckFallThroughForBody(S, D, Body, BlockTy, CD, AC); + CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC); } // Warning: check for unreachable code @@ -550,21 +594,3 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, } } } - -void clang::sema:: -AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, - const BlockExpr *E) { - return IssueWarnings(P, E->getBlockDecl(), E->getType()); -} - -void clang::sema:: -AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, - const ObjCMethodDecl *D) { - return IssueWarnings(P, D, QualType()); -} - -void clang::sema:: -AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, - const FunctionDecl *D) { - return IssueWarnings(P, D, QualType()); -} diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp index bc289ec..037594a 100644 --- a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp @@ -14,6 +14,9 @@ #include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency! #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/TypeLoc.h" #include "clang/Lex/Preprocessor.h" #include "clang/Basic/LangOptions.h" #include "llvm/ADT/STLExtras.h" @@ -44,6 +47,239 @@ void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) { EndLocation = TemplateId->RAngleLoc; } +CXXScopeSpec::CXXScopeSpec(const CXXScopeSpec &Other) + : Range(Other.Range), ScopeRep(Other.ScopeRep), Buffer(0), + BufferSize(Other.BufferSize), BufferCapacity(Other.BufferSize) +{ + if (BufferSize) { + Buffer = static_cast<char *>(malloc(BufferSize)); + memcpy(Buffer, Other.Buffer, BufferSize); + } +} + +CXXScopeSpec &CXXScopeSpec::operator=(const CXXScopeSpec &Other) { + Range = Other.Range; + ScopeRep = Other.ScopeRep; + if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) { + // Re-use our storage. + BufferSize = Other.BufferSize; + memcpy(Buffer, Other.Buffer, BufferSize); + return *this; + } + + if (BufferCapacity) + free(Buffer); + if (Other.Buffer) { + BufferSize = Other.BufferSize; + BufferCapacity = BufferSize; + Buffer = static_cast<char *>(malloc(BufferSize)); + memcpy(Buffer, Other.Buffer, BufferSize); + } else { + Buffer = 0; + BufferSize = 0; + BufferCapacity = 0; + } + return *this; +} + +CXXScopeSpec::~CXXScopeSpec() { + if (BufferCapacity) + free(Buffer); +} + +namespace { + void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, + unsigned &BufferCapacity) { + if (BufferSize + (End - Start) > BufferCapacity) { + // Reallocate the buffer. + unsigned NewCapacity + = std::max((unsigned)(BufferCapacity? BufferCapacity * 2 + : sizeof(void*) * 2), + (unsigned)(BufferSize + (End - Start))); + char *NewBuffer = static_cast<char *>(malloc(NewCapacity)); + memcpy(NewBuffer, Buffer, BufferSize); + + if (BufferCapacity) + free(Buffer); + Buffer = NewBuffer; + BufferCapacity = NewCapacity; + } + + memcpy(Buffer + BufferSize, Start, End - Start); + BufferSize += End-Start; + } + + /// \brief Save a source location to the given buffer. + void SaveSourceLocation(SourceLocation Loc, char *&Buffer, + unsigned &BufferSize, unsigned &BufferCapacity) { + unsigned Raw = Loc.getRawEncoding(); + Append(reinterpret_cast<char *>(&Raw), + reinterpret_cast<char *>(&Raw) + sizeof(unsigned), + Buffer, BufferSize, BufferCapacity); + } + + /// \brief Save a pointer to the given buffer. + void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize, + unsigned &BufferCapacity) { + Append(reinterpret_cast<char *>(&Ptr), + reinterpret_cast<char *>(&Ptr) + sizeof(void *), + Buffer, BufferSize, BufferCapacity); + } +} +void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc, + TypeLoc TL, SourceLocation ColonColonLoc) { + ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, + TemplateKWLoc.isValid(), + TL.getTypePtr()); + if (Range.getBegin().isInvalid()) + Range.setBegin(TL.getBeginLoc()); + Range.setEnd(ColonColonLoc); + + // Push source-location info into the buffer. + SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity); + SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); + + assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + +void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier, + SourceLocation IdentifierLoc, + SourceLocation ColonColonLoc) { + ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Identifier); + if (Range.getBegin().isInvalid()) + Range.setBegin(IdentifierLoc); + Range.setEnd(ColonColonLoc); + + // Push source-location info into the buffer. + SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity); + SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); + + assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + +void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace, + SourceLocation NamespaceLoc, + SourceLocation ColonColonLoc) { + ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Namespace); + if (Range.getBegin().isInvalid()) + Range.setBegin(NamespaceLoc); + Range.setEnd(ColonColonLoc); + + // Push source-location info into the buffer. + SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity); + SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); + + assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + +void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias, + SourceLocation AliasLoc, + SourceLocation ColonColonLoc) { + ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Alias); + if (Range.getBegin().isInvalid()) + Range.setBegin(AliasLoc); + Range.setEnd(ColonColonLoc); + + // Push source-location info into the buffer. + SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity); + SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); + + assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + +void CXXScopeSpec::MakeGlobal(ASTContext &Context, + SourceLocation ColonColonLoc) { + assert(!ScopeRep && "Already have a nested-name-specifier!?"); + ScopeRep = NestedNameSpecifier::GlobalSpecifier(Context); + Range = SourceRange(ColonColonLoc); + + // Push source-location info into the buffer. + SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); + + assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + +void CXXScopeSpec::MakeTrivial(ASTContext &Context, + NestedNameSpecifier *Qualifier, SourceRange R) { + ScopeRep = Qualifier; + Range = R; + + // Construct bogus (but well-formed) source information for the + // nested-name-specifier. + BufferSize = 0; + llvm::SmallVector<NestedNameSpecifier *, 4> Stack; + for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix()) + Stack.push_back(NNS); + while (!Stack.empty()) { + NestedNameSpecifier *NNS = Stack.back(); + Stack.pop_back(); + switch (NNS->getKind()) { + case NestedNameSpecifier::Identifier: + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: + SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity); + break; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: { + TypeSourceInfo *TSInfo + = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0), + R.getBegin()); + SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize, + BufferCapacity); + break; + } + + case NestedNameSpecifier::Global: + break; + } + + // Save the location of the '::'. + SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(), + Buffer, BufferSize, BufferCapacity); + } +} + +void CXXScopeSpec::Adopt(NestedNameSpecifierLoc Other) { + if (!Other) { + Range = SourceRange(); + ScopeRep = 0; + return; + } + + if (BufferCapacity) + free(Buffer); + + // Rather than copying the data (which is wasteful), "adopt" the + // pointer (which points into the ASTContext) but set the capacity to zero to + // indicate that we don't own it. + Range = Other.getSourceRange(); + ScopeRep = Other.getNestedNameSpecifier(); + Buffer = static_cast<char *>(Other.getOpaqueData()); + BufferSize = Other.getDataLength(); + BufferCapacity = 0; +} + +NestedNameSpecifierLoc +CXXScopeSpec::getWithLocInContext(ASTContext &Context) const { + if (isEmpty() || isInvalid()) + return NestedNameSpecifierLoc(); + + // If we adopted our data pointer from elsewhere in the AST context, there's + // no need to copy the memory. + if (BufferCapacity == 0) + return NestedNameSpecifierLoc(ScopeRep, Buffer); + + void *Mem = Context.Allocate(BufferSize, llvm::alignOf<void *>()); + memcpy(Mem, Buffer, BufferSize); + return NestedNameSpecifierLoc(ScopeRep, Mem); +} + /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. /// "TheDeclarator" is the declarator that this will be added to. DeclaratorChunk DeclaratorChunk::getFunction(const ParsedAttributes &attrs, diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp index 23a3c24..0c39e13 100644 --- a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp @@ -48,6 +48,7 @@ void FunctionScopeInfo::Clear() { SwitchStack.clear(); Returns.clear(); ErrorTrap.reset(); + PossiblyUnreachableDiags.clear(); } BlockScopeInfo::~BlockScopeInfo() { } @@ -466,6 +467,12 @@ void Sema::ActOnEndOfTranslationUnit() { checkUndefinedInternals(*this); } + // Check we've noticed that we're no longer parsing the initializer for every + // variable. If we miss cases, then at best we have a performance issue and + // at worst a rejects-valid bug. + assert(ParsingInitForAutoVars.empty() && + "Didn't unmark var as having its initializer parsed"); + TUScope = 0; } @@ -625,11 +632,27 @@ void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) { BlockScope, Block)); } -void Sema::PopFunctionOrBlockScope() { - FunctionScopeInfo *Scope = FunctionScopes.pop_back_val(); +void Sema::PopFunctionOrBlockScope(const AnalysisBasedWarnings::Policy *WP, + const Decl *D, const BlockExpr *blkExpr) { + FunctionScopeInfo *Scope = FunctionScopes.pop_back_val(); assert(!FunctionScopes.empty() && "mismatched push/pop!"); - if (FunctionScopes.back() != Scope) + + // Issue any analysis-based warnings. + if (WP && D) + AnalysisWarnings.IssueWarnings(*WP, Scope, D, blkExpr); + else { + for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator + i = Scope->PossiblyUnreachableDiags.begin(), + e = Scope->PossiblyUnreachableDiags.end(); + i != e; ++i) { + const sema::PossiblyUnreachableDiag &D = *i; + Diag(D.Loc, D.PD); + } + } + + if (FunctionScopes.back() != Scope) { delete Scope; + } } /// \brief Determine whether any errors occurred within this function/method/ diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp index aa0efcd..7ad4b45 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -19,6 +19,7 @@ #include "clang/AST/NestedNameSpecifier.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Sema/DeclSpec.h" +#include "TypeLocBuilder.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -138,6 +139,9 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, case NestedNameSpecifier::Namespace: return NNS->getAsNamespace(); + case NestedNameSpecifier::NamespaceAlias: + return NNS->getAsNamespaceAlias()->getNamespace(); + case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: { const TagType *Tag = NNS->getAsType()->getAs<TagType>(); @@ -219,7 +223,7 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, Context.getTypeDeclType(Tag), PDiag(diag::err_incomplete_nested_name_spec) << SS.getRange())) { - SS.setScopeRep(0); // Mark the ScopeSpec invalid. + SS.SetInvalid(SS.getRange()); return true; } } @@ -227,11 +231,10 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, return false; } -/// ActOnCXXGlobalScopeSpecifier - Return the object that represents the -/// global scope ('::'). -Sema::CXXScopeTy *Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, - SourceLocation CCLoc) { - return NestedNameSpecifier::GlobalSpecifier(Context); +bool Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc, + CXXScopeSpec &SS) { + SS.MakeGlobal(Context, CCLoc); + return false; } /// \brief Determines whether the given declaration is an valid acceptable @@ -352,22 +355,21 @@ bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS, /// /// If ErrorRecoveryLookup is true, then this call is used to improve error /// recovery. This means that it should not emit diagnostics, it should -/// just return null on failure. It also means it should only return a valid +/// just return true on failure. It also means it should only return a valid /// scope if it *knows* that the result is correct. It should not return in a -/// dependent context, for example. -Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, - CXXScopeSpec &SS, - SourceLocation IdLoc, - SourceLocation CCLoc, - IdentifierInfo &II, - QualType ObjectType, - NamedDecl *ScopeLookupResult, - bool EnteringContext, - bool ErrorRecoveryLookup) { - NestedNameSpecifier *Prefix - = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); - - LookupResult Found(*this, &II, IdLoc, LookupNestedNameSpecifierName); +/// dependent context, for example. Nor will it extend \p SS with the scope +/// specifier. +bool Sema::BuildCXXNestedNameSpecifier(Scope *S, + IdentifierInfo &Identifier, + SourceLocation IdentifierLoc, + SourceLocation CCLoc, + QualType ObjectType, + bool EnteringContext, + CXXScopeSpec &SS, + NamedDecl *ScopeLookupResult, + bool ErrorRecoveryLookup) { + LookupResult Found(*this, &Identifier, IdentifierLoc, + LookupNestedNameSpecifierName); // Determine where to perform name lookup DeclContext *LookupCtx = 0; @@ -397,7 +399,7 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, // The declaration context must be complete. if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(SS, LookupCtx)) - return 0; + return true; LookupQualifiedName(Found, LookupCtx); @@ -442,16 +444,14 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, !cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()))) { // Don't speculate if we're just trying to improve error recovery. if (ErrorRecoveryLookup) - return 0; + return true; // We were not able to compute the declaration context for a dependent // base object type or prior nested-name-specifier, so this // nested-name-specifier refers to an unknown specialization. Just build // a dependent nested-name-specifier. - if (!Prefix) - return NestedNameSpecifier::Create(Context, &II); - - return NestedNameSpecifier::Create(Context, Prefix, &II); + SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc); + return false; } // FIXME: Deal with ambiguities cleanly. @@ -480,7 +480,7 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, << ND->getDeclName(); } else { Found.clear(); - Found.setLookupName(&II); + Found.setLookupName(&Identifier); } } @@ -497,7 +497,8 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, // scope, reconstruct the result from the template instantiation itself. NamedDecl *OuterDecl; if (S) { - LookupResult FoundOuter(*this, &II, IdLoc, LookupNestedNameSpecifierName); + LookupResult FoundOuter(*this, &Identifier, IdentifierLoc, + LookupNestedNameSpecifierName); LookupName(FoundOuter, S); OuterDecl = FoundOuter.getAsSingle<NamedDecl>(); } else @@ -509,39 +510,72 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, !Context.hasSameType( Context.getTypeDeclType(cast<TypeDecl>(OuterDecl)), Context.getTypeDeclType(cast<TypeDecl>(SD))))) { - if (ErrorRecoveryLookup) - return 0; - - Diag(IdLoc, diag::err_nested_name_member_ref_lookup_ambiguous) - << &II; - Diag(SD->getLocation(), diag::note_ambig_member_ref_object_type) - << ObjectType; - Diag(OuterDecl->getLocation(), diag::note_ambig_member_ref_scope); - - // Fall through so that we'll pick the name we found in the object - // type, since that's probably what the user wanted anyway. - } + if (ErrorRecoveryLookup) + return true; + + Diag(IdentifierLoc, + diag::err_nested_name_member_ref_lookup_ambiguous) + << &Identifier; + Diag(SD->getLocation(), diag::note_ambig_member_ref_object_type) + << ObjectType; + Diag(OuterDecl->getLocation(), diag::note_ambig_member_ref_scope); + + // Fall through so that we'll pick the name we found in the object + // type, since that's probably what the user wanted anyway. + } } - if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD)) - return NestedNameSpecifier::Create(Context, Prefix, Namespace); + // If we're just performing this lookup for error-recovery purposes, + // don't extend the nested-name-specifier. Just return now. + if (ErrorRecoveryLookup) + return false; + + if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD)) { + SS.Extend(Context, Namespace, IdentifierLoc, CCLoc); + return false; + } - // FIXME: It would be nice to maintain the namespace alias name, then - // see through that alias when resolving the nested-name-specifier down to - // a declaration context. - if (NamespaceAliasDecl *Alias = dyn_cast<NamespaceAliasDecl>(SD)) - return NestedNameSpecifier::Create(Context, Prefix, - Alias->getNamespace()); + if (NamespaceAliasDecl *Alias = dyn_cast<NamespaceAliasDecl>(SD)) { + SS.Extend(Context, Alias, IdentifierLoc, CCLoc); + return false; + } QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD)); - return NestedNameSpecifier::Create(Context, Prefix, false, - T.getTypePtr()); + TypeLocBuilder TLB; + if (isa<InjectedClassNameType>(T)) { + InjectedClassNameTypeLoc InjectedTL + = TLB.push<InjectedClassNameTypeLoc>(T); + InjectedTL.setNameLoc(IdentifierLoc); + } else if (isa<RecordDecl>(SD)) { + RecordTypeLoc RecordTL = TLB.push<RecordTypeLoc>(T); + RecordTL.setNameLoc(IdentifierLoc); + } else if (isa<TypedefDecl>(SD)) { + TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(T); + TypedefTL.setNameLoc(IdentifierLoc); + } else if (isa<EnumDecl>(SD)) { + EnumTypeLoc EnumTL = TLB.push<EnumTypeLoc>(T); + EnumTL.setNameLoc(IdentifierLoc); + } else if (isa<TemplateTypeParmDecl>(SD)) { + TemplateTypeParmTypeLoc TemplateTypeTL + = TLB.push<TemplateTypeParmTypeLoc>(T); + TemplateTypeTL.setNameLoc(IdentifierLoc); + } else { + assert(isa<UnresolvedUsingTypenameDecl>(SD) && + "Unhandled TypeDecl node in nested-name-specifier"); + UnresolvedUsingTypeLoc UnresolvedTL + = TLB.push<UnresolvedUsingTypeLoc>(T); + UnresolvedTL.setNameLoc(IdentifierLoc); + } + + SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T), + CCLoc); + return false; } // Otherwise, we have an error case. If we don't want diagnostics, just // return an error now. if (ErrorRecoveryLookup) - return 0; + return true; // If we didn't find anything during our lookup, try again with // ordinary name lookup, which can help us produce better error @@ -555,36 +589,34 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, if (!Found.empty()) DiagID = diag::err_expected_class_or_namespace; else if (SS.isSet()) { - Diag(IdLoc, diag::err_no_member) << &II << LookupCtx << SS.getRange(); - return 0; + Diag(IdentifierLoc, diag::err_no_member) + << &Identifier << LookupCtx << SS.getRange(); + return true; } else DiagID = diag::err_undeclared_var_use; if (SS.isSet()) - Diag(IdLoc, DiagID) << &II << SS.getRange(); + Diag(IdentifierLoc, DiagID) << &Identifier << SS.getRange(); else - Diag(IdLoc, DiagID) << &II; + Diag(IdentifierLoc, DiagID) << &Identifier; - return 0; + return true; } -/// ActOnCXXNestedNameSpecifier - Called during parsing of a -/// nested-name-specifier. e.g. for "foo::bar::" we parsed "foo::" and now -/// we want to resolve "bar::". 'SS' is empty or the previously parsed -/// nested-name part ("foo::"), 'IdLoc' is the source location of 'bar', -/// 'CCLoc' is the location of '::' and 'II' is the identifier for 'bar'. -/// Returns a CXXScopeTy* object representing the C++ scope. -Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, - CXXScopeSpec &SS, - SourceLocation IdLoc, - SourceLocation CCLoc, - IdentifierInfo &II, - ParsedType ObjectTypePtr, - bool EnteringContext) { - return BuildCXXNestedNameSpecifier(S, SS, IdLoc, CCLoc, II, - GetTypeFromParser(ObjectTypePtr), - /*ScopeLookupResult=*/0, EnteringContext, - false); +bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, + IdentifierInfo &Identifier, + SourceLocation IdentifierLoc, + SourceLocation CCLoc, + ParsedType ObjectType, + bool EnteringContext, + CXXScopeSpec &SS) { + if (SS.isInvalid()) + return true; + + return BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, CCLoc, + GetTypeFromParser(ObjectType), + EnteringContext, SS, + /*ScopeLookupResult=*/0, false); } /// IsInvalidUnlessNestedName - This method is used for error recovery @@ -594,23 +626,71 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, /// /// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier. bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, - IdentifierInfo &II, ParsedType ObjectType, + IdentifierInfo &Identifier, + SourceLocation IdentifierLoc, + SourceLocation ColonLoc, + ParsedType ObjectType, bool EnteringContext) { - return BuildCXXNestedNameSpecifier(S, SS, SourceLocation(), SourceLocation(), - II, GetTypeFromParser(ObjectType), - /*ScopeLookupResult=*/0, EnteringContext, - true); + if (SS.isInvalid()) + return false; + + return !BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, ColonLoc, + GetTypeFromParser(ObjectType), + EnteringContext, SS, + /*ScopeLookupResult=*/0, true); } -Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, - const CXXScopeSpec &SS, - ParsedType Ty, - SourceRange TypeRange, - SourceLocation CCLoc) { - NestedNameSpecifier *Prefix = SS.getScopeRep(); - QualType T = GetTypeFromParser(Ty); - return NestedNameSpecifier::Create(Context, Prefix, /*FIXME:*/false, - T.getTypePtr()); +bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, + ParsedType Type, + SourceLocation CCLoc, + CXXScopeSpec &SS) { + if (SS.isInvalid()) + return true; + + TypeSourceInfo *TSInfo; + QualType T = GetTypeFromParser(Type, &TSInfo); + if (T.isNull()) + return true; + + assert(TSInfo && "Not TypeSourceInfo in nested-name-specifier?"); + // FIXME: location of the 'template' keyword? + SS.Extend(Context, SourceLocation(), TSInfo->getTypeLoc(), CCLoc); + return false; +} + +namespace { + /// \brief A structure that stores a nested-name-specifier annotation, + /// including both the nested-name-specifier + struct NestedNameSpecifierAnnotation { + NestedNameSpecifier *NNS; + }; +} + +void *Sema::SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS) { + if (SS.isEmpty() || SS.isInvalid()) + return 0; + + void *Mem = Context.Allocate((sizeof(NestedNameSpecifierAnnotation) + + SS.location_size()), + llvm::alignOf<NestedNameSpecifierAnnotation>()); + NestedNameSpecifierAnnotation *Annotation + = new (Mem) NestedNameSpecifierAnnotation; + Annotation->NNS = SS.getScopeRep(); + memcpy(Annotation + 1, SS.location_data(), SS.location_size()); + return Annotation; +} + +void Sema::RestoreNestedNameSpecifierAnnotation(void *AnnotationPtr, + SourceRange AnnotationRange, + CXXScopeSpec &SS) { + if (!AnnotationPtr) { + SS.SetInvalid(AnnotationRange); + return; + } + + NestedNameSpecifierAnnotation *Annotation + = static_cast<NestedNameSpecifierAnnotation *>(AnnotationPtr); + SS.Adopt(NestedNameSpecifierLoc(Annotation->NNS, Annotation + 1)); } bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { @@ -636,6 +716,7 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { switch (Qualifier->getKind()) { case NestedNameSpecifier::Global: case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: // These are always namespace scopes. We never want to enter a // namespace scope from anything but a file context. return CurContext->getRedeclContext()->isFileContext(); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp index 24cdaef..3ffa748 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp @@ -66,6 +66,26 @@ bool Sema::CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall) { return false; } +/// Checks that a call expression's argument count is the desired number. +/// This is useful when doing custom type-checking. Returns true on error. +static bool checkArgCount(Sema &S, CallExpr *call, unsigned desiredArgCount) { + unsigned argCount = call->getNumArgs(); + if (argCount == desiredArgCount) return false; + + if (argCount < desiredArgCount) + return S.Diag(call->getLocEnd(), diag::err_typecheck_call_too_few_args) + << 0 /*function call*/ << desiredArgCount << argCount + << call->getSourceRange(); + + // Highlight all the excess arguments. + SourceRange range(call->getArg(desiredArgCount)->getLocStart(), + call->getArg(argCount - 1)->getLocEnd()); + + return S.Diag(range.getBegin(), diag::err_typecheck_call_too_many_args) + << 0 /*function call*/ << desiredArgCount << argCount + << call->getArg(1)->getSourceRange(); +} + ExprResult Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { ExprResult TheCallResult(Owned(TheCall)); @@ -137,15 +157,14 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { if (SemaBuiltinLongjmp(TheCall)) return ExprError(); break; + + case Builtin::BI__builtin_classify_type: + if (checkArgCount(*this, TheCall, 1)) return true; + TheCall->setType(Context.IntTy); + break; case Builtin::BI__builtin_constant_p: - if (TheCall->getNumArgs() == 0) - return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) - << 0 /*function call*/ << 1 << 0 << TheCall->getSourceRange(); - if (TheCall->getNumArgs() > 1) - return Diag(TheCall->getArg(1)->getLocStart(), - diag::err_typecheck_call_too_many_args) - << 0 /*function call*/ << 1 << TheCall->getNumArgs() - << TheCall->getArg(1)->getSourceRange(); + if (checkArgCount(*this, TheCall, 1)) return true; + TheCall->setType(Context.IntTy); break; case Builtin::BI__sync_fetch_and_add: case Builtin::BI__sync_fetch_and_sub: @@ -875,7 +894,7 @@ bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) { return false; } -// Handle i > 1 ? "x" : "y", recursivelly +// Handle i > 1 ? "x" : "y", recursively. bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg, @@ -918,6 +937,12 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, } return false; + case Stmt::PredefinedExprClass: + // While __func__, etc., are technically not string literals, they + // cannot contain format specifiers and thus are not a security + // liability. + return true; + case Stmt::DeclRefExprClass: { const DeclRefExpr *DR = cast<DeclRefExpr>(E); @@ -2896,6 +2921,17 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, return DiagnoseImpCast(S, E, T, CC, DiagID); } + // Diagnose conversions between different enumeration types. + if (const EnumType *SourceEnum = Source->getAs<EnumType>()) + if (const EnumType *TargetEnum = Target->getAs<EnumType>()) + if ((SourceEnum->getDecl()->getIdentifier() || + SourceEnum->getDecl()->getTypedefForAnonDecl()) && + (TargetEnum->getDecl()->getIdentifier() || + TargetEnum->getDecl()->getTypedefForAnonDecl()) && + SourceEnum != TargetEnum) + return DiagnoseImpCast(S, E, T, CC, + diag::warn_impcast_different_enum_types); + return; } @@ -3147,7 +3183,7 @@ void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) { if (!IndexExpr->isIntegerConstantExpr(index, Context)) return; - if (!index.isNegative()) { + if (index.isUnsigned() || !index.isNegative()) { llvm::APInt size = ArrayTy->getSize(); if (!size.isStrictlyPositive()) return; @@ -3159,12 +3195,15 @@ void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) { if (index.slt(size)) return; - Diag(E->getBase()->getLocStart(), diag::warn_array_index_exceeds_bounds) - << index.toString(10, true) << size.toString(10, true) - << IndexExpr->getSourceRange(); + DiagRuntimeBehavior(E->getBase()->getLocStart(), BaseExpr, + PDiag(diag::warn_array_index_exceeds_bounds) + << index.toString(10, true) << size.toString(10, true) + << IndexExpr->getSourceRange()); } else { - Diag(E->getBase()->getLocStart(), diag::warn_array_index_precedes_bounds) - << index.toString(10, true) << IndexExpr->getSourceRange(); + DiagRuntimeBehavior(E->getBase()->getLocStart(), BaseExpr, + PDiag(diag::warn_array_index_precedes_bounds) + << index.toString(10, true) + << IndexExpr->getSourceRange()); } const NamedDecl *ND = NULL; @@ -3173,7 +3212,8 @@ void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *E) { if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr)) ND = dyn_cast<NamedDecl>(ME->getMemberDecl()); if (ND) - Diag(ND->getLocStart(), diag::note_array_index_out_of_bounds) - << ND->getDeclName(); + DiagRuntimeBehavior(ND->getLocStart(), BaseExpr, + PDiag(diag::note_array_index_out_of_bounds) + << ND->getDeclName()); } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp index dd30c12..d6efd7a 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp @@ -2895,8 +2895,7 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC, static void SetNestedNameSpecifier(DeclaratorDecl *DD, Declarator &D) { CXXScopeSpec &SS = D.getCXXScopeSpec(); if (!SS.isSet()) return; - DD->setQualifierInfo(static_cast<NestedNameSpecifier*>(SS.getScopeRep()), - SS.getRange()); + DD->setQualifierInfo(SS.getWithLocInContext(DD->getASTContext())); } NamedDecl* @@ -3026,11 +3025,11 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(), II, R, TInfo, SC, SCAsWritten); - // If this decl has an auto type in need of deduction, mark the VarDecl so - // we can diagnose uses of it in its own initializer. - if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto) { - NewVD->setParsingAutoInit(R->getContainedAutoType()); - } + // If this decl has an auto type in need of deduction, make a note of the + // Decl so we can diagnose uses of it in its own initializer. + if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto && + R->getContainedAutoType()) + ParsingInitForAutoVars.insert(NewVD); if (D.isInvalidType() || Invalid) NewVD->setInvalidDecl(); @@ -4534,8 +4533,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) { - VDecl->setParsingAutoInit(false); - QualType DeducedType; if (!DeduceAutoType(VDecl->getType(), Init, DeducedType)) { Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure) @@ -4800,9 +4797,8 @@ void Sema::ActOnInitializerError(Decl *D) { if (!VD) return; // Auto types are meaningless if we can't make sense of the initializer. - if (VD->isParsingAutoInit()) { - VD->setParsingAutoInit(false); - VD->setInvalidDecl(); + if (ParsingInitForAutoVars.count(D)) { + D->setInvalidDecl(); return; } @@ -4840,8 +4836,6 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, // C++0x [dcl.spec.auto]p3 if (TypeMayContainAuto && Type->getContainedAutoType()) { - Var->setParsingAutoInit(false); - Diag(Var->getLocation(), diag::err_auto_var_requires_init) << Var->getDeclName() << Type; Var->setInvalidDecl(); @@ -5044,6 +5038,14 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { FinalizeVarWithDestructor(var, recordType); } +/// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform +/// any semantic actions necessary after any initializer has been attached. +void +Sema::FinalizeDeclaration(Decl *ThisDecl) { + // Note that we are no longer parsing the initializer for this declaration. + ParsingInitForAutoVars.erase(ThisDecl); +} + Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, Decl **Group, unsigned NumDecls) { @@ -5052,6 +5054,19 @@ Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, if (DS.isTypeSpecOwned()) Decls.push_back(DS.getRepAsDecl()); + for (unsigned i = 0; i != NumDecls; ++i) + if (Decl *D = Group[i]) + Decls.push_back(D); + + return BuildDeclaratorGroup(Decls.data(), Decls.size(), + DS.getTypeSpecType() == DeclSpec::TST_auto); +} + +/// BuildDeclaratorGroup - convert a list of declarations into a declaration +/// group, performing any necessary semantic checking. +Sema::DeclGroupPtrTy +Sema::BuildDeclaratorGroup(Decl **Group, unsigned NumDecls, + bool TypeMayContainAuto) { // C++0x [dcl.spec.auto]p7: // If the type deduced for the template parameter U is not the same in each // deduction, the program is ill-formed. @@ -5059,14 +5074,16 @@ Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, // between the deduced type U and the deduced type which 'auto' stands for. // auto a = 0, b = { 1, 2, 3 }; // is legal because the deduced type U is 'int' in both cases. - bool TypeContainsAuto = DS.getTypeSpecType() == DeclSpec::TST_auto; - if (TypeContainsAuto && NumDecls > 1) { + if (TypeMayContainAuto && NumDecls > 1) { QualType Deduced; CanQualType DeducedCanon; VarDecl *DeducedDecl = 0; for (unsigned i = 0; i != NumDecls; ++i) { if (VarDecl *D = dyn_cast<VarDecl>(Group[i])) { AutoType *AT = D->getType()->getContainedAutoType(); + // Don't reissue diagnostics when instantiating a template. + if (AT && D->isInvalidDecl()) + break; if (AT && AT->isDeduced()) { QualType U = AT->getDeducedType(); CanQualType UCanon = Context.getCanonicalType(U); @@ -5075,11 +5092,13 @@ Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, DeducedCanon = UCanon; DeducedDecl = D; } else if (DeducedCanon != UCanon) { - Diag(DS.getTypeSpecTypeLoc(), diag::err_auto_different_deductions) + Diag(D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(), + diag::err_auto_different_deductions) << Deduced << DeducedDecl->getDeclName() << U << D->getDeclName() << DeducedDecl->getInit()->getSourceRange() << D->getInit()->getSourceRange(); + D->setInvalidDecl(); break; } } @@ -5087,12 +5106,7 @@ Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, } } - for (unsigned i = 0; i != NumDecls; ++i) - if (Decl *D = Group[i]) - Decls.push_back(D); - - return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, - Decls.data(), Decls.size())); + return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, Group, NumDecls)); } @@ -5537,6 +5551,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, FD = dyn_cast_or_null<FunctionDecl>(dcl); sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy(); + sema::AnalysisBasedWarnings::Policy *ActivePolicy = 0; if (FD) { FD->setBody(Body); @@ -5605,13 +5620,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, else if (!isa<FunctionTemplateDecl>(dcl)) { // Since the body is valid, issue any analysis-based warnings that are // enabled. - QualType ResultType; - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(dcl)) { - AnalysisWarnings.IssueWarnings(WP, FD); - } else { - ObjCMethodDecl *MD = cast<ObjCMethodDecl>(dcl); - AnalysisWarnings.IssueWarnings(WP, MD); - } + ActivePolicy = &WP; } assert(ExprTemporaries.empty() && "Leftover temporaries in function"); @@ -5620,7 +5629,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (!IsInstantiation) PopDeclContext(); - PopFunctionOrBlockScope(); + PopFunctionOrBlockScope(ActivePolicy, dcl); // If any errors have occurred, clear out any temporaries that may have // been leftover. This ensures that these temporaries won't be picked up for @@ -6435,9 +6444,7 @@ CreateNewDecl: // Maybe add qualifier info. if (SS.isNotEmpty()) { if (SS.isSet()) { - NestedNameSpecifier *NNS - = static_cast<NestedNameSpecifier*>(SS.getScopeRep()); - New->setQualifierInfo(NNS, SS.getRange()); + New->setQualifierInfo(SS.getWithLocInContext(Context)); if (NumMatchedTemplateParamLists > 0) { New->setTemplateParameterListsInfo(Context, NumMatchedTemplateParamLists, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp index cbc940f..893cf6a 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp @@ -1014,54 +1014,48 @@ static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { } static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) { - // check the attribute arguments. - int noArgs = Attr.getNumArgs(); - if (noArgs > 1) { + unsigned NumArgs = Attr.getNumArgs(); + if (NumArgs > 1) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "0 or 1"; return; } + // Handle the case where deprecated attribute has a text message. - StringLiteral *SE; - if (noArgs == 1) { - Expr *ArgExpr = Attr.getArg(0); - SE = dyn_cast<StringLiteral>(ArgExpr); + llvm::StringRef Str; + if (NumArgs == 1) { + StringLiteral *SE = dyn_cast<StringLiteral>(Attr.getArg(0)); if (!SE) { - S.Diag(ArgExpr->getLocStart(), - diag::err_attribute_not_string) << "deprecated"; + S.Diag(Attr.getArg(0)->getLocStart(), diag::err_attribute_not_string) + << "deprecated"; return; } + Str = SE->getString(); } - else - SE = StringLiteral::CreateEmpty(S.Context, 1); - d->addAttr(::new (S.Context) DeprecatedAttr(Attr.getLoc(), S.Context, - SE->getString())); + d->addAttr(::new (S.Context) DeprecatedAttr(Attr.getLoc(), S.Context, Str)); } static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) { - // check the attribute arguments. - int noArgs = Attr.getNumArgs(); - if (noArgs > 1) { + unsigned NumArgs = Attr.getNumArgs(); + if (NumArgs > 1) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << "0 or 1"; return; } + // Handle the case where unavailable attribute has a text message. - StringLiteral *SE; - if (noArgs == 1) { - Expr *ArgExpr = Attr.getArg(0); - SE = dyn_cast<StringLiteral>(ArgExpr); + llvm::StringRef Str; + if (NumArgs == 1) { + StringLiteral *SE = dyn_cast<StringLiteral>(Attr.getArg(0)); if (!SE) { - S.Diag(ArgExpr->getLocStart(), + S.Diag(Attr.getArg(0)->getLocStart(), diag::err_attribute_not_string) << "unavailable"; return; } + Str = SE->getString(); } - else - SE = StringLiteral::CreateEmpty(S.Context, 1); - d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context, - SE->getString())); + d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context, Str)); } static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -2847,7 +2841,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) { FD->getType(), FD->getTypeSourceInfo()); if (FD->getQualifier()) { FunctionDecl *NewFD = cast<FunctionDecl>(NewD); - NewFD->setQualifierInfo(FD->getQualifier(), FD->getQualifierRange()); + NewFD->setQualifierInfo(FD->getQualifierLoc()); } } else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) { NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(), @@ -2857,7 +2851,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) { VD->getStorageClassAsWritten()); if (VD->getQualifier()) { VarDecl *NewVD = cast<VarDecl>(NewD); - NewVD->setQualifierInfo(VD->getQualifier(), VD->getQualifierRange()); + NewVD->setQualifierInfo(VD->getQualifierLoc()); } } return NewD; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp index e8abab8..f483262 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp @@ -1078,6 +1078,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, if (Deleted) // FIXME: Source location is not very good. SetDeclDeleted(Member, D.getSourceRange().getBegin()); + FinalizeDeclaration(Member); + if (isInstField) FieldCollector->Add(cast<FieldDecl>(Member)); return Member; @@ -2586,6 +2588,9 @@ struct CheckAbstractUsage { void Check(FunctionProtoTypeLoc TL, Sema::AbstractDiagSelID Sel) { Visit(TL.getResultLoc(), Sema::AbstractReturnType); for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { + if (!TL.getArg(I)) + continue; + TypeSourceInfo *TSI = TL.getArg(I)->getTypeSourceInfo(); if (TSI) Visit(TSI->getTypeLoc(), Sema::AbstractParamType); } @@ -3618,8 +3623,7 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, = UsingDirectiveDecl::Create(Context, CurContext, /* 'using' */ LBrace, /* 'namespace' */ SourceLocation(), - /* qualifier */ SourceRange(), - /* NNS */ NULL, + /* qualifier */ NestedNameSpecifierLoc(), /* identifier */ SourceLocation(), Namespc, /* Ancestor */ CurContext); @@ -3763,8 +3767,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S, CommonAncestor = CommonAncestor->getParent(); UDir = UsingDirectiveDecl::Create(Context, CurContext, UsingLoc, NamespcLoc, - SS.getRange(), - (NestedNameSpecifier *)SS.getScopeRep(), + SS.getWithLocInContext(Context), IdentLoc, Named, CommonAncestor); PushUsingDirective(S, UDir); } else { @@ -3914,16 +3917,16 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, if (OrigDC == CurContext) { Diag(Using->getLocation(), diag::err_using_decl_nested_name_specifier_is_current_class) - << Using->getNestedNameRange(); + << Using->getQualifierLoc().getSourceRange(); Diag(Orig->getLocation(), diag::note_using_decl_target); return true; } - Diag(Using->getNestedNameRange().getBegin(), + Diag(Using->getQualifierLoc().getBeginLoc(), diag::err_using_decl_nested_name_specifier_is_not_base_class) - << Using->getTargetNestedNameDecl() + << Using->getQualifier() << cast<CXXRecordDecl>(CurContext) - << Using->getNestedNameRange(); + << Using->getQualifierLoc().getSourceRange(); Diag(Orig->getLocation(), diag::note_using_decl_target); return true; } @@ -4129,8 +4132,6 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, LookupQualifiedName(Previous, CurContext); } - NestedNameSpecifier *NNS = SS.getScopeRep(); - // Check for invalid redeclarations. if (CheckUsingDeclRedeclaration(UsingLoc, IsTypeName, SS, IdentLoc, Previous)) return 0; @@ -4141,22 +4142,21 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, DeclContext *LookupContext = computeDeclContext(SS); NamedDecl *D; + NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); if (!LookupContext) { if (IsTypeName) { // FIXME: not all declaration name kinds are legal here D = UnresolvedUsingTypenameDecl::Create(Context, CurContext, UsingLoc, TypenameLoc, - SS.getRange(), NNS, + QualifierLoc, IdentLoc, NameInfo.getName()); } else { - D = UnresolvedUsingValueDecl::Create(Context, CurContext, - UsingLoc, SS.getRange(), - NNS, NameInfo); + D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc, + QualifierLoc, NameInfo); } } else { - D = UsingDecl::Create(Context, CurContext, - SS.getRange(), UsingLoc, NNS, NameInfo, - IsTypeName); + D = UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc, + NameInfo, IsTypeName); } D->setAccess(AS); CurContext->addDecl(D); @@ -4247,7 +4247,7 @@ bool Sema::CheckInheritedConstructorUsingDecl(UsingDecl *UD) { return true; } - const Type *SourceType = UD->getTargetNestedNameDecl()->getAsType(); + const Type *SourceType = UD->getQualifier()->getAsType(); assert(SourceType && "Using decl naming constructor doesn't have type in scope spec."); CXXRecordDecl *TargetClass = cast<CXXRecordDecl>(CurContext); @@ -4304,15 +4304,15 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, NestedNameSpecifier *DQual; if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) { DTypename = UD->isTypeName(); - DQual = UD->getTargetNestedNameDecl(); + DQual = UD->getQualifier(); } else if (UnresolvedUsingValueDecl *UD = dyn_cast<UnresolvedUsingValueDecl>(D)) { DTypename = false; - DQual = UD->getTargetNestedNameSpecifier(); + DQual = UD->getQualifier(); } else if (UnresolvedUsingTypenameDecl *UD = dyn_cast<UnresolvedUsingTypenameDecl>(D)) { DTypename = true; - DQual = UD->getTargetNestedNameSpecifier(); + DQual = UD->getQualifier(); } else continue; // using decls differ if one says 'typename' and the other doesn't. @@ -4542,8 +4542,7 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, NamespaceAliasDecl *AliasDecl = NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc, - Alias, SS.getRange(), - (NestedNameSpecifier *)SS.getScopeRep(), + Alias, SS.getWithLocInContext(Context), IdentLoc, R.getFoundDecl()); PushOnScopeChains(AliasDecl, S); @@ -5080,9 +5079,10 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, // reference to operator=; this is required to suppress the virtual // call mechanism. CXXScopeSpec SS; - SS.setRange(Loc); - SS.setScopeRep(NestedNameSpecifier::Create(S.Context, 0, false, - T.getTypePtr())); + SS.MakeTrivial(S.Context, + NestedNameSpecifier::Create(S.Context, 0, false, + T.getTypePtr()), + Loc); // Create the reference to operator=. ExprResult OpEqualRef @@ -5972,8 +5972,6 @@ void Sema::AddCXXDirectInitializerToDecl(Decl *RealDecl, // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) { - VDecl->setParsingAutoInit(false); - // FIXME: n3225 doesn't actually seem to indicate this is ill-formed if (Exprs.size() > 1) { Diag(Exprs.get()[1]->getSourceRange().getBegin(), diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp index 66f6f2b..652318f 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp @@ -856,9 +856,21 @@ static SourceRange getTypeRange(TypeSourceInfo *TSI) { static void CheckMethodOverrideReturn(Sema &S, ObjCMethodDecl *MethodImpl, - ObjCMethodDecl *MethodIface) { + ObjCMethodDecl *MethodDecl, + bool IsProtocolMethodDecl) { + if (IsProtocolMethodDecl && + (MethodDecl->getObjCDeclQualifier() != + MethodImpl->getObjCDeclQualifier())) { + S.Diag(MethodImpl->getLocation(), + diag::warn_conflicting_ret_type_modifiers) + << MethodImpl->getDeclName() + << getTypeRange(MethodImpl->getResultTypeSourceInfo()); + S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration) + << getTypeRange(MethodDecl->getResultTypeSourceInfo()); + } + if (S.Context.hasSameUnqualifiedType(MethodImpl->getResultType(), - MethodIface->getResultType())) + MethodDecl->getResultType())) return; unsigned DiagID = diag::warn_conflicting_ret_types; @@ -868,7 +880,7 @@ static void CheckMethodOverrideReturn(Sema &S, if (const ObjCObjectPointerType *ImplPtrTy = MethodImpl->getResultType()->getAs<ObjCObjectPointerType>()) { if (const ObjCObjectPointerType *IfacePtrTy = - MethodIface->getResultType()->getAs<ObjCObjectPointerType>()) { + MethodDecl->getResultType()->getAs<ObjCObjectPointerType>()) { // Allow non-matching return types as long as they don't violate // the principle of substitutability. Specifically, we permit // return types that are subclasses of the declared return type, @@ -882,20 +894,33 @@ static void CheckMethodOverrideReturn(Sema &S, S.Diag(MethodImpl->getLocation(), DiagID) << MethodImpl->getDeclName() - << MethodIface->getResultType() + << MethodDecl->getResultType() << MethodImpl->getResultType() << getTypeRange(MethodImpl->getResultTypeSourceInfo()); - S.Diag(MethodIface->getLocation(), diag::note_previous_definition) - << getTypeRange(MethodIface->getResultTypeSourceInfo()); + S.Diag(MethodDecl->getLocation(), diag::note_previous_definition) + << getTypeRange(MethodDecl->getResultTypeSourceInfo()); } static void CheckMethodOverrideParam(Sema &S, ObjCMethodDecl *MethodImpl, - ObjCMethodDecl *MethodIface, + ObjCMethodDecl *MethodDecl, ParmVarDecl *ImplVar, - ParmVarDecl *IfaceVar) { + ParmVarDecl *IfaceVar, + bool IsProtocolMethodDecl) { + if (IsProtocolMethodDecl && + (ImplVar->getObjCDeclQualifier() != + IfaceVar->getObjCDeclQualifier())) { + S.Diag(ImplVar->getLocation(), + diag::warn_conflicting_param_modifiers) + << getTypeRange(ImplVar->getTypeSourceInfo()) + << MethodImpl->getDeclName(); + S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration) + << getTypeRange(IfaceVar->getTypeSourceInfo()); + } + QualType ImplTy = ImplVar->getType(); QualType IfaceTy = IfaceVar->getType(); + if (S.Context.hasSameUnqualifiedType(ImplTy, IfaceTy)) return; @@ -927,17 +952,20 @@ static void CheckMethodOverrideParam(Sema &S, void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl, - ObjCMethodDecl *IntfMethodDecl) { - CheckMethodOverrideReturn(*this, ImpMethodDecl, IntfMethodDecl); + ObjCMethodDecl *MethodDecl, + bool IsProtocolMethodDecl) { + CheckMethodOverrideReturn(*this, ImpMethodDecl, MethodDecl, + IsProtocolMethodDecl); for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(), - IF = IntfMethodDecl->param_begin(), EM = ImpMethodDecl->param_end(); + IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end(); IM != EM; ++IM, ++IF) - CheckMethodOverrideParam(*this, ImpMethodDecl, IntfMethodDecl, *IM, *IF); + CheckMethodOverrideParam(*this, ImpMethodDecl, MethodDecl, *IM, *IF, + IsProtocolMethodDecl); - if (ImpMethodDecl->isVariadic() != IntfMethodDecl->isVariadic()) { + if (ImpMethodDecl->isVariadic() != MethodDecl->isVariadic()) { Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_variadic); - Diag(IntfMethodDecl->getLocation(), diag::note_previous_declaration); + Diag(MethodDecl->getLocation(), diag::note_previous_declaration); } } @@ -1061,13 +1089,14 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap, } else { ObjCMethodDecl *ImpMethodDecl = IMPDecl->getInstanceMethod((*I)->getSelector()); - ObjCMethodDecl *IntfMethodDecl = + ObjCMethodDecl *MethodDecl = CDecl->getInstanceMethod((*I)->getSelector()); - assert(IntfMethodDecl && - "IntfMethodDecl is null in ImplMethodsVsClassMethods"); + assert(MethodDecl && + "MethodDecl is null in ImplMethodsVsClassMethods"); // ImpMethodDecl may be null as in a @dynamic property. if (ImpMethodDecl) - WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl); + WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl, + isa<ObjCProtocolDecl>(CDecl)); } } @@ -1085,9 +1114,10 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap, } else { ObjCMethodDecl *ImpMethodDecl = IMPDecl->getClassMethod((*I)->getSelector()); - ObjCMethodDecl *IntfMethodDecl = + ObjCMethodDecl *MethodDecl = CDecl->getClassMethod((*I)->getSelector()); - WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl); + WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl, + isa<ObjCProtocolDecl>(CDecl)); } } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp index 65b57c3..415ab3f 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp @@ -76,12 +76,10 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, } // See if this is an auto-typed variable whose initializer we are parsing. - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { - if (VD->isParsingAutoInit()) { - Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer) - << D->getDeclName(); - return true; - } + if (ParsingInitForAutoVars.count(D)) { + Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer) + << D->getDeclName(); + return true; } // See if the decl is deprecated. @@ -389,13 +387,13 @@ bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT, return false; if (Expr->getType()->isObjCObjectType() && - DiagRuntimeBehavior(Expr->getLocStart(), + DiagRuntimeBehavior(Expr->getLocStart(), 0, PDiag(diag::err_cannot_pass_objc_interface_to_vararg) << Expr->getType() << CT)) return true; if (!Expr->getType()->isPODType() && - DiagRuntimeBehavior(Expr->getLocStart(), + DiagRuntimeBehavior(Expr->getLocStart(), 0, PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg) << Expr->getType() << CT)) return true; @@ -1675,20 +1673,6 @@ ExprResult Sema::ActOnIdExpression(Scope *S, // This is guaranteed from this point on. assert(!R.empty() || ADL); - if (VarDecl *Var = R.getAsSingle<VarDecl>()) { - if (getLangOptions().ObjCNonFragileABI && IvarLookupFollowUp && - !(getLangOptions().ObjCDefaultSynthProperties && - getLangOptions().ObjCNonFragileABI2) && - Var->isFileVarDecl()) { - ObjCPropertyDecl *Property = canSynthesizeProvisionalIvar(II); - if (Property) { - Diag(NameLoc, diag::warn_ivar_variable_conflict) << Var->getDeclName(); - Diag(Property->getLocation(), diag::note_property_declare); - Diag(Var->getLocation(), diag::note_global_declared_at); - } - } - } - // Check whether this might be a C++ implicit instance member access. // C++ [class.mfct.non-static]p3: // When an id-expression that is not part of a class member access @@ -3996,131 +3980,130 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, // Failure cases. fail: - // There's a possible road to recovery for function types. - const FunctionType *Fun = 0; - SourceLocation ParenInsertionLoc = - PP.getLocForEndOfToken(BaseExpr->getLocEnd()); - + // Recover from dot accesses to pointers, e.g.: + // type *foo; + // foo.bar + // This is actually well-formed in two cases: + // - 'type' is an Objective C type + // - 'bar' is a pseudo-destructor name which happens to refer to + // the appropriate pointer type if (const PointerType *Ptr = BaseType->getAs<PointerType>()) { - if ((Fun = Ptr->getPointeeType()->getAs<FunctionType>())) { - // fall out, handled below. - - // Recover from dot accesses to pointers, e.g.: - // type *foo; - // foo.bar - // This is actually well-formed in two cases: - // - 'type' is an Objective C type - // - 'bar' is a pseudo-destructor name which happens to refer to - // the appropriate pointer type - } else if (!IsArrow && Ptr->getPointeeType()->isRecordType() && - MemberName.getNameKind() != DeclarationName::CXXDestructorName) { + if (!IsArrow && Ptr->getPointeeType()->isRecordType() && + MemberName.getNameKind() != DeclarationName::CXXDestructorName) { Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) - << BaseType << int(IsArrow) << BaseExpr->getSourceRange() - << FixItHint::CreateReplacement(OpLoc, "->"); + << BaseType << int(IsArrow) << BaseExpr->getSourceRange() + << FixItHint::CreateReplacement(OpLoc, "->"); // Recurse as an -> access. IsArrow = true; return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, ObjCImpDecl, HasTemplateArgs); } - } else { - Fun = BaseType->getAs<FunctionType>(); - } - - // If the user is trying to apply -> or . to a function pointer - // type, it's probably because they forgot parentheses to call that - // function. Suggest the addition of those parentheses, build the - // call, and continue on. - if (Fun || BaseType == Context.OverloadTy) { - bool TryCall; - if (BaseType == Context.OverloadTy) { - // Plunder the overload set for something that would make the member - // expression valid. - const OverloadExpr *Overloads = cast<OverloadExpr>(BaseExpr); - UnresolvedSet<4> CandidateOverloads; - bool HasZeroArgCandidateOverload = false; - for (OverloadExpr::decls_iterator it = Overloads->decls_begin(), - DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) { - const FunctionDecl *OverloadDecl = cast<FunctionDecl>(*it); - QualType ResultTy = OverloadDecl->getResultType(); - if ((!IsArrow && ResultTy->isRecordType()) || - (IsArrow && ResultTy->isPointerType() && - ResultTy->getPointeeType()->isRecordType())) { - CandidateOverloads.addDecl(*it); - if (OverloadDecl->getNumParams() == 0) { - HasZeroArgCandidateOverload = true; - } + } + + // If the user is trying to apply -> or . to a function name, it's probably + // because they forgot parentheses to call that function. + bool TryCall = false; + bool Overloaded = false; + UnresolvedSet<8> AllOverloads; + if (const OverloadExpr *Overloads = dyn_cast<OverloadExpr>(BaseExpr)) { + AllOverloads.append(Overloads->decls_begin(), Overloads->decls_end()); + TryCall = true; + Overloaded = true; + } else if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(BaseExpr)) { + if (FunctionDecl* Fun = dyn_cast<FunctionDecl>(DeclRef->getDecl())) { + AllOverloads.addDecl(Fun); + TryCall = true; + } + } + + if (TryCall) { + // Plunder the overload set for something that would make the member + // expression valid. + UnresolvedSet<4> ViableOverloads; + bool HasViableZeroArgOverload = false; + for (OverloadExpr::decls_iterator it = AllOverloads.begin(), + DeclsEnd = AllOverloads.end(); it != DeclsEnd; ++it) { + const FunctionDecl *OverloadDecl = cast<FunctionDecl>(*it); + QualType ResultTy = OverloadDecl->getResultType(); + if ((!IsArrow && ResultTy->isRecordType()) || + (IsArrow && ResultTy->isPointerType() && + ResultTy->getPointeeType()->isRecordType())) { + ViableOverloads.addDecl(*it); + if (OverloadDecl->getMinRequiredArguments() == 0) { + HasViableZeroArgOverload = true; } } - if (HasZeroArgCandidateOverload && CandidateOverloads.size() == 1) { - // We have one reasonable overload, and there's only one way to call it, - // so emit a fixit and try to recover - Diag(ParenInsertionLoc, diag::err_member_reference_needs_call) - << 1 - << BaseExpr->getSourceRange() - << FixItHint::CreateInsertion(ParenInsertionLoc, "()"); - TryCall = true; - } else { - Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call) - << 0 - << BaseExpr->getSourceRange(); - int CandidateOverloadCount = CandidateOverloads.size(); - int I; - for (I = 0; I < CandidateOverloadCount; ++I) { - // FIXME: Magic number for max shown overloads stolen from - // OverloadCandidateSet::NoteCandidates. - if (I >= 4 && Diags.getShowOverloads() == Diagnostic::Ovl_Best) { - break; - } - Diag(CandidateOverloads[I].getDecl()->getSourceRange().getBegin(), - diag::note_member_ref_possible_intended_overload); - } - if (I != CandidateOverloadCount) { - Diag(BaseExpr->getExprLoc(), diag::note_ovl_too_many_candidates) - << int(CandidateOverloadCount - I); + } + + if (!HasViableZeroArgOverload || ViableOverloads.size() != 1) { + Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call) + << 1 << 0 + << BaseExpr->getSourceRange(); + int ViableOverloadCount = ViableOverloads.size(); + int I; + for (I = 0; I < ViableOverloadCount; ++I) { + // FIXME: Magic number for max shown overloads stolen from + // OverloadCandidateSet::NoteCandidates. + if (I >= 4 && Diags.getShowOverloads() == Diagnostic::Ovl_Best) { + break; } - return ExprError(); + Diag(ViableOverloads[I].getDecl()->getSourceRange().getBegin(), + diag::note_member_ref_possible_intended_overload); } - } else { - if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(Fun)) { - TryCall = (FPT->getNumArgs() == 0); - } else { - TryCall = true; + if (I != ViableOverloadCount) { + Diag(BaseExpr->getExprLoc(), diag::note_ovl_too_many_candidates) + << int(ViableOverloadCount - I); } - - if (TryCall) { - QualType ResultTy = Fun->getResultType(); - TryCall = (!IsArrow && ResultTy->isRecordType()) || - (IsArrow && ResultTy->isPointerType() && - ResultTy->getAs<PointerType>()->getPointeeType()->isRecordType()); + return ExprError(); + } + } else { + // We don't have an expression that's convenient to get a Decl from, but we + // can at least check if the type is "function of 0 arguments which returns + // an acceptable type". + const FunctionType *Fun = NULL; + if (const PointerType *Ptr = BaseType->getAs<PointerType>()) { + if ((Fun = Ptr->getPointeeType()->getAs<FunctionType>())) { + TryCall = true; } + } else if ((Fun = BaseType->getAs<FunctionType>())) { + TryCall = true; } - if (TryCall) { - if (Fun) { - Diag(BaseExpr->getExprLoc(), - diag::err_member_reference_needs_call_zero_arg) - << QualType(Fun, 0) - << FixItHint::CreateInsertion(ParenInsertionLoc, "()"); + if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(Fun)) { + if (FPT->getNumArgs() == 0) { + QualType ResultTy = Fun->getResultType(); + TryCall = (!IsArrow && ResultTy->isRecordType()) || + (IsArrow && ResultTy->isPointerType() && + ResultTy->getPointeeType()->isRecordType()); + } } - - ExprResult NewBase - = ActOnCallExpr(0, BaseExpr, ParenInsertionLoc, - MultiExprArg(*this, 0, 0), ParenInsertionLoc); - if (NewBase.isInvalid()) - return ExprError(); - BaseExpr = NewBase.takeAs<Expr>(); - - - DefaultFunctionArrayConversion(BaseExpr); - BaseType = BaseExpr->getType(); - - return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, - ObjCImpDecl, HasTemplateArgs); } } + if (TryCall) { + // At this point, we know BaseExpr looks like it's potentially callable with + // 0 arguments, and that it returns something of a reasonable type, so we + // can emit a fixit and carry on pretending that BaseExpr was actually a + // CallExpr. + SourceLocation ParenInsertionLoc = + PP.getLocForEndOfToken(BaseExpr->getLocEnd()); + Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call) + << int(Overloaded) << 1 + << BaseExpr->getSourceRange() + << FixItHint::CreateInsertion(ParenInsertionLoc, "()"); + ExprResult NewBase = ActOnCallExpr(0, BaseExpr, ParenInsertionLoc, + MultiExprArg(*this, 0, 0), + ParenInsertionLoc); + if (NewBase.isInvalid()) + return ExprError(); + BaseExpr = NewBase.takeAs<Expr>(); + DefaultFunctionArrayConversion(BaseExpr); + return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, + ObjCImpDecl, HasTemplateArgs); + } + Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union) << BaseType << BaseExpr->getSourceRange(); @@ -4298,6 +4281,13 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, const FunctionProtoType *Proto, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc) { + // Bail out early if calling a builtin with custom typechecking. + // We don't need to do this in the + if (FDecl) + if (unsigned ID = FDecl->getBuiltinID()) + if (Context.BuiltinInfo.hasCustomTypechecking(ID)) + return false; + // C99 6.5.2.2p7 - the arguments are implicitly converted, as if by // assignment, to the types of the corresponding parameter, ... unsigned NumArgsInProto = Proto->getNumArgs(); @@ -4625,22 +4615,41 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, RParenLoc); } + unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0); + + // Bail out early if calling a builtin with custom typechecking. + if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID)) + return CheckBuiltinFunctionCall(BuiltinID, TheCall); + const FunctionType *FuncT; - if (!Fn->getType()->isBlockPointerType()) { + if (const PointerType *PT = Fn->getType()->getAs<PointerType>()) { // C99 6.5.2.2p1 - "The expression that denotes the called function shall // have type pointer to function". - const PointerType *PT = Fn->getType()->getAs<PointerType>(); - if (PT == 0) - return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function) - << Fn->getType() << Fn->getSourceRange()); FuncT = PT->getPointeeType()->getAs<FunctionType>(); - } else { // This is a block call. - FuncT = Fn->getType()->getAs<BlockPointerType>()->getPointeeType()-> - getAs<FunctionType>(); - } - if (FuncT == 0) + if (FuncT == 0) + return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function) + << Fn->getType() << Fn->getSourceRange()); + } else if (const BlockPointerType *BPT = + Fn->getType()->getAs<BlockPointerType>()) { + FuncT = BPT->getPointeeType()->castAs<FunctionType>(); + } else { return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function) << Fn->getType() << Fn->getSourceRange()); + } + + if (getLangOptions().CUDA) { + if (Config) { + // CUDA: Kernel calls must be to global functions + if (FDecl && !FDecl->hasAttr<CUDAGlobalAttr>()) + return ExprError(Diag(LParenLoc,diag::err_kern_call_not_global_function) + << FDecl->getName() << Fn->getSourceRange()); + + // CUDA: Kernel function must have 'void' return type + if (!FuncT->getResultType()->isVoidType()) + return ExprError(Diag(LParenLoc, diag::err_kern_type_not_void_return) + << Fn->getType() << Fn->getSourceRange()); + } + } // Check for a valid return type if (CheckCallReturnType(FuncT->getResultType(), @@ -4721,7 +4730,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, if (CheckFunctionCall(FDecl, TheCall)) return ExprError(); - if (unsigned BuiltinID = FDecl->getBuiltinID()) + if (BuiltinID) return CheckBuiltinFunctionCall(BuiltinID, TheCall); } else if (NDecl) { if (CheckBlockCall(NDecl, TheCall)) @@ -6372,8 +6381,8 @@ QualType Sema::CheckMultiplyDivideOperands( // Check for division by zero. if (isDiv && rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) - DiagRuntimeBehavior(Loc, PDiag(diag::warn_division_by_zero) - << rex->getSourceRange()); + DiagRuntimeBehavior(Loc, rex, PDiag(diag::warn_division_by_zero) + << rex->getSourceRange()); return compType; } @@ -6394,8 +6403,8 @@ QualType Sema::CheckRemainderOperands( // Check for remainder by zero. if (rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) - DiagRuntimeBehavior(Loc, PDiag(diag::warn_remainder_by_zero) - << rex->getSourceRange()); + DiagRuntimeBehavior(Loc, rex, PDiag(diag::warn_remainder_by_zero) + << rex->getSourceRange()); return compType; } @@ -6629,9 +6638,61 @@ static bool isScopedEnumerationType(QualType T) { return false; } +static void DiagnoseBadShiftValues(Sema& S, Expr *&lex, Expr *&rex, + SourceLocation Loc, unsigned Opc, + QualType LHSTy) { + llvm::APSInt Right; + // Check right/shifter operand + if (rex->isValueDependent() || !rex->isIntegerConstantExpr(Right, S.Context)) + return; + + if (Right.isNegative()) { + S.Diag(Loc, diag::warn_shift_negative) << rex->getSourceRange(); + return; + } + llvm::APInt LeftBits(Right.getBitWidth(), + S.Context.getTypeSize(lex->getType())); + if (Right.uge(LeftBits)) { + S.Diag(Loc, diag::warn_shift_gt_typewidth) << rex->getSourceRange(); + return; + } + if (Opc != BO_Shl) + return; + + // When left shifting an ICE which is signed, we can check for overflow which + // according to C++ has undefined behavior ([expr.shift] 5.8/2). Unsigned + // integers have defined behavior modulo one more than the maximum value + // representable in the result type, so never warn for those. + llvm::APSInt Left; + if (lex->isValueDependent() || !lex->isIntegerConstantExpr(Left, S.Context) || + LHSTy->hasUnsignedIntegerRepresentation()) + return; + llvm::APInt ResultBits = + static_cast<llvm::APInt&>(Right) + Left.getMinSignedBits(); + if (LeftBits.uge(ResultBits)) + return; + llvm::APSInt Result = Left.extend(ResultBits.getLimitedValue()); + Result = Result.shl(Right); + + // If we are only missing a sign bit, this is less likely to result in actual + // bugs -- if the result is cast back to an unsigned type, it will have the + // expected value. Thus we place this behind a different warning that can be + // turned off separately if needed. + if (LeftBits == ResultBits - 1) { + S.Diag(Loc, diag::warn_shift_result_overrides_sign_bit) + << Result.toString(10) << LHSTy + << lex->getSourceRange() << rex->getSourceRange(); + return; + } + + S.Diag(Loc, diag::warn_shift_result_gt_typewidth) + << Result.toString(10) << Result.getMinSignedBits() << LHSTy + << Left.getBitWidth() << lex->getSourceRange() << rex->getSourceRange(); +} + // C99 6.5.7 QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, - bool isCompAssign) { + unsigned Opc, bool isCompAssign) { // C99 6.5.7p2: Each of the operands shall have integer type. if (!lex->getType()->hasIntegerRepresentation() || !rex->getType()->hasIntegerRepresentation()) @@ -6662,19 +6723,7 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, UsualUnaryConversions(rex); // Sanity-check shift operands - llvm::APSInt Right; - // Check right/shifter operand - if (!rex->isValueDependent() && - rex->isIntegerConstantExpr(Right, Context)) { - if (Right.isNegative()) - Diag(Loc, diag::warn_shift_negative) << rex->getSourceRange(); - else { - llvm::APInt LeftBits(Right.getBitWidth(), - Context.getTypeSize(lex->getType())); - if (Right.uge(LeftBits)) - Diag(Loc, diag::warn_shift_gt_typewidth) << rex->getSourceRange(); - } - } + DiagnoseBadShiftValues(*this, lex, rex, Loc, Opc, LHSTy); // "The type of the result is that of the promoted left operand." return LHSTy; @@ -6738,7 +6787,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped)) { if (DRL->getDecl() == DRR->getDecl() && !IsWithinTemplateSpecialization(DRL->getDecl())) { - DiagRuntimeBehavior(Loc, PDiag(diag::warn_comparison_always) + DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always) << 0 // self- << (Opc == BO_EQ || Opc == BO_LE @@ -6760,7 +6809,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, always_evals_to = 2; // e.g. array1 <= array2 break; } - DiagRuntimeBehavior(Loc, PDiag(diag::warn_comparison_always) + DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always) << 1 // array << always_evals_to); } @@ -6801,7 +6850,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, default: assert(false && "Invalid comparison operator"); } - DiagRuntimeBehavior(Loc, + DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_stringcompare) << isa<ObjCEncodeExpr>(literalStringStripped) << literalString->getSourceRange()); @@ -7111,7 +7160,7 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex, if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(lex->IgnoreParens())) if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(rex->IgnoreParens())) if (DRL->getDecl() == DRR->getDecl()) - DiagRuntimeBehavior(Loc, + DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always) << 0 // self- << 2 // "a constant" @@ -7372,9 +7421,11 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, UO->getSubExpr()->IgnoreParenCasts()-> isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull) && !UO->getType().isVolatileQualified()) { - Diag(UO->getOperatorLoc(), diag::warn_indirection_through_null) - << UO->getSubExpr()->getSourceRange(); - Diag(UO->getOperatorLoc(), diag::note_indirection_through_null); + DiagRuntimeBehavior(UO->getOperatorLoc(), UO, + PDiag(diag::warn_indirection_through_null) + << UO->getSubExpr()->getSourceRange()); + DiagRuntimeBehavior(UO->getOperatorLoc(), UO, + PDiag(diag::note_indirection_through_null)); } // Check for trivial buffer overflows. @@ -7959,7 +8010,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, break; case BO_Shl: case BO_Shr: - ResultTy = CheckShiftOperands(lhs, rhs, OpLoc); + ResultTy = CheckShiftOperands(lhs, rhs, OpLoc, Opc); break; case BO_LE: case BO_LT: @@ -8006,7 +8057,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, break; case BO_ShlAssign: case BO_ShrAssign: - CompResultTy = CheckShiftOperands(lhs, rhs, OpLoc, true); + CompResultTy = CheckShiftOperands(lhs, rhs, OpLoc, Opc, true); CompLHSTy = CompResultTy; if (!CompResultTy.isNull()) ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy); @@ -8563,7 +8614,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, // (clause 9). if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) { if (!CRD->isPOD() && !DidWarnAboutNonPOD && - DiagRuntimeBehavior(BuiltinLoc, + DiagRuntimeBehavior(BuiltinLoc, 0, PDiag(diag::warn_offsetof_non_pod_type) << SourceRange(CompPtr[0].LocStart, OC.LocEnd) << CurrentType)) @@ -8907,12 +8958,8 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy); - // Issue any analysis-based warnings. - const sema::AnalysisBasedWarnings::Policy &WP = - AnalysisWarnings.getDefaultPolicy(); - AnalysisWarnings.IssueWarnings(WP, Result); - - PopFunctionOrBlockScope(); + const AnalysisBasedWarnings::Policy &WP = AnalysisWarnings.getDefaultPolicy(); + PopFunctionOrBlockScope(&WP, Result->getBlockDecl(), Result); return Owned(Result); } @@ -9350,9 +9397,12 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { } } - // Keep track of used but undefined variables. + // Keep track of used but undefined variables. We make a hole in + // the warning for static const data members with in-line + // initializers. if (Var->hasDefinition() == VarDecl::DeclarationOnly - && Var->getLinkage() != ExternalLinkage) { + && Var->getLinkage() != ExternalLinkage + && !(Var->isStaticDataMember() && Var->hasInit())) { SourceLocation &old = UndefinedInternals[Var->getCanonicalDecl()]; if (old.isInvalid()) old = Loc; } @@ -9484,7 +9534,7 @@ void Sema::MarkDeclarationsReferencedInExpr(Expr *E) { /// behavior of a program, such as passing a non-POD value through an ellipsis. /// Failure to do so will likely result in spurious diagnostics or failures /// during overload resolution or within sizeof/alignof/typeof/typeid. -bool Sema::DiagRuntimeBehavior(SourceLocation Loc, +bool Sema::DiagRuntimeBehavior(SourceLocation Loc, const Stmt *stmt, const PartialDiagnostic &PD) { switch (ExprEvalContexts.back().Context ) { case Unevaluated: @@ -9493,7 +9543,13 @@ bool Sema::DiagRuntimeBehavior(SourceLocation Loc, case PotentiallyEvaluated: case PotentiallyEvaluatedIfUsed: - Diag(Loc, PD); + if (stmt && getCurFunctionOrMethodDecl()) { + FunctionScopes.back()->PossiblyUnreachableDiags. + push_back(sema::PossiblyUnreachableDiag(PD, Loc, stmt)); + } + else + Diag(Loc, PD); + return true; case PotentiallyPotentiallyEvaluated: diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp index f9c2c9a..6dd7aab 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp @@ -107,7 +107,7 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc, // Nothing left to do. } else if (LookAtPrefix && (Prefix = NNS->getPrefix())) { CXXScopeSpec PrefixSS; - PrefixSS.setScopeRep(Prefix); + PrefixSS.Adopt(NestedNameSpecifierLoc(Prefix, SS.location_data())); LookupCtx = computeDeclContext(PrefixSS, EnteringContext); isDependent = isDependentScopeSpecifier(PrefixSS); } else if (ObjectTypePtr) { @@ -476,7 +476,9 @@ Sema::ActOnCXXNullPtrLiteral(SourceLocation Loc) { /// ActOnCXXThrow - Parse throw expressions. ExprResult Sema::ActOnCXXThrow(SourceLocation OpLoc, Expr *Ex) { - if (!getLangOptions().Exceptions) + // Don't report an error if 'throw' is used in system headers. + if (!getLangOptions().Exceptions && + !getSourceManager().isInSystemHeader(OpLoc)) Diag(OpLoc, diag::err_exceptions_disabled) << "throw"; if (Ex && !Ex->isTypeDependent() && CheckCXXThrowOperand(OpLoc, Ex)) @@ -1347,6 +1349,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, case OR_Success: { // Got one! FunctionDecl *FnDecl = Best->Function; + MarkDeclarationReferenced(StartLoc, FnDecl); // The first argument is size_t, and the first parameter must be size_t, // too. This is checked on declaration and can be assumed. (It can't be // asserted on, though, since invalid decls are left in there.) @@ -1384,7 +1387,10 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, case OR_Deleted: Diag(StartLoc, diag::err_ovl_deleted_call) << Best->Function->isDeleted() - << Name << Range; + << Name + << Best->Function->getMessageUnavailableAttr( + !Best->Function->isDeleted()) + << Range; Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); return true; } @@ -2920,6 +2926,8 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS, Self.PerformImplicitConversion(RHS, Best->BuiltinTypes.ParamTypes[1], Best->Conversions[1], Sema::AA_Converting)) break; + if (Best->Function) + Self.MarkDeclarationReferenced(QuestionLoc, Best->Function); return false; case OR_No_Viable_Function: @@ -3580,14 +3588,14 @@ ExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc, } ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - const CXXScopeSpec &SS, - TypeSourceInfo *ScopeTypeInfo, - SourceLocation CCLoc, - SourceLocation TildeLoc, + SourceLocation OpLoc, + tok::TokenKind OpKind, + const CXXScopeSpec &SS, + TypeSourceInfo *ScopeTypeInfo, + SourceLocation CCLoc, + SourceLocation TildeLoc, PseudoDestructorTypeStorage Destructed, - bool HasTrailingLParen) { + bool HasTrailingLParen) { TypeSourceInfo *DestructedTypeInfo = Destructed.getTypeSourceInfo(); // C++ [expr.pseudo]p2: @@ -3662,7 +3670,7 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base, Expr *Result = new (Context) CXXPseudoDestructorExpr(Context, Base, OpKind == tok::arrow, OpLoc, - SS.getScopeRep(), SS.getRange(), + SS.getWithLocInContext(Context), ScopeTypeInfo, CCLoc, TildeLoc, @@ -3675,14 +3683,14 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base, } ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - CXXScopeSpec &SS, - UnqualifiedId &FirstTypeName, - SourceLocation CCLoc, - SourceLocation TildeLoc, - UnqualifiedId &SecondTypeName, - bool HasTrailingLParen) { + SourceLocation OpLoc, + tok::TokenKind OpKind, + CXXScopeSpec &SS, + UnqualifiedId &FirstTypeName, + SourceLocation CCLoc, + SourceLocation TildeLoc, + UnqualifiedId &SecondTypeName, + bool HasTrailingLParen) { assert((FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId || FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) && "Invalid first type name in pseudo-destructor"); @@ -3714,8 +3722,8 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, // record types and dependent types matter. ParsedType ObjectTypePtrForLookup; if (!SS.isSet()) { - if (const Type *T = ObjectType->getAs<RecordType>()) - ObjectTypePtrForLookup = ParsedType::make(QualType(T, 0)); + if (ObjectType->isRecordType()) + ObjectTypePtrForLookup = ParsedType::make(ObjectType); else if (ObjectType->isDependentType()) ObjectTypePtrForLookup = ParsedType::make(Context.DependentTy); } @@ -3784,7 +3792,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, if (FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) { ParsedType T = getTypeName(*FirstTypeName.Identifier, FirstTypeName.StartLocation, - S, &SS, false, false, ObjectTypePtrForLookup); + S, &SS, true, false, ObjectTypePtrForLookup); if (!T) { Diag(FirstTypeName.StartLocation, diag::err_pseudo_dtor_destructor_non_type) diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp index b9a6a57..5882da0 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp @@ -31,10 +31,8 @@ using namespace clang; // Sema Initialization Checking //===----------------------------------------------------------------------===// -static Expr *IsStringInit(Expr *Init, QualType DeclType, ASTContext &Context) { - const ArrayType *AT = Context.getAsArrayType(DeclType); - if (!AT) return 0; - +static Expr *IsStringInit(Expr *Init, const ArrayType *AT, + ASTContext &Context) { if (!isa<ConstantArrayType>(AT) && !isa<IncompleteArrayType>(AT)) return 0; @@ -66,13 +64,20 @@ static Expr *IsStringInit(Expr *Init, QualType DeclType, ASTContext &Context) { return 0; } -static void CheckStringInit(Expr *Str, QualType &DeclT, Sema &S) { +static Expr *IsStringInit(Expr *init, QualType declType, ASTContext &Context) { + const ArrayType *arrayType = Context.getAsArrayType(declType); + if (!arrayType) return 0; + + return IsStringInit(init, arrayType, Context); +} + +static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, + Sema &S) { // Get the length of the string as parsed. uint64_t StrLength = cast<ConstantArrayType>(Str->getType())->getSize().getZExtValue(); - const ArrayType *AT = S.Context.getAsArrayType(DeclT); if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) { // C99 6.7.8p14. We have an array of character type with unknown size // being initialized to a string literal. @@ -651,82 +656,93 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, newStructuredList, newStructuredIndex); ++StructuredIndex; ++Index; - } else if (Expr *Str = IsStringInit(expr, ElemType, SemaRef.Context)) { - CheckStringInit(Str, ElemType, SemaRef); - UpdateStructuredListElement(StructuredList, StructuredIndex, Str); - ++Index; + return; } else if (ElemType->isScalarType()) { - CheckScalarType(Entity, IList, ElemType, Index, - StructuredList, StructuredIndex); + return CheckScalarType(Entity, IList, ElemType, Index, + StructuredList, StructuredIndex); } else if (ElemType->isReferenceType()) { - CheckReferenceType(Entity, IList, ElemType, Index, - StructuredList, StructuredIndex); - } else { - if (SemaRef.getLangOptions().CPlusPlus) { - // C++ [dcl.init.aggr]p12: - // All implicit type conversions (clause 4) are considered when - // initializing the aggregate member with an ini- tializer from - // an initializer-list. If the initializer can initialize a - // member, the member is initialized. [...] - - // FIXME: Better EqualLoc? - InitializationKind Kind = - InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation()); - InitializationSequence Seq(SemaRef, Entity, Kind, &expr, 1); - - if (Seq) { - ExprResult Result = - Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1)); - if (Result.isInvalid()) - hadError = true; - - UpdateStructuredListElement(StructuredList, StructuredIndex, - Result.takeAs<Expr>()); - ++Index; - return; - } + return CheckReferenceType(Entity, IList, ElemType, Index, + StructuredList, StructuredIndex); + } - // Fall through for subaggregate initialization - } else { - // C99 6.7.8p13: - // - // The initializer for a structure or union object that has - // automatic storage duration shall be either an initializer - // list as described below, or a single expression that has - // compatible structure or union type. In the latter case, the - // initial value of the object, including unnamed members, is - // that of the expression. - if ((ElemType->isRecordType() || ElemType->isVectorType()) && - SemaRef.CheckSingleAssignmentConstraints(ElemType, expr) - == Sema::Compatible) { - SemaRef.DefaultFunctionArrayLvalueConversion(expr); - UpdateStructuredListElement(StructuredList, StructuredIndex, expr); - ++Index; - return; - } + if (const ArrayType *arrayType = SemaRef.Context.getAsArrayType(ElemType)) { + // arrayType can be incomplete if we're initializing a flexible + // array member. There's nothing we can do with the completed + // type here, though. - // Fall through for subaggregate initialization + if (Expr *Str = IsStringInit(expr, arrayType, SemaRef.Context)) { + CheckStringInit(Str, ElemType, arrayType, SemaRef); + UpdateStructuredListElement(StructuredList, StructuredIndex, Str); + ++Index; + return; } + // Fall through for subaggregate initialization. + + } else if (SemaRef.getLangOptions().CPlusPlus) { // C++ [dcl.init.aggr]p12: + // All implicit type conversions (clause 4) are considered when + // initializing the aggregate member with an ini- tializer from + // an initializer-list. If the initializer can initialize a + // member, the member is initialized. [...] + + // FIXME: Better EqualLoc? + InitializationKind Kind = + InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation()); + InitializationSequence Seq(SemaRef, Entity, Kind, &expr, 1); + + if (Seq) { + ExprResult Result = + Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1)); + if (Result.isInvalid()) + hadError = true; + + UpdateStructuredListElement(StructuredList, StructuredIndex, + Result.takeAs<Expr>()); + ++Index; + return; + } + + // Fall through for subaggregate initialization + } else { + // C99 6.7.8p13: // - // [...] Otherwise, if the member is itself a non-empty - // subaggregate, brace elision is assumed and the initializer is - // considered for the initialization of the first member of - // the subaggregate. - if (ElemType->isAggregateType() || ElemType->isVectorType()) { - CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList, - StructuredIndex); - ++StructuredIndex; - } else { - // We cannot initialize this element, so let - // PerformCopyInitialization produce the appropriate diagnostic. - SemaRef.PerformCopyInitialization(Entity, SourceLocation(), - SemaRef.Owned(expr)); - hadError = true; + // The initializer for a structure or union object that has + // automatic storage duration shall be either an initializer + // list as described below, or a single expression that has + // compatible structure or union type. In the latter case, the + // initial value of the object, including unnamed members, is + // that of the expression. + if ((ElemType->isRecordType() || ElemType->isVectorType()) && + SemaRef.CheckSingleAssignmentConstraints(ElemType, expr) + == Sema::Compatible) { + SemaRef.DefaultFunctionArrayLvalueConversion(expr); + UpdateStructuredListElement(StructuredList, StructuredIndex, expr); ++Index; - ++StructuredIndex; + return; } + + // Fall through for subaggregate initialization + } + + // C++ [dcl.init.aggr]p12: + // + // [...] Otherwise, if the member is itself a non-empty + // subaggregate, brace elision is assumed and the initializer is + // considered for the initialization of the first member of + // the subaggregate. + if (ElemType->isAggregateType() || ElemType->isVectorType()) { + CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList, + StructuredIndex); + ++StructuredIndex; + } else { + // We cannot initialize this element, so let + // PerformCopyInitialization produce the appropriate diagnostic. + SemaRef.PerformCopyInitialization(Entity, SourceLocation(), + SemaRef.Owned(expr)); + hadError = true; + ++Index; + ++StructuredIndex; } } @@ -936,11 +952,13 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex) { + const ArrayType *arrayType = SemaRef.Context.getAsArrayType(DeclType); + // Check for the special-case of initializing an array with a string. if (Index < IList->getNumInits()) { - if (Expr *Str = IsStringInit(IList->getInit(Index), DeclType, + if (Expr *Str = IsStringInit(IList->getInit(Index), arrayType, SemaRef.Context)) { - CheckStringInit(Str, DeclType, SemaRef); + CheckStringInit(Str, DeclType, arrayType, SemaRef); // We place the string literal directly into the resulting // initializer list. This is the only place where the structure // of the structured initializer list doesn't match exactly, @@ -952,8 +970,7 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity, return; } } - if (const VariableArrayType *VAT = - SemaRef.Context.getAsVariableArrayType(DeclType)) { + if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(arrayType)) { // Check for VLAs; in standard C it would be possible to check this // earlier, but I don't know where clang accepts VLAs (gcc accepts // them in all sorts of strange places). @@ -970,16 +987,14 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity, llvm::APSInt maxElements(elementIndex.getBitWidth(), elementIndex.isUnsigned()); bool maxElementsKnown = false; - if (const ConstantArrayType *CAT = - SemaRef.Context.getAsConstantArrayType(DeclType)) { + if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(arrayType)) { maxElements = CAT->getSize(); elementIndex = elementIndex.extOrTrunc(maxElements.getBitWidth()); elementIndex.setIsUnsigned(maxElements.isUnsigned()); maxElementsKnown = true; } - QualType elementType = SemaRef.Context.getAsArrayType(DeclType) - ->getElementType(); + QualType elementType = arrayType->getElementType(); while (Index < IList->getNumInits()) { Expr *Init = IList->getInit(Index); if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) { @@ -2059,6 +2074,7 @@ void InitializationSequence::Step::Destroy() { case SK_CAssignment: case SK_StringInit: case SK_ObjCObjectConversion: + case SK_ArrayInit: break; case SK_ConversionSequence: @@ -2090,6 +2106,8 @@ bool InitializationSequence::isAmbiguous() const { case FK_InitListBadDestinationType: case FK_DefaultInitOfConst: case FK_Incomplete: + case FK_ArrayTypeMismatch: + case FK_NonConstantArrayInit: return false; case FK_ReferenceInitOverloadFailed: @@ -2232,6 +2250,13 @@ void InitializationSequence::AddObjCObjectConversionStep(QualType T) { Steps.push_back(S); } +void InitializationSequence::AddArrayInitStep(QualType T) { + Step S; + S.Kind = SK_ArrayInit; + S.Type = T; + Steps.push_back(S); +} + void InitializationSequence::SetOverloadFailure(FailureKind Failure, OverloadingResult Result) { SequenceKind = FailedSequence; @@ -2416,6 +2441,10 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, FunctionDecl *Function = Best->Function; + // This is the overload that will actually be used for the initialization, so + // mark it as used. + S.MarkDeclarationReferenced(DeclLoc, Function); + // Compute the returned type of the conversion. if (isa<CXXConversionDecl>(Function)) T2 = Function->getResultType(); @@ -3020,6 +3049,7 @@ static void TryUserDefinedConversion(Sema &S, } FunctionDecl *Function = Best->Function; + S.MarkDeclarationReferenced(DeclLoc, Function); if (isa<CXXConstructorDecl>(Function)) { // Add the user-defined conversion step. Any cv-qualification conversion is @@ -3054,6 +3084,25 @@ static void TryUserDefinedConversion(Sema &S, } } +/// \brief Determine whether we have compatible array types for the +/// purposes of GNU by-copy array initialization. +static bool hasCompatibleArrayTypes(ASTContext &Context, + const ArrayType *Dest, + const ArrayType *Source) { + // If the source and destination array types are equivalent, we're + // done. + if (Context.hasSameType(QualType(Dest, 0), QualType(Source, 0))) + return true; + + // Make sure that the element types are the same. + if (!Context.hasSameType(Dest->getElementType(), Source->getElementType())) + return false; + + // The only mismatch we allow is when the destination is an + // incomplete array type and the source is a constant array type. + return Source->isConstantArrayType() && Dest->isIncompleteArrayType(); +} + InitializationSequence::InitializationSequence(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, @@ -3109,14 +3158,6 @@ InitializationSequence::InitializationSequence(Sema &S, return; } - // - If the destination type is an array of characters, an array of - // char16_t, an array of char32_t, or an array of wchar_t, and the - // initializer is a string literal, see 8.5.2. - if (Initializer && IsStringInit(Initializer, DestType, Context)) { - TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this); - return; - } - // - If the initializer is (), the object is value-initialized. if (Kind.getKind() == InitializationKind::IK_Value || (Kind.getKind() == InitializationKind::IK_Direct && NumArgs == 0)) { @@ -3130,10 +3171,34 @@ InitializationSequence::InitializationSequence(Sema &S, return; } + // - If the destination type is an array of characters, an array of + // char16_t, an array of char32_t, or an array of wchar_t, and the + // initializer is a string literal, see 8.5.2. // - Otherwise, if the destination type is an array, the program is // ill-formed. - if (const ArrayType *AT = Context.getAsArrayType(DestType)) { - if (AT->getElementType()->isAnyCharacterType()) + if (const ArrayType *DestAT = Context.getAsArrayType(DestType)) { + if (Initializer && IsStringInit(Initializer, DestAT, Context)) { + TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this); + return; + } + + // Note: as an GNU C extension, we allow initialization of an + // array from a compound literal that creates an array of the same + // type, so long as the initializer has no side effects. + if (!S.getLangOptions().CPlusPlus && Initializer && + isa<CompoundLiteralExpr>(Initializer->IgnoreParens()) && + Initializer->getType()->isArrayType()) { + const ArrayType *SourceAT + = Context.getAsArrayType(Initializer->getType()); + if (!hasCompatibleArrayTypes(S.Context, DestAT, SourceAT)) + SetFailed(FK_ArrayTypeMismatch); + else if (Initializer->HasSideEffects(S.Context)) + SetFailed(FK_NonConstantArrayInit); + else { + setSequenceKind(ArrayInit); + AddArrayInitStep(DestType); + } + } else if (DestAT->getElementType()->isAnyCharacterType()) SetFailed(FK_ArrayNeedsInitListOrStringLiteral); else SetFailed(FK_ArrayNeedsInitList); @@ -3482,6 +3547,8 @@ static ExprResult CopyObject(Sema &S, return S.Owned(CurInitExpr); } + S.MarkDeclarationReferenced(Loc, Constructor); + // Determine the arguments required to actually perform the // constructor call (we might have derived-to-base conversions, or // the copy constructor may have default arguments). @@ -3616,7 +3683,8 @@ InitializationSequence::Perform(Sema &S, case SK_ListInitialization: case SK_CAssignment: case SK_StringInit: - case SK_ObjCObjectConversion: { + case SK_ObjCObjectConversion: + case SK_ArrayInit: { assert(Args.size() == 1); Expr *CurInitExpr = Args.get()[0]; if (!CurInitExpr) return ExprError(); @@ -4029,7 +4097,8 @@ InitializationSequence::Perform(Sema &S, case SK_StringInit: { QualType Ty = Step->Type; - CheckStringInit(CurInitExpr, ResultType ? *ResultType : Ty, S); + CheckStringInit(CurInitExpr, ResultType ? *ResultType : Ty, + S.Context.getAsArrayType(Ty), S); break; } @@ -4040,6 +4109,30 @@ InitializationSequence::Perform(Sema &S, CurInit.release(); CurInit = S.Owned(CurInitExpr); break; + + case SK_ArrayInit: + // Okay: we checked everything before creating this step. Note that + // this is a GNU extension. + S.Diag(Kind.getLocation(), diag::ext_array_init_copy) + << Step->Type << CurInitExpr->getType() + << CurInitExpr->getSourceRange(); + + // If the destination type is an incomplete array type, update the + // type accordingly. + if (ResultType) { + if (const IncompleteArrayType *IncompleteDest + = S.Context.getAsIncompleteArrayType(Step->Type)) { + if (const ConstantArrayType *ConstantSource + = S.Context.getAsConstantArrayType(CurInitExpr->getType())) { + *ResultType = S.Context.getConstantArrayType( + IncompleteDest->getElementType(), + ConstantSource->getSize(), + ArrayType::Normal, 0); + } + } + } + + break; } } @@ -4081,6 +4174,17 @@ bool InitializationSequence::Diagnose(Sema &S, << (Failure == FK_ArrayNeedsInitListOrStringLiteral); break; + case FK_ArrayTypeMismatch: + case FK_NonConstantArrayInit: + S.Diag(Kind.getLocation(), + (Failure == FK_ArrayTypeMismatch + ? diag::err_array_init_different_type + : diag::err_array_init_non_constant_array)) + << DestType.getNonReferenceType() + << Args[0]->getType() + << Args[0]->getSourceRange(); + break; + case FK_AddressOfOverloadFailed: { DeclAccessPair Found; S.ResolveAddressOfOverloadedFunction(Args[0], @@ -4338,6 +4442,14 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const { OS << "array requires initializer list or string literal"; break; + case FK_ArrayTypeMismatch: + OS << "array type mismatch"; + break; + + case FK_NonConstantArrayInit: + OS << "non-constant array initializer"; + break; + case FK_AddressOfOverloadFailed: OS << "address of overloaded function failed"; break; @@ -4441,6 +4553,10 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const { case StringInit: OS << "String initialization: "; break; + + case ArrayInit: + OS << "Array initialization: "; + break; } for (step_iterator S = step_begin(), SEnd = step_end(); S != SEnd; ++S) { @@ -4520,6 +4636,10 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const { case SK_ObjCObjectConversion: OS << "Objective-C object conversion"; break; + + case SK_ArrayInit: + OS << "array initialization"; + break; } } } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp index 0fd0e08..3deb403 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp @@ -18,6 +18,7 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/TemplateDeduction.h" +#include "clang/Sema/ExternalSemaSource.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" @@ -1132,7 +1133,11 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { if (AllowBuiltinCreation) return LookupBuiltin(*this, R); - return false; + // If we didn't find a use of this identifier, the ExternalSource + // may be able to handle the situation. + // Note: some lookup failures are expected! + // See e.g. R.isForRedeclaration(). + return (ExternalSource && ExternalSource->LookupUnqualified(R, S)); } /// @brief Perform qualified name lookup in the namespaces nominated by diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp index 6fb789c..8d03285 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp @@ -2261,6 +2261,8 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // Record the standard conversion we used and the conversion function. if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Best->Function)) { + S.MarkDeclarationReferenced(From->getLocStart(), Constructor); + // C++ [over.ics.user]p1: // If the user-defined conversion is specified by a // constructor (12.3.1), the initial standard conversion @@ -2282,6 +2284,8 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, return OR_Success; } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(Best->Function)) { + S.MarkDeclarationReferenced(From->getLocStart(), Conversion); + // C++ [over.ics.user]p1: // // [...] If the user-defined conversion is specified by a @@ -3068,6 +3072,8 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, if (!Best->FinalConversion.DirectBinding) return false; + if (Best->Function) + S.MarkDeclarationReferenced(DeclLoc, Best->Function); ICS.setUserDefined(); ICS.UserDefined.Before = Best->Conversions[0].Standard; ICS.UserDefined.After = Best->FinalConversion; @@ -6280,15 +6286,6 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc, Best->Function->getAttr<UnavailableAttr>())) return OR_Deleted; - // C++ [basic.def.odr]p2: - // An overloaded function is used if it is selected by overload resolution - // when referred to from a potentially-evaluated expression. [Note: this - // covers calls to named functions (5.2.2), operator overloading - // (clause 13), user-defined conversions (12.3.2), allocation function for - // placement new (5.3.4), as well as non-default initialization (8.5). - if (Best->Function) - S.MarkDeclarationReferenced(Loc, Best->Function); - return OR_Success; } @@ -7078,16 +7075,6 @@ void OverloadCandidateSet::NoteCandidates(Sema &S, S.Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I); } -static bool CheckUnresolvedAccess(Sema &S, OverloadExpr *E, DeclAccessPair D) { - if (isa<UnresolvedLookupExpr>(E)) - return S.CheckUnresolvedLookupAccess(cast<UnresolvedLookupExpr>(E), D); - - return S.CheckUnresolvedMemberAccess(cast<UnresolvedMemberExpr>(E), D); -} - - - - // [PossiblyAFunctionType] --> [Return] // NonFunctionType --> NonFunctionType // R (A) --> R(A) @@ -7603,10 +7590,9 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, SourceLocation RParenLoc) { CXXScopeSpec SS; - if (ULE->getQualifier()) { - SS.setScopeRep(ULE->getQualifier()); - SS.setRange(ULE->getQualifierRange()); - } + if (ULE->getQualifier()) + SS.MakeTrivial(SemaRef.Context, + ULE->getQualifier(), ULE->getQualifierRange()); TemplateArgumentListInfo TABuffer; const TemplateArgumentListInfo *ExplicitTemplateArgs = 0; @@ -7691,6 +7677,7 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, switch (CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best)) { case OR_Success: { FunctionDecl *FDecl = Best->Function; + MarkDeclarationReferenced(Fn->getExprLoc(), FDecl); CheckUnresolvedLookupAccess(ULE, Best->FoundDecl); DiagnoseUseOfDecl(FDecl? FDecl : Best->FoundDecl.getDecl(), ULE->getNameLoc()); @@ -7713,11 +7700,15 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, break; case OR_Deleted: - Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_deleted_call) - << Best->Function->isDeleted() - << ULE->getName() - << Fn->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + { + Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_deleted_call) + << Best->Function->isDeleted() + << ULE->getName() + << Best->Function->getMessageUnavailableAttr( + !Best->Function->isDeleted()) + << Fn->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + } break; } @@ -7824,6 +7815,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, // We matched an overloaded operator. Build a call to that // operator. + MarkDeclarationReferenced(OpLoc, FnDecl); + // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { CheckMemberOperatorAccess(OpLoc, Args[0], 0, Best->FoundDecl); @@ -7895,6 +7888,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, Diag(OpLoc, diag::err_ovl_deleted_oper) << Best->Function->isDeleted() << UnaryOperator::getOpcodeStr(Opc) + << Best->Function->getMessageUnavailableAttr( + !Best->Function->isDeleted()) << Input->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); return ExprError(); @@ -8047,6 +8042,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // We matched an overloaded operator. Build a call to that // operator. + MarkDeclarationReferenced(OpLoc, FnDecl); + // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { // Best->Access is only meaningful for class members. @@ -8161,6 +8158,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, Diag(OpLoc, diag::err_ovl_deleted_oper) << Best->Function->isDeleted() << BinaryOperator::getOpcodeStr(Opc) + << Best->Function->getMessageUnavailableAttr( + !Best->Function->isDeleted()) << Args[0]->getSourceRange() << Args[1]->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2); return ExprError(); @@ -8228,6 +8227,8 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // We matched an overloaded operator. Build a call to that // operator. + MarkDeclarationReferenced(LLoc, FnDecl); + CheckMemberOperatorAccess(LLoc, Args[0], Args[1], Best->FoundDecl); DiagnoseUseOfDecl(Best->FoundDecl, LLoc); @@ -8307,6 +8308,8 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, case OR_Deleted: Diag(LLoc, diag::err_ovl_deleted_oper) << Best->Function->isDeleted() << "[]" + << Best->Function->getMessageUnavailableAttr( + !Best->Function->isDeleted()) << Args[0]->getSourceRange() << Args[1]->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2, "[]", LLoc); @@ -8399,6 +8402,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, Best)) { case OR_Success: Method = cast<CXXMethodDecl>(Best->Function); + MarkDeclarationReferenced(UnresExpr->getMemberLoc(), Method); FoundDecl = Best->FoundDecl; CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl); DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc()); @@ -8422,7 +8426,10 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, case OR_Deleted: Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call) << Best->Function->isDeleted() - << DeclName << MemExprE->getSourceRange(); + << DeclName + << Best->Function->getMessageUnavailableAttr( + !Best->Function->isDeleted()) + << MemExprE->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); // FIXME: Leaking incoming expressions! return ExprError(); @@ -8594,7 +8601,10 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, Diag(Object->getSourceRange().getBegin(), diag::err_ovl_deleted_object_call) << Best->Function->isDeleted() - << Object->getType() << Object->getSourceRange(); + << Object->getType() + << Best->Function->getMessageUnavailableAttr( + !Best->Function->isDeleted()) + << Object->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); break; } @@ -8626,6 +8636,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, RParenLoc); } + MarkDeclarationReferenced(LParenLoc, Best->Function); CheckMemberOperatorAccess(LParenLoc, Object, 0, Best->FoundDecl); DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc); @@ -8799,11 +8810,15 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { case OR_Deleted: Diag(OpLoc, diag::err_ovl_deleted_oper) << Best->Function->isDeleted() - << "->" << Base->getSourceRange(); + << "->" + << Best->Function->getMessageUnavailableAttr( + !Best->Function->isDeleted()) + << Base->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &Base, 1); return ExprError(); } + MarkDeclarationReferenced(OpLoc, Best->Function); CheckMemberOperatorAccess(OpLoc, Base, 0, Best->FoundDecl); DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp index e995e8f..89957e6 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp @@ -25,6 +25,7 @@ #include "clang/AST/TypeLoc.h" #include "clang/Lex/Preprocessor.h" #include "clang/Basic/TargetInfo.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" using namespace clang; @@ -92,6 +93,8 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { unsigned DiagID = diag::warn_unused_expr; if (const ExprWithCleanups *Temps = dyn_cast<ExprWithCleanups>(E)) E = Temps->getSubExpr(); + if (const CXXBindTemporaryExpr *TempExpr = dyn_cast<CXXBindTemporaryExpr>(E)) + E = TempExpr->getSubExpr(); E = E->IgnoreParenImpCasts(); if (const CallExpr *CE = dyn_cast<CallExpr>(E)) { @@ -143,7 +146,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { } } - DiagRuntimeBehavior(Loc, PDiag(DiagID) << R1 << R2); + DiagRuntimeBehavior(Loc, 0, PDiag(DiagID) << R1 << R2); } StmtResult @@ -499,8 +502,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, bool HasDependentValue = CondExpr->isTypeDependent() || CondExpr->isValueDependent(); unsigned CondWidth - = HasDependentValue? 0 - : static_cast<unsigned>(Context.getTypeSize(CondTypeBeforePromotion)); + = HasDependentValue ? 0 : Context.getIntWidth(CondTypeBeforePromotion); bool CondIsSigned = CondTypeBeforePromotion->isSignedIntegerType(); // Accumulate all of the case values in a vector so that we can sort them @@ -1392,19 +1394,29 @@ static bool CheckAsmLValue(const Expr *E, Sema &S) { return true; } +/// isOperandMentioned - Return true if the specified operand # is mentioned +/// anywhere in the decomposed asm string. +static bool isOperandMentioned(unsigned OpNo, + llvm::ArrayRef<AsmStmt::AsmStringPiece> AsmStrPieces) { + for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) { + const AsmStmt::AsmStringPiece &Piece = AsmStrPieces[p]; + if (!Piece.isOperand()) continue; + + // If this is a reference to the input and if the input was the smaller + // one, then we have to reject this asm. + if (Piece.getOperandNo() == OpNo) + return true; + } + + return false; +} -StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, - bool IsSimple, - bool IsVolatile, - unsigned NumOutputs, - unsigned NumInputs, - IdentifierInfo **Names, - MultiExprArg constraints, - MultiExprArg exprs, - Expr *asmString, - MultiExprArg clobbers, - SourceLocation RParenLoc, - bool MSAsm) { +StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, + bool IsVolatile, unsigned NumOutputs, + unsigned NumInputs, IdentifierInfo **Names, + MultiExprArg constraints, MultiExprArg exprs, + Expr *asmString, MultiExprArg clobbers, + SourceLocation RParenLoc, bool MSAsm) { unsigned NumClobbers = clobbers.size(); StringLiteral **Constraints = reinterpret_cast<StringLiteral**>(constraints.get()); @@ -1529,8 +1541,9 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, if (!Info.hasTiedOperand()) continue; unsigned TiedTo = Info.getTiedOperand(); + unsigned InputOpNo = i+NumOutputs; Expr *OutputExpr = Exprs[TiedTo]; - Expr *InputExpr = Exprs[i+NumOutputs]; + Expr *InputExpr = Exprs[InputOpNo]; QualType InTy = InputExpr->getType(); QualType OutTy = OutputExpr->getType(); if (Context.hasSameType(InTy, OutTy)) @@ -1569,30 +1582,22 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, continue; // If the smaller input/output operand is not mentioned in the asm string, - // then we can promote it and the asm string won't notice. Check this - // case now. + // then we can promote the smaller one to a larger input and the asm string + // won't notice. bool SmallerValueMentioned = false; - for (unsigned p = 0, e = Pieces.size(); p != e; ++p) { - AsmStmt::AsmStringPiece &Piece = Pieces[p]; - if (!Piece.isOperand()) continue; - - // If this is a reference to the input and if the input was the smaller - // one, then we have to reject this asm. - if (Piece.getOperandNo() == i+NumOutputs) { - if (InSize < OutSize) { - SmallerValueMentioned = true; - break; - } - } - - // If this is a reference to the input and if the input was the smaller - // one, then we have to reject this asm. - if (Piece.getOperandNo() == TiedTo) { - if (InSize > OutSize) { - SmallerValueMentioned = true; - break; - } - } + + // If this is a reference to the input and if the input was the smaller + // one, then we have to reject this asm. + if (isOperandMentioned(InputOpNo, Pieces)) { + // This is a use in the asm string of the smaller operand. Since we + // codegen this by promoting to a wider value, the asm will get printed + // "wrong". + SmallerValueMentioned |= InSize < OutSize; + } + if (isOperandMentioned(TiedTo, Pieces)) { + // If this is a reference to the output, and if the output is the larger + // value, then it's ok because we'll promote the input to the larger type. + SmallerValueMentioned |= OutSize < InSize; } // If the smaller value wasn't mentioned in the asm string, and if the @@ -1601,7 +1606,20 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, if (!SmallerValueMentioned && InputDomain != AD_Other && OutputConstraintInfos[TiedTo].allowsRegister()) continue; - + + // Either both of the operands were mentioned or the smaller one was + // mentioned. One more special case that we'll allow: if the tied input is + // integer, unmentioned, and is a constant, then we'll allow truncating it + // down to the size of the destination. + if (InputDomain == AD_Int && OutputDomain == AD_Int && + !isOperandMentioned(InputOpNo, Pieces) && + InputExpr->isEvaluatable(Context)) { + ImpCastExprToType(InputExpr, OutTy, CK_IntegralCast); + Exprs[InputOpNo] = InputExpr; + NS->setInputExpr(i, InputExpr); + continue; + } + Diag(InputExpr->getLocStart(), diag::err_asm_tying_incompatible_types) << InTy << OutTy << OutputExpr->getSourceRange() @@ -1747,8 +1765,10 @@ public: StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, MultiStmtArg RawHandlers) { - if (!getLangOptions().Exceptions) - Diag(TryLoc, diag::err_exceptions_disabled) << "try"; + // Don't report an error if 'try' is used in system headers. + if (!getLangOptions().Exceptions && + !getSourceManager().isInSystemHeader(TryLoc)) + Diag(TryLoc, diag::err_exceptions_disabled) << "try"; unsigned NumHandlers = RawHandlers.size(); assert(NumHandlers > 0 && diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp index f0a0103..f02dd25 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp @@ -400,8 +400,7 @@ Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs) { return Owned(DependentScopeDeclRefExpr::Create(Context, - static_cast<NestedNameSpecifier*>(SS.getScopeRep()), - SS.getRange(), + SS.getWithLocInContext(Context), NameInfo, TemplateArgs)); } @@ -783,8 +782,7 @@ Sema::ActOnTemplateParameterList(unsigned Depth, static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) { if (SS.isSet()) - T->setQualifierInfo(static_cast<NestedNameSpecifier*>(SS.getScopeRep()), - SS.getRange()); + T->setQualifierInfo(SS.getWithLocInContext(T->getASTContext())); } DeclResult @@ -2333,9 +2331,13 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, DeclarationNameInfo NameInfo(DTN->getIdentifier(), Arg.getTemplateNameLoc()); + // FIXME: TemplateArgumentLoc should store a NestedNameSpecifierLoc + // for the template name. + CXXScopeSpec SS; + SS.MakeTrivial(Context, DTN->getQualifier(), + Arg.getTemplateQualifierRange()); Expr *E = DependentScopeDeclRefExpr::Create(Context, - DTN->getQualifier(), - Arg.getTemplateQualifierRange(), + SS.getWithLocInContext(Context), NameInfo); // If we parsed the template argument as a pack expansion, create a @@ -2868,6 +2870,7 @@ bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier( switch (NNS->getKind()) { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: return false; @@ -3610,7 +3613,7 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, = NestedNameSpecifier::Create(Context, 0, false, ClassType.getTypePtr()); CXXScopeSpec SS; - SS.setScopeRep(Qualifier); + SS.MakeTrivial(Context, Qualifier, Loc); // The actual value-ness of this is unimportant, but for // internal consistency's sake, references to instance methods @@ -5997,8 +6000,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, SourceLocation KeywordLoc, SourceRange NNSRange, SourceLocation IILoc) { CXXScopeSpec SS; - SS.setScopeRep(NNS); - SS.setRange(NNSRange); + SS.MakeTrivial(Context, NNS, NNSRange); DeclContext *Ctx = computeDeclContext(SS); if (!Ctx) { @@ -6036,7 +6038,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, << Name << Ctx << FullRange; if (UnresolvedUsingValueDecl *Using = dyn_cast<UnresolvedUsingValueDecl>(Result.getRepresentativeDecl())){ - SourceLocation Loc = Using->getTargetNestedNameRange().getBegin(); + SourceLocation Loc = Using->getQualifierLoc().getBeginLoc(); Diag(Loc, diag::note_using_value_decl_missing_typename) << FixItHint::CreateInsertion(Loc, "typename "); } @@ -6168,16 +6170,18 @@ ExprResult Sema::RebuildExprInCurrentInstantiation(Expr *E) { } bool Sema::RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS) { - if (SS.isInvalid()) return true; + if (SS.isInvalid()) + return true; - NestedNameSpecifier *NNS = static_cast<NestedNameSpecifier*>(SS.getScopeRep()); + NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); CurrentInstantiationRebuilder Rebuilder(*this, SS.getRange().getBegin(), DeclarationName()); - NestedNameSpecifier *Rebuilt = - Rebuilder.TransformNestedNameSpecifier(NNS, SS.getRange()); - if (!Rebuilt) return true; + NestedNameSpecifierLoc Rebuilt + = Rebuilder.TransformNestedNameSpecifierLoc(QualifierLoc); + if (!Rebuilt) + return true; - SS.setScopeRep(Rebuilt); + SS.Adopt(Rebuilt); return false; } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp index bd0a618..139fafb 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3004,12 +3004,12 @@ Sema::DeduceAutoType(QualType Type, Expr *Init, QualType &Result) { LocalInstantiationScope InstScope(*this); // Build template<class TemplParam> void Func(FuncParam); - NamedDecl *TemplParam - = TemplateTypeParmDecl::Create(Context, 0, Loc, 0, 0, 0, false, false); - TemplateParameterList *TemplateParams - = TemplateParameterList::Create(Context, Loc, Loc, &TemplParam, 1, Loc); - QualType TemplArg = Context.getTemplateTypeParmType(0, 0, false); + TemplateTypeParmDecl TemplParam(0, Loc, 0, false, TemplArg, false); + NamedDecl *TemplParamPtr = &TemplParam; + FixedSizeTemplateParameterList<1> TemplateParams(Loc, Loc, &TemplParamPtr, + Loc); + QualType FuncParam = SubstituteAutoTransform(*this, TemplArg).TransformType(Type); @@ -3018,13 +3018,13 @@ Sema::DeduceAutoType(QualType Type, Expr *Init, QualType &Result) { Deduced.resize(1); QualType InitType = Init->getType(); unsigned TDF = 0; - if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams, + if (AdjustFunctionParmAndArgTypesForDeduction(*this, &TemplateParams, FuncParam, InitType, Init, TDF)) return false; TemplateDeductionInfo Info(Context, Loc); - if (::DeduceTemplateArguments(*this, TemplateParams, + if (::DeduceTemplateArguments(*this, &TemplateParams, FuncParam, InitType, Info, Deduced, TDF)) return false; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp index 44f5913..ae0ac9c 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2140,6 +2140,17 @@ Sema::SubstNestedNameSpecifier(NestedNameSpecifier *NNS, return Instantiator.TransformNestedNameSpecifier(NNS, Range); } +NestedNameSpecifierLoc +Sema::SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, + const MultiLevelTemplateArgumentList &TemplateArgs) { + if (!NNS) + return NestedNameSpecifierLoc(); + + TemplateInstantiator Instantiator(*this, TemplateArgs, NNS.getBeginLoc(), + DeclarationName()); + return Instantiator.TransformNestedNameSpecifierLoc(NNS); +} + /// \brief Do template substitution on declaration name info. DeclarationNameInfo Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index c0150c0..3a40b6f 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -27,33 +27,33 @@ using namespace clang; bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl, DeclaratorDecl *NewDecl) { - NestedNameSpecifier *OldQual = OldDecl->getQualifier(); - if (!OldQual) return false; - - SourceRange QualRange = OldDecl->getQualifierRange(); - - NestedNameSpecifier *NewQual - = SemaRef.SubstNestedNameSpecifier(OldQual, QualRange, TemplateArgs); - if (!NewQual) + if (!OldDecl->getQualifierLoc()) + return false; + + NestedNameSpecifierLoc NewQualifierLoc + = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(), + TemplateArgs); + + if (!NewQualifierLoc) return true; - - NewDecl->setQualifierInfo(NewQual, QualRange); + + NewDecl->setQualifierInfo(NewQualifierLoc); return false; } bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl, TagDecl *NewDecl) { - NestedNameSpecifier *OldQual = OldDecl->getQualifier(); - if (!OldQual) return false; - - SourceRange QualRange = OldDecl->getQualifierRange(); - - NestedNameSpecifier *NewQual - = SemaRef.SubstNestedNameSpecifier(OldQual, QualRange, TemplateArgs); - if (!NewQual) + if (!OldDecl->getQualifierLoc()) + return false; + + NestedNameSpecifierLoc NewQualifierLoc + = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(), + TemplateArgs); + + if (!NewQualifierLoc) return true; - - NewDecl->setQualifierInfo(NewQual, QualRange); + + NewDecl->setQualifierInfo(NewQualifierLoc); return false; } @@ -120,9 +120,8 @@ TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { = NamespaceAliasDecl::Create(SemaRef.Context, Owner, D->getNamespaceLoc(), D->getAliasLoc(), - D->getNamespace()->getIdentifier(), - D->getQualifierRange(), - D->getQualifier(), + D->getIdentifier(), + D->getQualifierLoc(), D->getTargetNameLoc(), D->getNamespace()); Owner->addDecl(Inst); @@ -642,12 +641,12 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { // Instantiate the qualifier. We have to do this first in case // we're a friend declaration, because if we are then we need to put // the new declaration in the appropriate context. - NestedNameSpecifier *Qualifier = Pattern->getQualifier(); - if (Qualifier) { - Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier, - Pattern->getQualifierRange(), - TemplateArgs); - if (!Qualifier) return 0; + NestedNameSpecifierLoc QualifierLoc = Pattern->getQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, + TemplateArgs); + if (!QualifierLoc) + return 0; } CXXRecordDecl *PrevDecl = 0; @@ -668,10 +667,9 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { // the appropriate context. DeclContext *DC = Owner; if (isFriend) { - if (Qualifier) { + if (QualifierLoc) { CXXScopeSpec SS; - SS.setScopeRep(Qualifier); - SS.setRange(Pattern->getQualifierRange()); + SS.Adopt(QualifierLoc); DC = SemaRef.computeDeclContext(SS); if (!DC) return 0; } else { @@ -692,10 +690,10 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { PrevDecl = PrevClassTemplate->getTemplatedDecl(); } - if (!PrevClassTemplate && Qualifier) { + if (!PrevClassTemplate && QualifierLoc) { SemaRef.Diag(Pattern->getLocation(), diag::err_not_tag_in_scope) << D->getTemplatedDecl()->getTagKind() << Pattern->getDeclName() << DC - << Pattern->getQualifierRange(); + << QualifierLoc.getSourceRange(); return 0; } @@ -756,8 +754,8 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { Pattern->getTagKeywordLoc(), PrevDecl, /*DelayTypeCreation=*/true); - if (Qualifier) - RecordInst->setQualifierInfo(Qualifier, Pattern->getQualifierRange()); + if (QualifierLoc) + RecordInst->setQualifierInfo(QualifierLoc); ClassTemplateDecl *Inst = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(), @@ -969,12 +967,12 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, return 0; QualType T = TInfo->getType(); - NestedNameSpecifier *Qualifier = D->getQualifier(); - if (Qualifier) { - Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier, - D->getQualifierRange(), - TemplateArgs); - if (!Qualifier) return 0; + NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, + TemplateArgs); + if (!QualifierLoc) + return 0; } // If we're instantiating a local function declaration, put the result @@ -982,10 +980,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, DeclContext *DC; if (D->getDeclContext()->isFunctionOrMethod()) DC = Owner; - else if (isFriend && Qualifier) { + else if (isFriend && QualifierLoc) { CXXScopeSpec SS; - SS.setScopeRep(Qualifier); - SS.setRange(D->getQualifierRange()); + SS.Adopt(QualifierLoc); DC = SemaRef.computeDeclContext(SS); if (!DC) return 0; } else { @@ -999,8 +996,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, D->getStorageClass(), D->getStorageClassAsWritten(), D->isInlineSpecified(), D->hasWrittenPrototype()); - if (Qualifier) - Function->setQualifierInfo(Qualifier, D->getQualifierRange()); + if (QualifierLoc) + Function->setQualifierInfo(QualifierLoc); DeclContext *LexicalDC = Owner; if (!isFriend && D->isOutOfLine()) { @@ -1262,20 +1259,19 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, return 0; } - NestedNameSpecifier *Qualifier = D->getQualifier(); - if (Qualifier) { - Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier, - D->getQualifierRange(), + NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgs); - if (!Qualifier) return 0; + if (!QualifierLoc) + return 0; } DeclContext *DC = Owner; if (isFriend) { - if (Qualifier) { + if (QualifierLoc) { CXXScopeSpec SS; - SS.setScopeRep(Qualifier); - SS.setRange(D->getQualifierRange()); + SS.Adopt(QualifierLoc); DC = SemaRef.computeDeclContext(SS); if (DC && SemaRef.RequireCompleteDeclContext(SS, DC)) @@ -1318,8 +1314,8 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, D->isInlineSpecified()); } - if (Qualifier) - Method->setQualifierInfo(Qualifier, D->getQualifierRange()); + if (QualifierLoc) + Method->setQualifierInfo(QualifierLoc); if (TemplateParams) { // Our resulting instantiation is actually a function template, since we @@ -1641,12 +1637,13 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl( } Decl *TemplateDeclInstantiator::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { - // Using directives are never dependent, so they require no explicit + // Using directives are never dependent (and never contain any types or + // expressions), so they require no explicit instantiation work. UsingDirectiveDecl *Inst = UsingDirectiveDecl::Create(SemaRef.Context, Owner, D->getLocation(), D->getNamespaceKeyLocation(), - D->getQualifierRange(), D->getQualifier(), + D->getQualifierLoc(), D->getIdentLocation(), D->getNominatedNamespace(), D->getCommonAncestor()); @@ -1664,12 +1661,11 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { // template struct t<int>; // Here, in using s1::f1, s1 refers to t<T>::s1; // we need to substitute for t<int>::s1. - NestedNameSpecifier *NNS = - SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameDecl(), - D->getNestedNameRange(), - TemplateArgs); - if (!NNS) - return 0; + NestedNameSpecifierLoc QualifierLoc + = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), + TemplateArgs); + if (!QualifierLoc) + return 0; // The name info is non-dependent, so no transformation // is required. @@ -1684,16 +1680,13 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { Sema::ForRedeclaration); UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner, - D->getNestedNameRange(), D->getUsingLocation(), - NNS, + QualifierLoc, NameInfo, D->isTypeName()); CXXScopeSpec SS; - SS.setScopeRep(NNS); - SS.setRange(D->getNestedNameRange()); - + SS.Adopt(QualifierLoc); if (CheckRedeclaration) { Prev.setHideTags(false); SemaRef.LookupQualifiedName(Prev, Owner); @@ -1752,16 +1745,14 @@ Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) { Decl * TemplateDeclInstantiator ::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { - NestedNameSpecifier *NNS = - SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(), - D->getTargetNestedNameRange(), - TemplateArgs); - if (!NNS) + NestedNameSpecifierLoc QualifierLoc + = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), + TemplateArgs); + if (!QualifierLoc) return 0; CXXScopeSpec SS; - SS.setRange(D->getTargetNestedNameRange()); - SS.setScopeRep(NNS); + SS.Adopt(QualifierLoc); // Since NameInfo refers to a typename, it cannot be a C++ special name. // Hence, no tranformation is required for it. @@ -1779,16 +1770,13 @@ Decl * TemplateDeclInstantiator Decl * TemplateDeclInstantiator ::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { - NestedNameSpecifier *NNS = - SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(), - D->getTargetNestedNameRange(), - TemplateArgs); - if (!NNS) + NestedNameSpecifierLoc QualifierLoc + = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), TemplateArgs); + if (!QualifierLoc) return 0; - + CXXScopeSpec SS; - SS.setRange(D->getTargetNestedNameRange()); - SS.setScopeRep(NNS); + SS.Adopt(QualifierLoc); DeclarationNameInfo NameInfo = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp index c88baa5..ba80076 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp @@ -1395,6 +1395,56 @@ QualType Sema::GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo) { return QT; } +static void DiagnoseIgnoredQualifiers(unsigned Quals, + SourceLocation ConstQualLoc, + SourceLocation VolatileQualLoc, + SourceLocation RestrictQualLoc, + Sema& S) { + std::string QualStr; + unsigned NumQuals = 0; + SourceLocation Loc; + + FixItHint ConstFixIt; + FixItHint VolatileFixIt; + FixItHint RestrictFixIt; + + // FIXME: The locations here are set kind of arbitrarily. It'd be nicer to + // find a range and grow it to encompass all the qualifiers, regardless of + // the order in which they textually appear. + if (Quals & Qualifiers::Const) { + ConstFixIt = FixItHint::CreateRemoval(ConstQualLoc); + Loc = ConstQualLoc; + ++NumQuals; + QualStr = "const"; + } + if (Quals & Qualifiers::Volatile) { + VolatileFixIt = FixItHint::CreateRemoval(VolatileQualLoc); + if (NumQuals == 0) { + Loc = VolatileQualLoc; + QualStr = "volatile"; + } else { + QualStr += " volatile"; + } + ++NumQuals; + } + if (Quals & Qualifiers::Restrict) { + RestrictFixIt = FixItHint::CreateRemoval(RestrictQualLoc); + if (NumQuals == 0) { + Loc = RestrictQualLoc; + QualStr = "restrict"; + } else { + QualStr += " restrict"; + } + ++NumQuals; + } + + assert(NumQuals > 0 && "No known qualifiers?"); + + S.Diag(Loc, diag::warn_qual_return_type) + << QualStr << NumQuals + << ConstFixIt << VolatileFixIt << RestrictFixIt; +} + /// GetTypeForDeclarator - Convert the type for the specified /// declarator to Type instances. /// @@ -1450,8 +1500,12 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, if (D.getAttributes()) distributeTypeAttrsFromDeclarator(state, T); + // C++0x [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context. + // In C++0x, a function declarator using 'auto' must have a trailing return + // type (this is checked later) and we can skip this. In other languages + // using auto, we need to check regardless. if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto && - !D.isFunctionDeclarator()) { + (!getLangOptions().CPlusPlus0x || !D.isFunctionDeclarator())) { int Error = -1; switch (D.getContext()) { @@ -1483,7 +1537,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, break; case Declarator::TypeNameContext: if (!AutoAllowedInTypeName) - Error = 8; // Generic + Error = 10; // Generic break; case Declarator::FileContext: case Declarator::BlockContext: @@ -1492,6 +1546,32 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, break; } + if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) + Error = 8; + + // In Objective-C it is an error to use 'auto' on a function declarator. + if (D.isFunctionDeclarator()) + Error = 9; + + // C++0x [dcl.spec.auto]p2: 'auto' is always fine if the declarator + // contains a trailing return type. That is only legal at the outermost + // level. Check all declarator chunks (outermost first) anyway, to give + // better diagnostics. + if (getLangOptions().CPlusPlus0x && Error != -1) { + for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { + unsigned chunkIndex = e - i - 1; + state.setCurrentChunkIndex(chunkIndex); + DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex); + if (DeclType.Kind == DeclaratorChunk::Function) { + const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; + if (FTI.TrailingReturnType) { + Error = -1; + break; + } + } + } + } + if (Error != -1) { Diag(D.getDeclSpec().getTypeSpecTypeLoc(), diag::err_auto_not_allowed) << Error; @@ -1499,7 +1579,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, D.setInvalidType(true); } } - + if (T.isNull()) return Context.getNullTypeSourceInfo(); @@ -1600,21 +1680,6 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // of the type, otherwise the argument list is (). const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; - // C99 6.7.5.3p1: The return type may not be a function or array type. - // For conversion functions, we'll diagnose this particular error later. - if ((T->isArrayType() || T->isFunctionType()) && - (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId)) { - unsigned diagID = diag::err_func_returning_array_function; - // Last processing chunk in block context means this function chunk - // represents the block. - if (chunkIndex == 0 && - D.getContext() == Declarator::BlockLiteralContext) - diagID = diag::err_block_returning_array_function; - Diag(DeclType.Loc, diagID) << T->isFunctionType() << T; - T = Context.IntTy; - D.setInvalidType(true); - } - // Check for auto functions and trailing return type and adjust the // return type accordingly. if (!D.isInvalidType()) { @@ -1627,8 +1692,13 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, T = Context.IntTy; D.setInvalidType(true); } else if (FTI.TrailingReturnType) { - if (T.hasQualifiers() || !isa<AutoType>(T)) { - // T must be exactly 'auto' at this point. See CWG issue 681. + // T must be exactly 'auto' at this point. See CWG issue 681. + if (isa<ParenType>(T)) { + Diag(D.getDeclSpec().getTypeSpecTypeLoc(), + diag::err_trailing_return_in_parens) + << T << D.getDeclSpec().getSourceRange(); + D.setInvalidType(true); + } else if (T.hasQualifiers() || !isa<AutoType>(T)) { Diag(D.getDeclSpec().getTypeSpecTypeLoc(), diag::err_trailing_return_without_auto) << T << D.getDeclSpec().getSourceRange(); @@ -1641,48 +1711,48 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, } } + // C99 6.7.5.3p1: The return type may not be a function or array type. + // For conversion functions, we'll diagnose this particular error later. + if ((T->isArrayType() || T->isFunctionType()) && + (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId)) { + unsigned diagID = diag::err_func_returning_array_function; + // Last processing chunk in block context means this function chunk + // represents the block. + if (chunkIndex == 0 && + D.getContext() == Declarator::BlockLiteralContext) + diagID = diag::err_block_returning_array_function; + Diag(DeclType.Loc, diagID) << T->isFunctionType() << T; + T = Context.IntTy; + D.setInvalidType(true); + } + // cv-qualifiers on return types are pointless except when the type is a // class type in C++. - if (T.getCVRQualifiers() && D.getDeclSpec().getTypeQualifiers() && + if (T->isPointerType() && T.getCVRQualifiers() && + (!getLangOptions().CPlusPlus || !T->isDependentType())) { + assert(chunkIndex + 1 < e && "No DeclaratorChunk for the return type?"); + DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1); + assert(ReturnTypeChunk.Kind == DeclaratorChunk::Pointer); + + DeclaratorChunk::PointerTypeInfo &PTI = ReturnTypeChunk.Ptr; + + DiagnoseIgnoredQualifiers(PTI.TypeQuals, + SourceLocation::getFromRawEncoding(PTI.ConstQualLoc), + SourceLocation::getFromRawEncoding(PTI.VolatileQualLoc), + SourceLocation::getFromRawEncoding(PTI.RestrictQualLoc), + *this); + + } else if (T.getCVRQualifiers() && D.getDeclSpec().getTypeQualifiers() && (!getLangOptions().CPlusPlus || (!T->isDependentType() && !T->isRecordType()))) { - unsigned Quals = D.getDeclSpec().getTypeQualifiers(); - std::string QualStr; - unsigned NumQuals = 0; - SourceLocation Loc; - if (Quals & Qualifiers::Const) { - Loc = D.getDeclSpec().getConstSpecLoc(); - ++NumQuals; - QualStr = "const"; - } - if (Quals & Qualifiers::Volatile) { - if (NumQuals == 0) { - Loc = D.getDeclSpec().getVolatileSpecLoc(); - QualStr = "volatile"; - } else - QualStr += " volatile"; - ++NumQuals; - } - if (Quals & Qualifiers::Restrict) { - if (NumQuals == 0) { - Loc = D.getDeclSpec().getRestrictSpecLoc(); - QualStr = "restrict"; - } else - QualStr += " restrict"; - ++NumQuals; - } - assert(NumQuals > 0 && "No known qualifiers?"); - - SemaDiagnosticBuilder DB = Diag(Loc, diag::warn_qual_return_type); - DB << QualStr << NumQuals; - if (Quals & Qualifiers::Const) - DB << FixItHint::CreateRemoval(D.getDeclSpec().getConstSpecLoc()); - if (Quals & Qualifiers::Volatile) - DB << FixItHint::CreateRemoval(D.getDeclSpec().getVolatileSpecLoc()); - if (Quals & Qualifiers::Restrict) - DB << FixItHint::CreateRemoval(D.getDeclSpec().getRestrictSpecLoc()); + + DiagnoseIgnoredQualifiers(D.getDeclSpec().getTypeQualifiers(), + D.getDeclSpec().getConstSpecLoc(), + D.getDeclSpec().getVolatileSpecLoc(), + D.getDeclSpec().getRestrictSpecLoc(), + *this); } - + if (getLangOptions().CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) { // C++ [dcl.fct]p6: // Types shall not be defined in return or parameter types. @@ -1825,6 +1895,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, break; case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: llvm_unreachable("Nested-name-specifier must name a type"); break; @@ -2047,7 +2118,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, break; } } - + if (T.isNull()) return Context.getNullTypeSourceInfo(); else if (D.isInvalidType()) diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h index 944e6a1..57a44ad 100644 --- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h +++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h @@ -385,6 +385,17 @@ public: QualType ObjectType = QualType(), NamedDecl *FirstQualifierInScope = 0); + /// \brief Transform the given nested-name-specifier with source-location + /// information. + /// + /// By default, transforms all of the types and declarations within the + /// nested-name-specifier. Subclasses may override this function to provide + /// alternate behavior. + NestedNameSpecifierLoc TransformNestedNameSpecifierLoc( + NestedNameSpecifierLoc NNS, + QualType ObjectType = QualType(), + NamedDecl *FirstQualifierInScope = 0); + /// \brief Transform the given declaration name. /// /// By default, transforms the types of conversion function, constructor, @@ -759,8 +770,7 @@ public: SourceRange NNSRange, SourceLocation IdLoc) { CXXScopeSpec SS; - SS.setScopeRep(NNS); - SS.setRange(NNSRange); + SS.MakeTrivial(SemaRef.Context, NNS, NNSRange); if (NNS->isDependent()) { // If the name is still dependent, just build a new dependent name type. @@ -878,6 +888,16 @@ public: NamespaceDecl *NS); /// \brief Build a new nested-name-specifier given the prefix and the + /// namespace alias named in the next step in the nested-name-specifier. + /// + /// By default, performs semantic analysis when building the new + /// nested-name-specifier. Subclasses may override this routine to provide + /// different behavior. + NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, + SourceRange Range, + NamespaceAliasDecl *Alias); + + /// \brief Build a new nested-name-specifier given the prefix and the /// type named in the next step in the nested-name-specifier. /// /// By default, performs semantic analysis when building the new @@ -1083,11 +1103,8 @@ public: StmtResult RebuildDeclStmt(Decl **Decls, unsigned NumDecls, SourceLocation StartLoc, SourceLocation EndLoc) { - return getSema().Owned( - new (getSema().Context) DeclStmt( - DeclGroupRef::Create(getSema().Context, - Decls, NumDecls), - StartLoc, EndLoc)); + Sema::DeclGroupPtrTy DG = getSema().BuildDeclaratorGroup(Decls, NumDecls); + return getSema().ActOnDeclStmt(DG, StartLoc, EndLoc); } /// \brief Build a new inline asm statement. @@ -1246,8 +1263,7 @@ public: const DeclarationNameInfo &NameInfo, TemplateArgumentListInfo *TemplateArgs) { CXXScopeSpec SS; - SS.setScopeRep(Qualifier); - SS.setRange(QualifierRange); + SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange); // FIXME: loses template args. @@ -1268,13 +1284,12 @@ public: /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. ExprResult RebuildCXXPseudoDestructorExpr(Expr *Base, - SourceLocation OperatorLoc, - bool isArrow, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - TypeSourceInfo *ScopeType, - SourceLocation CCLoc, - SourceLocation TildeLoc, + SourceLocation OperatorLoc, + bool isArrow, + CXXScopeSpec &SS, + TypeSourceInfo *ScopeType, + SourceLocation CCLoc, + SourceLocation TildeLoc, PseudoDestructorTypeStorage Destroyed); /// \brief Build a new unary operator expression. @@ -1386,8 +1401,7 @@ public: CXXScopeSpec SS; if (Qualifier) { - SS.setRange(QualifierRange); - SS.setScopeRep(Qualifier); + SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange); } getSema().DefaultFunctionArrayConversion(Base); @@ -1873,13 +1887,12 @@ public: /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - ExprResult RebuildDependentScopeDeclRefExpr(NestedNameSpecifier *NNS, - SourceRange QualifierRange, + ExprResult RebuildDependentScopeDeclRefExpr( + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs) { CXXScopeSpec SS; - SS.setRange(QualifierRange); - SS.setScopeRep(NNS); + SS.Adopt(QualifierLoc); if (TemplateArgs) return getSema().BuildQualifiedTemplateIdExpr(SS, NameInfo, @@ -1964,8 +1977,7 @@ public: const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs) { CXXScopeSpec SS; - SS.setRange(QualifierRange); - SS.setScopeRep(Qualifier); + SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange); return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType, OperatorLoc, IsArrow, @@ -1988,8 +2000,7 @@ public: LookupResult &R, const TemplateArgumentListInfo *TemplateArgs) { CXXScopeSpec SS; - SS.setRange(QualifierRange); - SS.setScopeRep(Qualifier); + SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange); return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType, OperatorLoc, IsArrow, @@ -2263,6 +2274,11 @@ private: QualType ObjectType, NamedDecl *FirstQualifierInScope, NestedNameSpecifier *Prefix); + + TypeLoc TransformTypeInObjectScope(TypeLoc TL, + QualType ObjectType, + NamedDecl *FirstQualifierInScope, + CXXScopeSpec &SS); }; template<typename Derived> @@ -2459,6 +2475,19 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS, return getDerived().RebuildNestedNameSpecifier(Prefix, Range, NS); } + case NestedNameSpecifier::NamespaceAlias: { + NamespaceAliasDecl *Alias + = cast_or_null<NamespaceAliasDecl>( + getDerived().TransformDecl(Range.getBegin(), + NNS->getAsNamespaceAlias())); + if (!getDerived().AlwaysRebuild() && + Prefix == NNS->getPrefix() && + Alias == NNS->getAsNamespaceAlias()) + return NNS; + + return getDerived().RebuildNestedNameSpecifier(Prefix, Range, Alias); + } + case NestedNameSpecifier::Global: // There is no meaningful transformation that one could perform on the // global scope. @@ -2490,6 +2519,103 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS, } template<typename Derived> +NestedNameSpecifierLoc +TreeTransform<Derived>::TransformNestedNameSpecifierLoc( + NestedNameSpecifierLoc NNS, + QualType ObjectType, + NamedDecl *FirstQualifierInScope) { + llvm::SmallVector<NestedNameSpecifierLoc, 4> Qualifiers; + for (NestedNameSpecifierLoc Qualifier = NNS; Qualifier; + Qualifier = Qualifier.getPrefix()) + Qualifiers.push_back(Qualifier); + + CXXScopeSpec SS; + while (!Qualifiers.empty()) { + NestedNameSpecifierLoc Q = Qualifiers.pop_back_val(); + NestedNameSpecifier *QNNS = Q.getNestedNameSpecifier(); + + switch (QNNS->getKind()) { + case NestedNameSpecifier::Identifier: + if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/0, + *QNNS->getAsIdentifier(), + Q.getLocalBeginLoc(), + Q.getLocalEndLoc(), + ObjectType, false, SS, + FirstQualifierInScope, false)) + return NestedNameSpecifierLoc(); + + break; + + case NestedNameSpecifier::Namespace: { + NamespaceDecl *NS + = cast_or_null<NamespaceDecl>( + getDerived().TransformDecl( + Q.getLocalBeginLoc(), + QNNS->getAsNamespace())); + SS.Extend(SemaRef.Context, NS, Q.getLocalBeginLoc(), Q.getLocalEndLoc()); + break; + } + + case NestedNameSpecifier::NamespaceAlias: { + NamespaceAliasDecl *Alias + = cast_or_null<NamespaceAliasDecl>( + getDerived().TransformDecl(Q.getLocalBeginLoc(), + QNNS->getAsNamespaceAlias())); + SS.Extend(SemaRef.Context, Alias, Q.getLocalBeginLoc(), + Q.getLocalEndLoc()); + break; + } + + case NestedNameSpecifier::Global: + // There is no meaningful transformation that one could perform on the + // global scope. + SS.MakeGlobal(SemaRef.Context, Q.getBeginLoc()); + break; + + case NestedNameSpecifier::TypeSpecWithTemplate: + case NestedNameSpecifier::TypeSpec: { + TypeLoc TL = TransformTypeInObjectScope(Q.getTypeLoc(), ObjectType, + FirstQualifierInScope, SS); + + if (!TL) + return NestedNameSpecifierLoc(); + + if (TL.getType()->isDependentType() || TL.getType()->isRecordType() || + (SemaRef.getLangOptions().CPlusPlus0x && + TL.getType()->isEnumeralType())) { + assert(!TL.getType().hasLocalQualifiers() && + "Can't get cv-qualifiers here"); + SS.Extend(SemaRef.Context, /*FIXME:*/SourceLocation(), TL, + Q.getLocalEndLoc()); + break; + } + + SemaRef.Diag(TL.getBeginLoc(), diag::err_nested_name_spec_non_tag) + << TL.getType() << SS.getRange(); + return NestedNameSpecifierLoc(); + } + } + + // The qualifier-in-scope only applies to the leftmost entity. + FirstQualifierInScope = 0; + } + + // Don't rebuild the nested-name-specifier if we don't have to. + if (SS.getScopeRep() == NNS.getNestedNameSpecifier() && + !getDerived().AlwaysRebuild()) + return NNS; + + // If we can re-use the source-location data from the original + // nested-name-specifier, do so. + if (SS.location_size() == NNS.getDataLength() && + memcmp(SS.location_data(), NNS.getOpaqueData(), SS.location_size()) == 0) + return NestedNameSpecifierLoc(SS.getScopeRep(), NNS.getOpaqueData()); + + // Allocate new nested-name-specifier location information. + return SS.getWithLocInContext(SemaRef.Context); +} + +template<typename Derived> DeclarationNameInfo TreeTransform<Derived> ::TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo) { @@ -3085,7 +3211,7 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSI, QualType ObjectType, NamedDecl *UnqualLookup, NestedNameSpecifier *Prefix) { - // TODO: in some cases, we might be some verification to do here. + // TODO: in some cases, we might have some verification to do here. if (ObjectType.isNull()) return getDerived().TransformType(TSI); @@ -3122,6 +3248,62 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSI, return TLB.getTypeSourceInfo(SemaRef.Context, Result); } +template<typename Derived> +TypeLoc +TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL, + QualType ObjectType, + NamedDecl *UnqualLookup, + CXXScopeSpec &SS) { + // FIXME: Painfully copy-paste from the above! + + // TODO: in some cases, we might have some verification to do here. + if (ObjectType.isNull()) { + TypeLocBuilder TLB; + TLB.reserve(TL.getFullDataSize()); + QualType Result = getDerived().TransformType(TLB, TL); + if (Result.isNull()) + return TypeLoc(); + + return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc(); + } + + QualType T = TL.getType(); + if (getDerived().AlreadyTransformed(T)) + return TL; + + TypeLocBuilder TLB; + QualType Result; + + if (isa<TemplateSpecializationType>(T)) { + TemplateSpecializationTypeLoc SpecTL + = cast<TemplateSpecializationTypeLoc>(TL); + + TemplateName Template = + getDerived().TransformTemplateName(SpecTL.getTypePtr()->getTemplateName(), + ObjectType, UnqualLookup); + if (Template.isNull()) + return TypeLoc(); + + Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL, + Template); + } else if (isa<DependentTemplateSpecializationType>(T)) { + DependentTemplateSpecializationTypeLoc SpecTL + = cast<DependentTemplateSpecializationTypeLoc>(TL); + + Result = getDerived().TransformDependentTemplateSpecializationType(TLB, + SpecTL, + SS.getScopeRep()); + } else { + // Nothing special needs to be done for these. + Result = getDerived().TransformType(TLB, TL); + } + + if (Result.isNull()) + return TypeLoc(); + + return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc(); +} + template <class TyLoc> static inline QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) { TyLoc NewT = TLB.push<TyLoc>(T.getType()); @@ -4337,7 +4519,8 @@ QualType TreeTransform<Derived>:: TemplateArgumentListInfo NewTemplateArgs; NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc()); NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc()); - + + // FIXME: Nested-name-specifier source location info! typedef TemplateArgumentLocContainerIterator< DependentTemplateSpecializationTypeLoc> ArgIterator; if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0), @@ -6426,21 +6609,22 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr( return ExprError(); QualType ObjectType = ObjectTypePtr.get(); - NestedNameSpecifier *Qualifier = E->getQualifier(); - if (Qualifier) { - Qualifier - = getDerived().TransformNestedNameSpecifier(E->getQualifier(), - E->getQualifierRange(), - ObjectType); - if (!Qualifier) + NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc(); + if (QualifierLoc) { + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc, ObjectType); + if (!QualifierLoc) return ExprError(); } + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); PseudoDestructorTypeStorage Destroyed; if (E->getDestroyedTypeInfo()) { TypeSourceInfo *DestroyedTypeInfo = getDerived().TransformTypeInObjectScope(E->getDestroyedTypeInfo(), - ObjectType, 0, Qualifier); + ObjectType, 0, + QualifierLoc.getNestedNameSpecifier()); if (!DestroyedTypeInfo) return ExprError(); Destroyed = DestroyedTypeInfo; @@ -6451,12 +6635,6 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr( E->getDestroyedTypeLoc()); } else { // Look for a destructor known with the given name. - CXXScopeSpec SS; - if (Qualifier) { - SS.setScopeRep(Qualifier); - SS.setRange(E->getQualifierRange()); - } - ParsedType T = SemaRef.getDestructorName(E->getTildeLoc(), *E->getDestroyedTypeIdentifier(), E->getDestroyedTypeLoc(), @@ -6481,8 +6659,7 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr( return getDerived().RebuildCXXPseudoDestructorExpr(Base.get(), E->getOperatorLoc(), E->isArrow(), - Qualifier, - E->getQualifierRange(), + SS, ScopeTypeInfo, E->getColonColonLoc(), E->getTildeLoc(), @@ -6538,8 +6715,7 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr( if (!Qualifier) return ExprError(); - SS.setScopeRep(Qualifier); - SS.setRange(Old->getQualifierRange()); + SS.MakeTrivial(SemaRef.Context, Qualifier, Old->getQualifierRange()); } if (Old->getNamingClass()) { @@ -6611,10 +6787,9 @@ template<typename Derived> ExprResult TreeTransform<Derived>::TransformDependentScopeDeclRefExpr( DependentScopeDeclRefExpr *E) { - NestedNameSpecifier *NNS - = getDerived().TransformNestedNameSpecifier(E->getQualifier(), - E->getQualifierRange()); - if (!NNS) + NestedNameSpecifierLoc QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc()); + if (!QualifierLoc) return ExprError(); // TODO: If this is a conversion-function-id, verify that the @@ -6628,14 +6803,13 @@ TreeTransform<Derived>::TransformDependentScopeDeclRefExpr( if (!E->hasExplicitTemplateArgs()) { if (!getDerived().AlwaysRebuild() && - NNS == E->getQualifier() && + QualifierLoc == E->getQualifierLoc() && // Note: it is sufficient to compare the Name component of NameInfo: // if name has not changed, DNLoc has not changed either. NameInfo.getName() == E->getDeclName()) return SemaRef.Owned(E); - return getDerived().RebuildDependentScopeDeclRefExpr(NNS, - E->getQualifierRange(), + return getDerived().RebuildDependentScopeDeclRefExpr(QualifierLoc, NameInfo, /*TemplateArgs*/ 0); } @@ -6646,8 +6820,7 @@ TreeTransform<Derived>::TransformDependentScopeDeclRefExpr( TransArgs)) return ExprError(); - return getDerived().RebuildDependentScopeDeclRefExpr(NNS, - E->getQualifierRange(), + return getDerived().RebuildDependentScopeDeclRefExpr(QualifierLoc, NameInfo, &TransArgs); } @@ -7560,14 +7733,15 @@ TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, NamedDecl *FirstQualifierInScope) { CXXScopeSpec SS; // FIXME: The source location information is all wrong. - SS.setRange(Range); - SS.setScopeRep(Prefix); - return static_cast<NestedNameSpecifier *>( - SemaRef.BuildCXXNestedNameSpecifier(0, SS, Range.getEnd(), - Range.getEnd(), II, - ObjectType, - FirstQualifierInScope, - false, false)); + SS.MakeTrivial(SemaRef.Context, Prefix, Range); + if (SemaRef.BuildCXXNestedNameSpecifier(0, II, /*FIXME:*/Range.getBegin(), + /*FIXME:*/Range.getEnd(), + ObjectType, false, + SS, FirstQualifierInScope, + false)) + return 0; + + return SS.getScopeRep(); } template<typename Derived> @@ -7582,6 +7756,14 @@ template<typename Derived> NestedNameSpecifier * TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, SourceRange Range, + NamespaceAliasDecl *Alias) { + return NestedNameSpecifier::Create(SemaRef.Context, Prefix, Alias); +} + +template<typename Derived> +NestedNameSpecifier * +TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, + SourceRange Range, bool TemplateKW, QualType T) { if (T->isDependentType() || T->isRecordType() || @@ -7612,8 +7794,7 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier, QualType ObjectType, NamedDecl *FirstQualifierInScope) { CXXScopeSpec SS; - SS.setRange(QualifierRange); - SS.setScopeRep(Qualifier); + SS.MakeTrivial(SemaRef.Context, Qualifier, QualifierRange); UnqualifiedId Name; Name.setIdentifier(&II, /*FIXME:*/getDerived().getBaseLocation()); Sema::TemplateTy Template; @@ -7633,8 +7814,7 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier, OverloadedOperatorKind Operator, QualType ObjectType) { CXXScopeSpec SS; - SS.setRange(SourceRange(getDerived().getBaseLocation())); - SS.setScopeRep(Qualifier); + SS.MakeTrivial(SemaRef.Context, Qualifier, SourceRange(getDerived().getBaseLocation())); UnqualifiedId Name; SourceLocation SymbolLocations[3]; // FIXME: Bogus location information. Name.setOperatorFunctionId(/*FIXME:*/getDerived().getBaseLocation(), @@ -7740,18 +7920,11 @@ ExprResult TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base, SourceLocation OperatorLoc, bool isArrow, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + CXXScopeSpec &SS, TypeSourceInfo *ScopeType, SourceLocation CCLoc, SourceLocation TildeLoc, PseudoDestructorTypeStorage Destroyed) { - CXXScopeSpec SS; - if (Qualifier) { - SS.setRange(QualifierRange); - SS.setScopeRep(Qualifier); - } - QualType BaseType = Base->getType(); if (Base->isTypeDependent() || Destroyed.getIdentifier() || (!isArrow && !BaseType->getAs<RecordType>()) || diff --git a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h index 3d20a52..1e0a7c4 100644 --- a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h +++ b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h @@ -107,6 +107,19 @@ class TypeLocBuilder { return DI; } + /// \brief Copies the type-location information to the given AST context and + /// returns a \c TypeLoc referring into the AST context. + TypeLoc getTypeLocInContext(ASTContext &Context, QualType T) { +#ifndef NDEBUG + assert(T == LastTy && "type doesn't match last type pushed!"); +#endif + + size_t FullDataSize = Capacity - Index; + void *Mem = Context.Allocate(FullDataSize); + memcpy(Mem, &Buffer[Index], FullDataSize); + return TypeLoc(T, Mem); + } + private: TypeLoc pushImpl(QualType T, size_t LocalSize) { #ifndef NDEBUG diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp index ce87b11..c3953ba 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReader.cpp @@ -97,8 +97,9 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { diag::warn_pch_lax_vector_conversions); PARSE_LANGOPT_IMPORTANT(AltiVec, diag::warn_pch_altivec); PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions); - PARSE_LANGOPT_IMPORTANT(SjLjExceptions, diag::warn_pch_sjlj_exceptions); PARSE_LANGOPT_IMPORTANT(ObjCExceptions, diag::warn_pch_objc_exceptions); + PARSE_LANGOPT_IMPORTANT(CXXExceptions, diag::warn_pch_cxx_exceptions); + PARSE_LANGOPT_IMPORTANT(SjLjExceptions, diag::warn_pch_sjlj_exceptions); PARSE_LANGOPT_IMPORTANT(MSBitfields, diag::warn_pch_ms_bitfields); PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime); PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding); @@ -243,14 +244,15 @@ FindMacro(const PCHPredefinesBlocks &Buffers, llvm::StringRef MacroDef) { bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, llvm::StringRef OriginalFileName, - std::string &SuggestedPredefines) { + std::string &SuggestedPredefines, + FileManager &FileMgr) { // We are in the context of an implicit include, so the predefines buffer will // have a #include entry for the PCH file itself (as normalized by the // preprocessor initialization). Find it and skip over it in the checking // below. llvm::SmallString<256> PCHInclude; PCHInclude += "#include \""; - PCHInclude += NormalizeDashIncludePath(OriginalFileName); + PCHInclude += NormalizeDashIncludePath(OriginalFileName, FileMgr); PCHInclude += "\"\n"; std::pair<llvm::StringRef,llvm::StringRef> Split = llvm::StringRef(PP.getPredefines()).split(PCHInclude.str()); @@ -960,7 +962,8 @@ bool ASTReader::CheckPredefinesBuffers() { if (Listener) return Listener->ReadPredefinesBuffer(PCHPredefinesBuffers, ActualOriginalFileName, - SuggestedPredefines); + SuggestedPredefines, + FileMgr); return false; } @@ -2799,8 +2802,9 @@ bool ASTReader::ParseLanguageOptions( PARSE_LANGOPT(LaxVectorConversions); PARSE_LANGOPT(AltiVec); PARSE_LANGOPT(Exceptions); - PARSE_LANGOPT(SjLjExceptions); PARSE_LANGOPT(ObjCExceptions); + PARSE_LANGOPT(CXXExceptions); + PARSE_LANGOPT(SjLjExceptions); PARSE_LANGOPT(MSBitfields); PARSE_LANGOPT(NeXTRuntime); PARSE_LANGOPT(Freestanding); @@ -4476,8 +4480,7 @@ void ASTReader::ReadDeclarationNameInfo(PerFileData &F, void ASTReader::ReadQualifierInfo(PerFileData &F, QualifierInfo &Info, const RecordData &Record, unsigned &Idx) { - Info.NNS = ReadNestedNameSpecifier(Record, Idx); - Info.NNSRange = ReadSourceRange(F, Record, Idx); + Info.QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, Idx); unsigned NumTPLists = Record[Idx++]; Info.NumTemplParamLists = NumTPLists; if (NumTPLists) { @@ -4726,6 +4729,13 @@ ASTReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) { break; } + case NestedNameSpecifier::NamespaceAlias: { + NamespaceAliasDecl *Alias + = cast<NamespaceAliasDecl>(GetDecl(Record[Idx++])); + NNS = NestedNameSpecifier::Create(*Context, Prev, Alias); + break; + } + case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: { const Type *T = GetType(Record[Idx++]).getTypePtrOrNull(); @@ -4748,6 +4758,109 @@ ASTReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) { return NNS; } +NestedNameSpecifierLoc +ASTReader::ReadNestedNameSpecifierLoc(PerFileData &F, const RecordData &Record, + unsigned &Idx) { + unsigned N = Record[Idx++]; + NestedNameSpecifier *NNS = 0, *Prev = 0; + llvm::SmallVector<char, 32> LocationData; + for (unsigned I = 0; I != N; ++I) { + NestedNameSpecifier::SpecifierKind Kind + = (NestedNameSpecifier::SpecifierKind)Record[Idx++]; + switch (Kind) { + case NestedNameSpecifier::Identifier: { + // Nested-name-specifier + IdentifierInfo *II = GetIdentifierInfo(Record, Idx); + NNS = NestedNameSpecifier::Create(*Context, Prev, II); + + // Location information + SourceRange Range = ReadSourceRange(F, Record, Idx); + unsigned RawStart = Range.getBegin().getRawEncoding(); + unsigned RawEnd = Range.getEnd().getRawEncoding(); + LocationData.append(reinterpret_cast<char*>(&RawStart), + reinterpret_cast<char*>(&RawStart) +sizeof(unsigned)); + LocationData.append(reinterpret_cast<char*>(&RawEnd), + reinterpret_cast<char*>(&RawEnd) + sizeof(unsigned)); + break; + } + + case NestedNameSpecifier::Namespace: { + // Nested-name-specifier + NamespaceDecl *NS = cast<NamespaceDecl>(GetDecl(Record[Idx++])); + NNS = NestedNameSpecifier::Create(*Context, Prev, NS); + + // Location information + SourceRange Range = ReadSourceRange(F, Record, Idx); + unsigned RawStart = Range.getBegin().getRawEncoding(); + unsigned RawEnd = Range.getEnd().getRawEncoding(); + LocationData.append(reinterpret_cast<char*>(&RawStart), + reinterpret_cast<char*>(&RawStart) +sizeof(unsigned)); + LocationData.append(reinterpret_cast<char*>(&RawEnd), + reinterpret_cast<char*>(&RawEnd) + sizeof(unsigned)); + break; + } + + case NestedNameSpecifier::NamespaceAlias: { + // Nested-name-specifier + NamespaceAliasDecl *Alias + = cast<NamespaceAliasDecl>(GetDecl(Record[Idx++])); + NNS = NestedNameSpecifier::Create(*Context, Prev, Alias); + + // Location information + SourceRange Range = ReadSourceRange(F, Record, Idx); + unsigned RawStart = Range.getBegin().getRawEncoding(); + unsigned RawEnd = Range.getEnd().getRawEncoding(); + LocationData.append(reinterpret_cast<char*>(&RawStart), + reinterpret_cast<char*>(&RawStart) +sizeof(unsigned)); + LocationData.append(reinterpret_cast<char*>(&RawEnd), + reinterpret_cast<char*>(&RawEnd) + sizeof(unsigned)); + + break; + } + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: { + // Nested-name-specifier + bool Template = Record[Idx++]; + TypeSourceInfo *T = GetTypeSourceInfo(F, Record, Idx); + if (!T) + return NestedNameSpecifierLoc(); + NNS = NestedNameSpecifier::Create(*Context, Prev, Template, + T->getType().getTypePtr()); + + // Location information. + SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx); + unsigned RawLocation = ColonColonLoc.getRawEncoding(); + void *OpaqueTypeData = T->getTypeLoc().getOpaqueData(); + LocationData.append(reinterpret_cast<char*>(&OpaqueTypeData), + (reinterpret_cast<char*>(&OpaqueTypeData) + + sizeof(void *))); + LocationData.append(reinterpret_cast<char*>(&RawLocation), + (reinterpret_cast<char*>(&RawLocation) + + sizeof(unsigned))); + break; + } + + case NestedNameSpecifier::Global: { + // Nested-name-specifier + NNS = NestedNameSpecifier::GlobalSpecifier(*Context); + + SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx); + unsigned RawLocation = ColonColonLoc.getRawEncoding(); + LocationData.append(reinterpret_cast<char*>(&RawLocation), + (reinterpret_cast<char*>(&RawLocation) + + sizeof(unsigned))); + break; + } + } + Prev = NNS; + } + + void *Mem = Context->Allocate(LocationData.size(), llvm::alignOf<void*>()); + memcpy(Mem, LocationData.data(), LocationData.size()); + return NestedNameSpecifierLoc(NNS, Mem); +} + SourceRange ASTReader::ReadSourceRange(PerFileData &F, const RecordData &Record, unsigned &Idx) { @@ -4932,4 +5045,3 @@ ASTReader::PerFileData::~PerFileData() { delete static_cast<HeaderFileInfoLookupTable *>(HeaderFileInfoTable); delete static_cast<ASTSelectorLookupTable *>(SelectorLookupTable); } - diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp index dec15dd..493ccba 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp @@ -744,17 +744,15 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { VisitNamedDecl(D); D->NamespaceLoc = ReadSourceLocation(Record, Idx); - D->setQualifierRange(ReadSourceRange(Record, Idx)); - D->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); D->IdentLoc = ReadSourceLocation(Record, Idx); + D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); D->Namespace = cast<NamedDecl>(Reader.GetDecl(Record[Idx++])); } void ASTDeclReader::VisitUsingDecl(UsingDecl *D) { VisitNamedDecl(D); D->setUsingLocation(ReadSourceLocation(Record, Idx)); - D->setNestedNameRange(ReadSourceRange(Record, Idx)); - D->setTargetNestedNameDecl(Reader.ReadNestedNameSpecifier(Record, Idx)); + D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx); D->FirstUsingShadow = cast_or_null<UsingShadowDecl>(Reader.GetDecl(Record[Idx++])); D->setTypeName(Record[Idx++]); @@ -777,27 +775,24 @@ void ASTDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { VisitNamedDecl(D); D->UsingLoc = ReadSourceLocation(Record, Idx); D->NamespaceLoc = ReadSourceLocation(Record, Idx); - D->QualifierRange = ReadSourceRange(Record, Idx); - D->Qualifier = Reader.ReadNestedNameSpecifier(Record, Idx); + D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); D->NominatedNamespace = cast<NamedDecl>(Reader.GetDecl(Record[Idx++])); D->CommonAncestor = cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])); } void ASTDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { VisitValueDecl(D); - D->setTargetNestedNameRange(ReadSourceRange(Record, Idx)); D->setUsingLoc(ReadSourceLocation(Record, Idx)); - D->setTargetNestedNameSpecifier(Reader.ReadNestedNameSpecifier(Record, Idx)); + D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx); } void ASTDeclReader::VisitUnresolvedUsingTypenameDecl( UnresolvedUsingTypenameDecl *D) { VisitTypeDecl(D); - D->TargetNestedNameRange = ReadSourceRange(Record, Idx); D->UsingLocation = ReadSourceLocation(Record, Idx); D->TypenameLocation = ReadSourceLocation(Record, Idx); - D->TargetNestedNameSpecifier = Reader.ReadNestedNameSpecifier(Record, Idx); + D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); } void ASTDeclReader::ReadCXXDefinitionData( @@ -1432,30 +1427,33 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { break; case DECL_NAMESPACE_ALIAS: D = NamespaceAliasDecl::Create(*Context, 0, SourceLocation(), - SourceLocation(), 0, SourceRange(), 0, + SourceLocation(), 0, + NestedNameSpecifierLoc(), SourceLocation(), 0); break; case DECL_USING: - D = UsingDecl::Create(*Context, 0, SourceRange(), SourceLocation(), - 0, DeclarationNameInfo(), false); + D = UsingDecl::Create(*Context, 0, SourceLocation(), + NestedNameSpecifierLoc(), DeclarationNameInfo(), + false); break; case DECL_USING_SHADOW: D = UsingShadowDecl::Create(*Context, 0, SourceLocation(), 0, 0); break; case DECL_USING_DIRECTIVE: D = UsingDirectiveDecl::Create(*Context, 0, SourceLocation(), - SourceLocation(), SourceRange(), 0, + SourceLocation(), NestedNameSpecifierLoc(), SourceLocation(), 0, 0); break; case DECL_UNRESOLVED_USING_VALUE: D = UnresolvedUsingValueDecl::Create(*Context, 0, SourceLocation(), - SourceRange(), 0, + NestedNameSpecifierLoc(), DeclarationNameInfo()); break; case DECL_UNRESOLVED_USING_TYPENAME: D = UnresolvedUsingTypenameDecl::Create(*Context, 0, SourceLocation(), - SourceLocation(), SourceRange(), - 0, SourceLocation(), + SourceLocation(), + NestedNameSpecifierLoc(), + SourceLocation(), DeclarationName()); break; case DECL_CXX_RECORD: diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp index 4e91c98..42f0b1a 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1167,14 +1167,13 @@ void ASTStmtReader::VisitCXXDeleteExpr(CXXDeleteExpr *E) { void ASTStmtReader::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { VisitExpr(E); - E->setBase(Reader.ReadSubExpr()); - E->setArrow(Record[Idx++]); - E->setOperatorLoc(ReadSourceLocation(Record, Idx)); - E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); - E->setQualifierRange(ReadSourceRange(Record, Idx)); - E->setScopeTypeInfo(GetTypeSourceInfo(Record, Idx)); - E->setColonColonLoc(ReadSourceLocation(Record, Idx)); - E->setTildeLoc(ReadSourceLocation(Record, Idx)); + E->Base = Reader.ReadSubExpr(); + E->IsArrow = Record[Idx++]; + E->OperatorLoc = ReadSourceLocation(Record, Idx); + E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); + E->ScopeType = GetTypeSourceInfo(Record, Idx); + E->ColonColonLoc = ReadSourceLocation(Record, Idx); + E->TildeLoc = ReadSourceLocation(Record, Idx); IdentifierInfo *II = Reader.GetIdentifierInfo(Record, Idx); if (II) @@ -1220,10 +1219,9 @@ ASTStmtReader::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { if (Record[Idx++]) ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(), Record[Idx++]); - + + E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); ReadDeclarationNameInfo(E->NameInfo, Record, Idx); - E->setQualifierRange(ReadSourceRange(Record, Idx)); - E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); } void diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp index 8fcb535..383ca3d 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp @@ -1023,8 +1023,9 @@ void ASTWriter::WriteLanguageOptions(const LangOptions &LangOpts) { Record.push_back(LangOpts.LaxVectorConversions); Record.push_back(LangOpts.AltiVec); Record.push_back(LangOpts.Exceptions); // Support exception handling. - Record.push_back(LangOpts.SjLjExceptions); Record.push_back(LangOpts.ObjCExceptions); + Record.push_back(LangOpts.CXXExceptions); + Record.push_back(LangOpts.SjLjExceptions); Record.push_back(LangOpts.MSBitfields); // MS-compatible structure layout Record.push_back(LangOpts.NeXTRuntime); // Use NeXT runtime. @@ -3275,15 +3276,21 @@ void ASTWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg, Record); } -void ASTWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordDataImpl &Record) { +void ASTWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo, + RecordDataImpl &Record) { if (TInfo == 0) { AddTypeRef(QualType(), Record); return; } - AddTypeRef(TInfo->getType(), Record); + AddTypeLoc(TInfo->getTypeLoc(), Record); +} + +void ASTWriter::AddTypeLoc(TypeLoc TL, RecordDataImpl &Record) { + AddTypeRef(TL.getType(), Record); + TypeLocWriter TLW(*this, Record); - for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc()) + for (; !TL.isNull(); TL = TL.getNextTypeLoc()) TLW.Visit(TL); } @@ -3436,8 +3443,7 @@ void ASTWriter::AddDeclarationNameInfo(const DeclarationNameInfo &NameInfo, void ASTWriter::AddQualifierInfo(const QualifierInfo &Info, RecordDataImpl &Record) { - AddNestedNameSpecifier(Info.NNS, Record); - AddSourceRange(Info.NNSRange, Record); + AddNestedNameSpecifierLoc(Info.QualifierLoc, Record); Record.push_back(Info.NumTemplParamLists); for (unsigned i=0, e=Info.NumTemplParamLists; i != e; ++i) AddTemplateParameterList(Info.TemplParamLists[i], Record); @@ -3469,6 +3475,10 @@ void ASTWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS, AddDeclRef(NNS->getAsNamespace(), Record); break; + case NestedNameSpecifier::NamespaceAlias: + AddDeclRef(NNS->getAsNamespaceAlias(), Record); + break; + case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: AddTypeRef(QualType(NNS->getAsType(), 0), Record); @@ -3482,6 +3492,55 @@ void ASTWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS, } } +void ASTWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, + RecordDataImpl &Record) { + // Nested name specifiers usually aren't too long. I think that 8 would + // typically accomodate the vast majority. + llvm::SmallVector<NestedNameSpecifierLoc , 8> NestedNames; + + // Push each of the nested-name-specifiers's onto a stack for + // serialization in reverse order. + while (NNS) { + NestedNames.push_back(NNS); + NNS = NNS.getPrefix(); + } + + Record.push_back(NestedNames.size()); + while(!NestedNames.empty()) { + NNS = NestedNames.pop_back_val(); + NestedNameSpecifier::SpecifierKind Kind + = NNS.getNestedNameSpecifier()->getKind(); + Record.push_back(Kind); + switch (Kind) { + case NestedNameSpecifier::Identifier: + AddIdentifierRef(NNS.getNestedNameSpecifier()->getAsIdentifier(), Record); + AddSourceRange(NNS.getLocalSourceRange(), Record); + break; + + case NestedNameSpecifier::Namespace: + AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespace(), Record); + AddSourceRange(NNS.getLocalSourceRange(), Record); + break; + + case NestedNameSpecifier::NamespaceAlias: + AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespaceAlias(), Record); + AddSourceRange(NNS.getLocalSourceRange(), Record); + break; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + Record.push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate); + AddTypeLoc(NNS.getTypeLoc(), Record); + AddSourceLocation(NNS.getLocalSourceRange().getEnd(), Record); + break; + + case NestedNameSpecifier::Global: + AddSourceLocation(NNS.getLocalSourceRange().getEnd(), Record); + break; + } + } +} + void ASTWriter::AddTemplateName(TemplateName Name, RecordDataImpl &Record) { TemplateName::NameKind Kind = Name.getKind(); Record.push_back(Kind); diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp index ce07e138..12d1226 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterDecl.cpp @@ -697,18 +697,16 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { void ASTDeclWriter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { VisitNamedDecl(D); Writer.AddSourceLocation(D->getNamespaceLoc(), Record); - Writer.AddSourceRange(D->getQualifierRange(), Record); - Writer.AddNestedNameSpecifier(D->getQualifier(), Record); Writer.AddSourceLocation(D->getTargetNameLoc(), Record); + Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record); Writer.AddDeclRef(D->getNamespace(), Record); Code = serialization::DECL_NAMESPACE_ALIAS; } void ASTDeclWriter::VisitUsingDecl(UsingDecl *D) { VisitNamedDecl(D); - Writer.AddSourceRange(D->getNestedNameRange(), Record); Writer.AddSourceLocation(D->getUsingLocation(), Record); - Writer.AddNestedNameSpecifier(D->getTargetNestedNameDecl(), Record); + Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record); Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record); Writer.AddDeclRef(D->FirstUsingShadow, Record); Record.push_back(D->isTypeName()); @@ -728,8 +726,7 @@ void ASTDeclWriter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { VisitNamedDecl(D); Writer.AddSourceLocation(D->getUsingLoc(), Record); Writer.AddSourceLocation(D->getNamespaceKeyLocation(), Record); - Writer.AddSourceRange(D->getQualifierRange(), Record); - Writer.AddNestedNameSpecifier(D->getQualifier(), Record); + Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record); Writer.AddDeclRef(D->getNominatedNamespace(), Record); Writer.AddDeclRef(dyn_cast<Decl>(D->getCommonAncestor()), Record); Code = serialization::DECL_USING_DIRECTIVE; @@ -737,9 +734,8 @@ void ASTDeclWriter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { void ASTDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { VisitValueDecl(D); - Writer.AddSourceRange(D->getTargetNestedNameRange(), Record); Writer.AddSourceLocation(D->getUsingLoc(), Record); - Writer.AddNestedNameSpecifier(D->getTargetNestedNameSpecifier(), Record); + Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record); Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record); Code = serialization::DECL_UNRESOLVED_USING_VALUE; } @@ -747,10 +743,9 @@ void ASTDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { void ASTDeclWriter::VisitUnresolvedUsingTypenameDecl( UnresolvedUsingTypenameDecl *D) { VisitTypeDecl(D); - Writer.AddSourceRange(D->getTargetNestedNameRange(), Record); Writer.AddSourceLocation(D->getUsingLoc(), Record); Writer.AddSourceLocation(D->getTypenameLoc(), Record); - Writer.AddNestedNameSpecifier(D->getTargetNestedNameSpecifier(), Record); + Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record); Code = serialization::DECL_UNRESOLVED_USING_TYPENAME; } diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp index 8a5ffe9..af846a9 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1150,8 +1150,7 @@ void ASTStmtWriter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { Writer.AddStmt(E->getBase()); Record.push_back(E->isArrow()); Writer.AddSourceLocation(E->getOperatorLoc(), Record); - Writer.AddNestedNameSpecifier(E->getQualifier(), Record); - Writer.AddSourceRange(E->getQualifierRange(), Record); + Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record); Writer.AddTypeSourceInfo(E->getScopeTypeInfo(), Record); Writer.AddSourceLocation(E->getColonColonLoc(), Record); Writer.AddSourceLocation(E->getTildeLoc(), Record); @@ -1217,9 +1216,8 @@ ASTStmtWriter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { AddExplicitTemplateArgumentList(Args); } + Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record); Writer.AddDeclarationNameInfo(E->NameInfo, Record); - Writer.AddSourceRange(E->getQualifierRange(), Record); - Writer.AddNestedNameSpecifier(E->getQualifier(), Record); Code = serialization::EXPR_CXX_DEPENDENT_SCOPE_DECL_REF; } diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp index 9194791..25e224e 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp @@ -12,9 +12,11 @@ // //===----------------------------------------------------------------------===// -#include "InternalChecks.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" using namespace clang; @@ -22,21 +24,15 @@ using namespace ento; namespace { class ArrayBoundChecker : - public CheckerVisitor<ArrayBoundChecker> { - BuiltinBug *BT; + public CheckerV2<check::Location> { + mutable llvm::OwningPtr<BuiltinBug> BT; public: - ArrayBoundChecker() : BT(0) {} - static void *getTag() { static int x = 0; return &x; } - void visitLocation(CheckerContext &C, const Stmt *S, SVal l, bool isLoad); + void checkLocation(SVal l, bool isLoad, CheckerContext &C) const; }; } -void ento::RegisterArrayBoundChecker(ExprEngine &Eng) { - Eng.registerCheck(new ArrayBoundChecker()); -} - -void ArrayBoundChecker::visitLocation(CheckerContext &C, const Stmt *S, SVal l, - bool isLoad) { +void ArrayBoundChecker::checkLocation(SVal l, bool isLoad, + CheckerContext &C) const { // Check for out of bound array element access. const MemRegion *R = l.getAsRegion(); if (!R) @@ -69,8 +65,8 @@ void ArrayBoundChecker::visitLocation(CheckerContext &C, const Stmt *S, SVal l, return; if (!BT) - BT = new BuiltinBug("Out-of-bound array access", - "Access out-of-bound array element (buffer overflow)"); + BT.reset(new BuiltinBug("Out-of-bound array access", + "Access out-of-bound array element (buffer overflow)")); // FIXME: It would be nice to eventually make this diagnostic more clear, // e.g., by referencing the original declaration or by saying *why* this @@ -80,7 +76,7 @@ void ArrayBoundChecker::visitLocation(CheckerContext &C, const Stmt *S, SVal l, RangedBugReport *report = new RangedBugReport(*BT, BT->getDescription(), N); - report->addRange(S->getSourceRange()); + report->addRange(C.getStmt()->getSourceRange()); C.EmitReport(report); return; } @@ -90,3 +86,7 @@ void ArrayBoundChecker::visitLocation(CheckerContext &C, const Stmt *S, SVal l, assert(StInBound); C.addTransition(StInBound); } + +void ento::registerArrayBoundChecker(CheckerManager &mgr) { + mgr.registerChecker<ArrayBoundChecker>(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp index 1b6c528..7aff201 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -16,14 +16,14 @@ #include "BasicObjCFoundationChecks.h" #include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" #include "clang/StaticAnalyzer/Checkers/LocalCheckers.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" @@ -69,22 +69,23 @@ static inline bool isNil(SVal X) { //===----------------------------------------------------------------------===// namespace { - class NilArgChecker : public CheckerVisitor<NilArgChecker> { - APIMisuse *BT; - void WarnNilArg(CheckerContext &C, const ObjCMessage &msg, unsigned Arg); + class NilArgChecker : public CheckerV2<check::PreObjCMessage> { + mutable llvm::OwningPtr<APIMisuse> BT; + + void WarnNilArg(CheckerContext &C, + const ObjCMessage &msg, unsigned Arg) const; + public: - NilArgChecker() : BT(0) {} - static void *getTag() { static int x = 0; return &x; } - void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg); + void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const; }; } void NilArgChecker::WarnNilArg(CheckerContext &C, const ObjCMessage &msg, - unsigned int Arg) + unsigned int Arg) const { if (!BT) - BT = new APIMisuse("nil argument"); + BT.reset(new APIMisuse("nil argument")); if (ExplodedNode *N = C.generateSink()) { llvm::SmallString<128> sbuf; @@ -98,9 +99,8 @@ void NilArgChecker::WarnNilArg(CheckerContext &C, } } -void NilArgChecker::preVisitObjCMessage(CheckerContext &C, - ObjCMessage msg) -{ +void NilArgChecker::checkPreObjCMessage(ObjCMessage msg, + CheckerContext &C) const { const ObjCInterfaceType *ReceiverType = GetReceiverType(msg); if (!ReceiverType) return; @@ -140,14 +140,14 @@ void NilArgChecker::preVisitObjCMessage(CheckerContext &C, //===----------------------------------------------------------------------===// namespace { -class CFNumberCreateChecker : public CheckerVisitor<CFNumberCreateChecker> { - APIMisuse* BT; - IdentifierInfo* II; +class CFNumberCreateChecker : public CheckerV2< check::PreStmt<CallExpr> > { + mutable llvm::OwningPtr<APIMisuse> BT; + mutable IdentifierInfo* II; public: - CFNumberCreateChecker() : BT(0), II(0) {} - ~CFNumberCreateChecker() {} - static void *getTag() { static int x = 0; return &x; } - void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE); + CFNumberCreateChecker() : II(0) {} + + void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; + private: void EmitError(const TypedRegion* R, const Expr* Ex, uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind); @@ -247,9 +247,8 @@ static const char* GetCFNumberTypeStr(uint64_t i) { } #endif -void CFNumberCreateChecker::PreVisitCallExpr(CheckerContext &C, - const CallExpr *CE) -{ +void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE, + CheckerContext &C) const { const Expr* Callee = CE->getCallee(); const GRState *state = C.getState(); SVal CallV = state->getSVal(Callee); @@ -335,7 +334,7 @@ void CFNumberCreateChecker::PreVisitCallExpr(CheckerContext &C, << " bits of the input integer will be lost."; if (!BT) - BT = new APIMisuse("Bad use of CFNumberCreate"); + BT.reset(new APIMisuse("Bad use of CFNumberCreate")); RangedBugReport *report = new RangedBugReport(*BT, os.str(), N); report->addRange(CE->getArg(2)->getSourceRange()); @@ -348,19 +347,18 @@ void CFNumberCreateChecker::PreVisitCallExpr(CheckerContext &C, //===----------------------------------------------------------------------===// namespace { -class CFRetainReleaseChecker : public CheckerVisitor<CFRetainReleaseChecker> { - APIMisuse *BT; - IdentifierInfo *Retain, *Release; +class CFRetainReleaseChecker : public CheckerV2< check::PreStmt<CallExpr> > { + mutable llvm::OwningPtr<APIMisuse> BT; + mutable IdentifierInfo *Retain, *Release; public: - CFRetainReleaseChecker(): BT(0), Retain(0), Release(0) {} - static void *getTag() { static int x = 0; return &x; } - void PreVisitCallExpr(CheckerContext& C, const CallExpr* CE); + CFRetainReleaseChecker(): Retain(0), Release(0) {} + void checkPreStmt(const CallExpr* CE, CheckerContext& C) const; }; } // end anonymous namespace -void CFRetainReleaseChecker::PreVisitCallExpr(CheckerContext& C, - const CallExpr* CE) { +void CFRetainReleaseChecker::checkPreStmt(const CallExpr* CE, + CheckerContext& C) const { // If the CallExpr doesn't have exactly 1 argument just give up checking. if (CE->getNumArgs() != 1) return; @@ -377,7 +375,7 @@ void CFRetainReleaseChecker::PreVisitCallExpr(CheckerContext& C, ASTContext &Ctx = C.getASTContext(); Retain = &Ctx.Idents.get("CFRetain"); Release = &Ctx.Idents.get("CFRelease"); - BT = new APIMisuse("null passed to CFRetain/CFRelease"); + BT.reset(new APIMisuse("null passed to CFRetain/CFRelease")); } // Check if we called CFRetain/CFRelease. @@ -431,28 +429,24 @@ void CFRetainReleaseChecker::PreVisitCallExpr(CheckerContext& C, //===----------------------------------------------------------------------===// namespace { -class ClassReleaseChecker : public CheckerVisitor<ClassReleaseChecker> { - Selector releaseS; - Selector retainS; - Selector autoreleaseS; - Selector drainS; - BugType *BT; -public: - ClassReleaseChecker() - : BT(0) {} +class ClassReleaseChecker : public CheckerV2<check::PreObjCMessage> { + mutable Selector releaseS; + mutable Selector retainS; + mutable Selector autoreleaseS; + mutable Selector drainS; + mutable llvm::OwningPtr<BugType> BT; - static void *getTag() { static int x = 0; return &x; } - - void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg); +public: + void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const; }; } -void ClassReleaseChecker::preVisitObjCMessage(CheckerContext &C, - ObjCMessage msg) { +void ClassReleaseChecker::checkPreObjCMessage(ObjCMessage msg, + CheckerContext &C) const { if (!BT) { - BT = new APIMisuse("message incorrectly sent to class instead of class " - "instance"); + BT.reset(new APIMisuse("message incorrectly sent to class instead of class " + "instance")); ASTContext &Ctx = C.getASTContext(); releaseS = GetNullarySelector("release", Ctx); @@ -488,34 +482,18 @@ void ClassReleaseChecker::preVisitObjCMessage(CheckerContext &C, // Check registration. //===----------------------------------------------------------------------===// -static void RegisterNilArgChecker(ExprEngine& Eng) { - Eng.registerCheck(new NilArgChecker()); -} - void ento::registerNilArgChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterNilArgChecker); -} - -static void RegisterCFNumberCreateChecker(ExprEngine& Eng) { - Eng.registerCheck(new CFNumberCreateChecker()); + mgr.registerChecker<NilArgChecker>(); } void ento::registerCFNumberCreateChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterCFNumberCreateChecker); -} - -static void RegisterCFRetainReleaseChecker(ExprEngine& Eng) { - Eng.registerCheck(new CFRetainReleaseChecker()); + mgr.registerChecker<CFNumberCreateChecker>(); } void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterCFRetainReleaseChecker); -} - -static void RegisterClassReleaseChecker(ExprEngine& Eng) { - Eng.registerCheck(new ClassReleaseChecker()); + mgr.registerChecker<CFRetainReleaseChecker>(); } void ento::registerClassReleaseChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterClassReleaseChecker); + mgr.registerChecker<ClassReleaseChecker>(); } diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 03f9047..2566e3c 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -13,9 +13,10 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" #include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" #include "llvm/ADT/StringSwitch.h" @@ -23,75 +24,86 @@ using namespace clang; using namespace ento; namespace { -class CStringChecker : public CheckerVisitor<CStringChecker> { - BugType *BT_Null, *BT_Bounds, *BT_BoundsWrite, *BT_Overlap, *BT_NotCString; +class CStringChecker : public CheckerV2< eval::Call, + check::PreStmt<DeclStmt>, + check::LiveSymbols, + check::DeadSymbols, + check::RegionChanges + > { + mutable llvm::OwningPtr<BugType> BT_Null, BT_Bounds, BT_BoundsWrite, + BT_Overlap, BT_NotCString; public: - CStringChecker() - : BT_Null(0), BT_Bounds(0), BT_BoundsWrite(0), BT_Overlap(0), BT_NotCString(0) - {} static void *getTag() { static int tag; return &tag; } - bool evalCallExpr(CheckerContext &C, const CallExpr *CE); - void PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS); - void MarkLiveSymbols(const GRState *state, SymbolReaper &SR); - void evalDeadSymbols(CheckerContext &C, SymbolReaper &SR); - bool wantsRegionChangeUpdate(const GRState *state); + bool evalCall(const CallExpr *CE, CheckerContext &C) const; + void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const; + void checkLiveSymbols(const GRState *state, SymbolReaper &SR) const; + void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const; + bool wantsRegionChangeUpdate(const GRState *state) const; - const GRState *EvalRegionChanges(const GRState *state, - const MemRegion * const *Begin, - const MemRegion * const *End, - bool*); + const GRState *checkRegionChanges(const GRState *state, + const MemRegion * const *Begin, + const MemRegion * const *End) const; - typedef void (CStringChecker::*FnCheck)(CheckerContext &, const CallExpr *); + typedef void (CStringChecker::*FnCheck)(CheckerContext &, + const CallExpr *) const; - void evalMemcpy(CheckerContext &C, const CallExpr *CE); - void evalMemmove(CheckerContext &C, const CallExpr *CE); - void evalBcopy(CheckerContext &C, const CallExpr *CE); + void evalMemcpy(CheckerContext &C, const CallExpr *CE) const; + void evalMemmove(CheckerContext &C, const CallExpr *CE) const; + void evalBcopy(CheckerContext &C, const CallExpr *CE) const; void evalCopyCommon(CheckerContext &C, const GRState *state, const Expr *Size, const Expr *Source, const Expr *Dest, - bool Restricted = false); + bool Restricted = false) const; - void evalMemcmp(CheckerContext &C, const CallExpr *CE); + void evalMemcmp(CheckerContext &C, const CallExpr *CE) const; - void evalstrLength(CheckerContext &C, const CallExpr *CE); + void evalstrLength(CheckerContext &C, const CallExpr *CE) const; + void evalstrnLength(CheckerContext &C, const CallExpr *CE) const; + void evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, + bool IsStrnlen = false) const; - void evalStrcpy(CheckerContext &C, const CallExpr *CE); - void evalStpcpy(CheckerContext &C, const CallExpr *CE); - void evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool returnEnd); + void evalStrcpy(CheckerContext &C, const CallExpr *CE) const; + void evalStrncpy(CheckerContext &C, const CallExpr *CE) const; + void evalStpcpy(CheckerContext &C, const CallExpr *CE) const; + void evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool returnEnd, + bool isStrncpy) const; // Utility methods std::pair<const GRState*, const GRState*> - assumeZero(CheckerContext &C, const GRState *state, SVal V, QualType Ty); - - const GRState *setCStringLength(const GRState *state, const MemRegion *MR, - SVal strLength); - SVal getCStringLengthForRegion(CheckerContext &C, const GRState *&state, - const Expr *Ex, const MemRegion *MR); + static assumeZero(CheckerContext &C, + const GRState *state, SVal V, QualType Ty); + + static const GRState *setCStringLength(const GRState *state, + const MemRegion *MR, SVal strLength); + static SVal getCStringLengthForRegion(CheckerContext &C, + const GRState *&state, + const Expr *Ex, const MemRegion *MR); SVal getCStringLength(CheckerContext &C, const GRState *&state, - const Expr *Ex, SVal Buf); + const Expr *Ex, SVal Buf) const; - const GRState *InvalidateBuffer(CheckerContext &C, const GRState *state, - const Expr *Ex, SVal V); + static const GRState *InvalidateBuffer(CheckerContext &C, + const GRState *state, + const Expr *Ex, SVal V); - bool SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx, - const MemRegion *MR); + static bool SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx, + const MemRegion *MR); // Re-usable checks const GRState *checkNonNull(CheckerContext &C, const GRState *state, - const Expr *S, SVal l); + const Expr *S, SVal l) const; const GRState *CheckLocation(CheckerContext &C, const GRState *state, const Expr *S, SVal l, - bool IsDestination = false); + bool IsDestination = false) const; const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state, const Expr *Size, const Expr *FirstBuf, const Expr *SecondBuf = NULL, - bool FirstIsDestination = false); + bool FirstIsDestination = false) const; const GRState *CheckOverlap(CheckerContext &C, const GRState *state, const Expr *Size, const Expr *First, - const Expr *Second); + const Expr *Second) const; void emitOverlapBug(CheckerContext &C, const GRState *state, - const Stmt *First, const Stmt *Second); + const Stmt *First, const Stmt *Second) const; }; class CStringLength { @@ -110,14 +122,6 @@ namespace ento { } } -static void RegisterCStringChecker(ExprEngine &Eng) { - Eng.registerCheck(new CStringChecker()); -} - -void ento::registerCStringChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterCStringChecker); -} - //===----------------------------------------------------------------------===// // Individual checks and utility methods. //===----------------------------------------------------------------------===// @@ -136,7 +140,7 @@ CStringChecker::assumeZero(CheckerContext &C, const GRState *state, SVal V, const GRState *CStringChecker::checkNonNull(CheckerContext &C, const GRState *state, - const Expr *S, SVal l) { + const Expr *S, SVal l) const { // If a previous check has failed, propagate the failure. if (!state) return NULL; @@ -150,11 +154,11 @@ const GRState *CStringChecker::checkNonNull(CheckerContext &C, return NULL; if (!BT_Null) - BT_Null = new BuiltinBug("API", - "Null pointer argument in call to byte string function"); + BT_Null.reset(new BuiltinBug("API", + "Null pointer argument in call to byte string function")); // Generate a report for this bug. - BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Null); + BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Null.get()); EnhancedBugReport *report = new EnhancedBugReport(*BT, BT->getDescription(), N); @@ -173,7 +177,7 @@ const GRState *CStringChecker::checkNonNull(CheckerContext &C, const GRState *CStringChecker::CheckLocation(CheckerContext &C, const GRState *state, const Expr *S, SVal l, - bool IsDestination) { + bool IsDestination) const { // If a previous check has failed, propagate the failure. if (!state) return NULL; @@ -209,16 +213,16 @@ const GRState *CStringChecker::CheckLocation(CheckerContext &C, BuiltinBug *BT; if (IsDestination) { if (!BT_BoundsWrite) { - BT_BoundsWrite = new BuiltinBug("Out-of-bound array access", - "Byte string function overflows destination buffer"); + BT_BoundsWrite.reset(new BuiltinBug("Out-of-bound array access", + "Byte string function overflows destination buffer")); } - BT = static_cast<BuiltinBug*>(BT_BoundsWrite); + BT = static_cast<BuiltinBug*>(BT_BoundsWrite.get()); } else { if (!BT_Bounds) { - BT_Bounds = new BuiltinBug("Out-of-bound array access", - "Byte string function accesses out-of-bound array element"); + BT_Bounds.reset(new BuiltinBug("Out-of-bound array access", + "Byte string function accesses out-of-bound array element")); } - BT = static_cast<BuiltinBug*>(BT_Bounds); + BT = static_cast<BuiltinBug*>(BT_Bounds.get()); } // FIXME: It would be nice to eventually make this diagnostic more clear, @@ -243,7 +247,7 @@ const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C, const Expr *Size, const Expr *FirstBuf, const Expr *SecondBuf, - bool FirstIsDestination) { + bool FirstIsDestination) const { // If a previous check has failed, propagate the failure. if (!state) return NULL; @@ -306,7 +310,7 @@ const GRState *CStringChecker::CheckOverlap(CheckerContext &C, const GRState *state, const Expr *Size, const Expr *First, - const Expr *Second) { + const Expr *Second) const { // Do a simple check for overlap: if the two arguments are from the same // buffer, see if the end of the first is greater than the start of the second // or vice versa. @@ -413,13 +417,13 @@ const GRState *CStringChecker::CheckOverlap(CheckerContext &C, } void CStringChecker::emitOverlapBug(CheckerContext &C, const GRState *state, - const Stmt *First, const Stmt *Second) { + const Stmt *First, const Stmt *Second) const { ExplodedNode *N = C.generateSink(state); if (!N) return; if (!BT_Overlap) - BT_Overlap = new BugType("Unix API", "Improper arguments"); + BT_Overlap.reset(new BugType("Unix API", "Improper arguments")); // Generate a report for this bug. RangedBugReport *report = @@ -480,13 +484,14 @@ SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C, unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); SValBuilder &svalBuilder = C.getSValBuilder(); QualType sizeTy = svalBuilder.getContext().getSizeType(); - SVal strLength = svalBuilder.getMetadataSymbolVal(getTag(), MR, Ex, sizeTy, Count); + SVal strLength = svalBuilder.getMetadataSymbolVal(CStringChecker::getTag(), + MR, Ex, sizeTy, Count); state = state->set<CStringLength>(MR, strLength); return strLength; } SVal CStringChecker::getCStringLength(CheckerContext &C, const GRState *&state, - const Expr *Ex, SVal Buf) { + const Expr *Ex, SVal Buf) const { const MemRegion *MR = Buf.getAsRegion(); if (!MR) { // If we can't get a region, see if it's something we /know/ isn't a @@ -495,8 +500,8 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, const GRState *&state, if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&Buf)) { if (ExplodedNode *N = C.generateNode(state)) { if (!BT_NotCString) - BT_NotCString = new BuiltinBug("API", - "Argument is not a null-terminated string."); + BT_NotCString.reset(new BuiltinBug("API", + "Argument is not a null-terminated string.")); llvm::SmallString<120> buf; llvm::raw_svector_ostream os(buf); @@ -551,8 +556,8 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, const GRState *&state, // The caller should always be prepared to handle this case. if (ExplodedNode *N = C.generateNode(state)) { if (!BT_NotCString) - BT_NotCString = new BuiltinBug("API", - "Argument is not a null-terminated string."); + BT_NotCString.reset(new BuiltinBug("API", + "Argument is not a null-terminated string.")); llvm::SmallString<120> buf; llvm::raw_svector_ostream os(buf); @@ -652,7 +657,7 @@ bool CStringChecker::SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx, void CStringChecker::evalCopyCommon(CheckerContext &C, const GRState *state, const Expr *Size, const Expr *Dest, - const Expr *Source, bool Restricted) { + const Expr *Source, bool Restricted) const { // See if the size argument is zero. SVal sizeVal = state->getSVal(Size); QualType sizeTy = Size->getType(); @@ -685,7 +690,7 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, const GRState *state, } -void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) { +void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) const { // void *memcpy(void *restrict dst, const void *restrict src, size_t n); // The return value is the address of the destination buffer. const Expr *Dest = CE->getArg(0); @@ -694,7 +699,7 @@ void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) { evalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1), true); } -void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) { +void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) const { // void *memmove(void *dst, const void *src, size_t n); // The return value is the address of the destination buffer. const Expr *Dest = CE->getArg(0); @@ -703,12 +708,12 @@ void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) { evalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1)); } -void CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) { +void CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) const { // void bcopy(const void *src, void *dst, size_t n); evalCopyCommon(C, C.getState(), CE->getArg(2), CE->getArg(1), CE->getArg(0)); } -void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) { +void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const { // int memcmp(const void *s1, const void *s2, size_t n); const Expr *Left = CE->getArg(0); const Expr *Right = CE->getArg(1); @@ -774,8 +779,20 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) { } } -void CStringChecker::evalstrLength(CheckerContext &C, const CallExpr *CE) { +void CStringChecker::evalstrLength(CheckerContext &C, + const CallExpr *CE) const { // size_t strlen(const char *s); + evalstrLengthCommon(C, CE, /* IsStrnlen = */ false); +} + +void CStringChecker::evalstrnLength(CheckerContext &C, + const CallExpr *CE) const { + // size_t strnlen(const char *s, size_t maxlen); + evalstrLengthCommon(C, CE, /* IsStrnlen = */ true); +} + +void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, + bool IsStrnlen) const { const GRState *state = C.getState(); const Expr *Arg = CE->getArg(0); SVal ArgVal = state->getSVal(Arg); @@ -791,6 +808,32 @@ void CStringChecker::evalstrLength(CheckerContext &C, const CallExpr *CE) { if (strLength.isUndef()) return; + // If the check is for strnlen() then bind the return value to no more than + // the maxlen value. + if (IsStrnlen) { + const Expr *maxlenExpr = CE->getArg(1); + SVal maxlenVal = state->getSVal(maxlenExpr); + + NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength); + NonLoc *maxlenValNL = dyn_cast<NonLoc>(&maxlenVal); + + QualType cmpTy = C.getSValBuilder().getContext().IntTy; + const GRState *stateTrue, *stateFalse; + + // Check if the strLength is greater than or equal to the maxlen + llvm::tie(stateTrue, stateFalse) = + state->assume(cast<DefinedOrUnknownSVal> + (C.getSValBuilder().evalBinOpNN(state, BO_GE, + *strLengthNL, *maxlenValNL, + cmpTy))); + + // If the strLength is greater than or equal to the maxlen, set strLength + // to maxlen + if (stateTrue && !stateFalse) { + strLength = maxlenVal; + } + } + // If getCStringLength couldn't figure out the length, conjure a return // value, so it can be used in constraints, at least. if (strLength.isUnknown()) { @@ -804,18 +847,23 @@ void CStringChecker::evalstrLength(CheckerContext &C, const CallExpr *CE) { } } -void CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) { +void CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) const { + // char *strcpy(char *restrict dst, const char *restrict src); + evalStrcpyCommon(C, CE, /* returnEnd = */ false, /* isStrncpy = */ false); +} + +void CStringChecker::evalStrncpy(CheckerContext &C, const CallExpr *CE) const { // char *strcpy(char *restrict dst, const char *restrict src); - evalStrcpyCommon(C, CE, /* returnEnd = */ false); + evalStrcpyCommon(C, CE, /* returnEnd = */ false, /* isStrncpy = */ true); } -void CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) { +void CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) const { // char *stpcpy(char *restrict dst, const char *restrict src); - evalStrcpyCommon(C, CE, /* returnEnd = */ true); + evalStrcpyCommon(C, CE, /* returnEnd = */ true, /* isStrncpy = */ false); } void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, - bool returnEnd) { + bool returnEnd, bool isStrncpy) const { const GRState *state = C.getState(); // Check that the destination is non-null @@ -840,6 +888,31 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, if (strLength.isUndef()) return; + if (isStrncpy) { + // Get the max number of characters to copy + const Expr *lenExpr = CE->getArg(2); + SVal lenVal = state->getSVal(lenExpr); + + NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength); + NonLoc *lenValNL = dyn_cast<NonLoc>(&lenVal); + + QualType cmpTy = C.getSValBuilder().getContext().IntTy; + const GRState *stateTrue, *stateFalse; + + // Check if the max number to copy is less than the length of the src + llvm::tie(stateTrue, stateFalse) = + state->assume(cast<DefinedOrUnknownSVal> + (C.getSValBuilder().evalBinOpNN(state, BO_GT, + *strLengthNL, *lenValNL, + cmpTy))); + + if (stateTrue) { + // Max number to copy is less than the length of the src, so the actual + // strLength copied is the max number arg. + strLength = lenVal; + } + } + SVal Result = (returnEnd ? UnknownVal() : DstVal); // If the destination is a MemRegion, try to check for a buffer overflow and @@ -889,7 +962,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, // The driver method, and other Checker callbacks. //===----------------------------------------------------------------------===// -bool CStringChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) { +bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { // Get the callee. All the functions we care about are C functions // with simple identifiers. const GRState *state = C.getState(); @@ -912,8 +985,10 @@ bool CStringChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) { .Cases("memcmp", "bcmp", &CStringChecker::evalMemcmp) .Cases("memmove", "__memmove_chk", &CStringChecker::evalMemmove) .Cases("strcpy", "__strcpy_chk", &CStringChecker::evalStrcpy) + .Cases("strncpy", "__strncpy_chk", &CStringChecker::evalStrncpy) .Cases("stpcpy", "__stpcpy_chk", &CStringChecker::evalStpcpy) .Case("strlen", &CStringChecker::evalstrLength) + .Case("strnlen", &CStringChecker::evalstrnLength) .Case("bcopy", &CStringChecker::evalBcopy) .Default(NULL); @@ -926,7 +1001,7 @@ bool CStringChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) { return true; } -void CStringChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) { +void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const { // Record string length for char a[] = "abc"; const GRState *state = C.getState(); @@ -962,15 +1037,15 @@ void CStringChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) { C.addTransition(state); } -bool CStringChecker::wantsRegionChangeUpdate(const GRState *state) { +bool CStringChecker::wantsRegionChangeUpdate(const GRState *state) const { CStringLength::EntryMap Entries = state->get<CStringLength>(); return !Entries.isEmpty(); } -const GRState *CStringChecker::EvalRegionChanges(const GRState *state, - const MemRegion * const *Begin, - const MemRegion * const *End, - bool *) { +const GRState * +CStringChecker::checkRegionChanges(const GRState *state, + const MemRegion * const *Begin, + const MemRegion * const *End) const { CStringLength::EntryMap Entries = state->get<CStringLength>(); if (Entries.isEmpty()) return state; @@ -1017,7 +1092,8 @@ const GRState *CStringChecker::EvalRegionChanges(const GRState *state, return state->set<CStringLength>(Entries); } -void CStringChecker::MarkLiveSymbols(const GRState *state, SymbolReaper &SR) { +void CStringChecker::checkLiveSymbols(const GRState *state, + SymbolReaper &SR) const { // Mark all symbols in our string length map as valid. CStringLength::EntryMap Entries = state->get<CStringLength>(); @@ -1029,7 +1105,8 @@ void CStringChecker::MarkLiveSymbols(const GRState *state, SymbolReaper &SR) { } } -void CStringChecker::evalDeadSymbols(CheckerContext &C, SymbolReaper &SR) { +void CStringChecker::checkDeadSymbols(SymbolReaper &SR, + CheckerContext &C) const { if (!SR.hasDeadSymbols()) return; @@ -1051,3 +1128,7 @@ void CStringChecker::evalDeadSymbols(CheckerContext &C, SymbolReaper &SR) { state = state->set<CStringLength>(Entries); C.generateNode(state); } + +void ento::registerCStringChecker(CheckerManager &mgr) { + mgr.registerChecker<CStringChecker>(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp index 518cf96..6a4506b 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp @@ -11,30 +11,25 @@ // whether the size of the symbolic region is a multiple of the size of T. // //===----------------------------------------------------------------------===// -#include "clang/AST/CharUnits.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" -#include "InternalChecks.h" +#include "clang/AST/CharUnits.h" using namespace clang; using namespace ento; namespace { -class CastSizeChecker : public CheckerVisitor<CastSizeChecker> { - BuiltinBug *BT; +class CastSizeChecker : public CheckerV2< check::PreStmt<CastExpr> > { + mutable llvm::OwningPtr<BuiltinBug> BT; public: - CastSizeChecker() : BT(0) {} - static void *getTag(); - void PreVisitCastExpr(CheckerContext &C, const CastExpr *B); + void checkPreStmt(const CastExpr *CE, CheckerContext &C) const; }; } -void *CastSizeChecker::getTag() { - static int x; - return &x; -} - -void CastSizeChecker::PreVisitCastExpr(CheckerContext &C, const CastExpr *CE) { +void CastSizeChecker::checkPreStmt(const CastExpr *CE,CheckerContext &C) const { const Expr *E = CE->getSubExpr(); ASTContext &Ctx = C.getASTContext(); QualType ToTy = Ctx.getCanonicalType(CE->getType()); @@ -74,9 +69,9 @@ void CastSizeChecker::PreVisitCastExpr(CheckerContext &C, const CastExpr *CE) { if (regionSize % typeSize != 0) { if (ExplodedNode *errorNode = C.generateSink()) { if (!BT) - BT = new BuiltinBug("Cast region with wrong size.", + BT.reset(new BuiltinBug("Cast region with wrong size.", "Cast a region whose size is not a multiple of the" - " destination type size."); + " destination type size.")); RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), errorNode); R->addRange(CE->getSourceRange()); @@ -86,6 +81,6 @@ void CastSizeChecker::PreVisitCastExpr(CheckerContext &C, const CastExpr *CE) { } -void ento::RegisterCastSizeChecker(ExprEngine &Eng) { - Eng.registerCheck(new CastSizeChecker()); +void ento::registerCastSizeChecker(CheckerManager &mgr) { + mgr.registerChecker<CastSizeChecker>(); } diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp index 8ec226a..04cc253 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp @@ -14,31 +14,25 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" using namespace clang; using namespace ento; namespace { -class CastToStructChecker - : public CheckerVisitor<CastToStructChecker> { - BuiltinBug *BT; +class CastToStructChecker : public CheckerV2< check::PreStmt<CastExpr> > { + mutable llvm::OwningPtr<BuiltinBug> BT; + public: - CastToStructChecker() : BT(0) {} - static void *getTag(); - void PreVisitCastExpr(CheckerContext &C, const CastExpr *B); + void checkPreStmt(const CastExpr *CE, CheckerContext &C) const; }; } -void *CastToStructChecker::getTag() { - static int x; - return &x; -} - -void CastToStructChecker::PreVisitCastExpr(CheckerContext &C, - const CastExpr *CE) { +void CastToStructChecker::checkPreStmt(const CastExpr *CE, + CheckerContext &C) const { const Expr *E = CE->getSubExpr(); ASTContext &Ctx = C.getASTContext(); QualType OrigTy = Ctx.getCanonicalType(E->getType()); @@ -64,10 +58,10 @@ void CastToStructChecker::PreVisitCastExpr(CheckerContext &C, if (!OrigPointeeTy->isRecordType()) { if (ExplodedNode *N = C.generateNode()) { if (!BT) - BT = new BuiltinBug("Cast from non-struct type to struct type", + BT.reset(new BuiltinBug("Cast from non-struct type to struct type", "Casting a non-structure type to a structure type " "and accessing a field can lead to memory access " - "errors or data corruption."); + "errors or data corruption.")); RangedBugReport *R = new RangedBugReport(*BT,BT->getDescription(), N); R->addRange(CE->getSourceRange()); C.EmitReport(R); @@ -75,10 +69,6 @@ void CastToStructChecker::PreVisitCastExpr(CheckerContext &C, } } -static void RegisterCastToStructChecker(ExprEngine &Eng) { - Eng.registerCheck(new CastToStructChecker()); -} - void ento::registerCastToStructChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterCastToStructChecker); + mgr.registerChecker<CastToStructChecker>(); } diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td index 1dc7486..894b961 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Checkers.td @@ -71,16 +71,16 @@ def ObjCUnusedIvarsChecker : Checker<"UnusedIvars">, HelpText<"Warn about private ivars that are never used">, DescFile<"ObjCUnusedIVarsChecker.cpp">; -} +} // end "cocoa" -def StackAddrLeakChecker : Checker<"StackAddrLeak">, +def StackAddrEscapeChecker : Checker<"StackAddrEscape">, InPackage<Core>, - HelpText<"Check that addresses to stack memory are not leaked outside the function">, - DescFile<"StackAddrLeakChecker.cpp">; + HelpText<"Check that addresses to stack memory do not escape the function">, + DescFile<"StackAddrEscapeChecker.cpp">; def DeadStoresChecker : Checker<"DeadStores">, InPackage<Core>, - HelpText<"Check for stores to dead variables">, + HelpText<"Check for values stored to a variables that are never read afterwards">, DescFile<"DeadStoresChecker.cpp">; def UnixAPIChecker : Checker<"API">, @@ -90,12 +90,12 @@ def UnixAPIChecker : Checker<"API">, def MacOSXAPIChecker : Checker<"API">, InPackage<MacOSX>, - HelpText<"Check calls to various MacOSXAPIChecker">, + HelpText<"Check for proper uses of various Mac OS X APIs">, DescFile<"MacOSXAPIChecker.cpp">; def CFNumberCreateChecker : Checker<"CFNumber">, InPackage<MacOSX>, - HelpText<"Check for CFNumberCreate">, + HelpText<"Check for proper uses of CFNumberCreate">, DescFile<"BasicObjCFoundationChecks.cpp">; def CFRetainReleaseChecker : Checker<"CFRetainRelease">, @@ -137,7 +137,8 @@ def CStringChecker : Checker<"CString">, def UnreachableCodeChecker : Checker<"UnreachableCode">, InPackage<CoreExperimental>, HelpText<"Check unreachable code">, - DescFile<"UnreachableCodeChecker.cpp">; + DescFile<"UnreachableCodeChecker.cpp">, + Hidden; // Must be specified explicitly in order to run. def IdempotentOperationChecker : Checker<"IdempotentOps">, InPackage<CoreExperimental>, @@ -174,6 +175,21 @@ def SecuritySyntaxChecker : Checker<"SecuritySyntactic">, HelpText<"Perform quick security checks that require no data flow">, DescFile<"CheckSecuritySyntaxOnly.cpp">; +def ReturnPointerRangeChecker : Checker<"ReturnPtrRange">, + InPackage<CoreExperimental>, + HelpText<"Check for an out-of-bound pointer being returned to callers">, + DescFile<"ReturnPointerRangeChecker.cpp">; + +def ArrayBoundChecker : Checker<"ArrayBound">, + InPackage<CoreExperimental>, + HelpText<"Check for an out-of-bound pointer being returned to callers">, + DescFile<"ArrayBoundChecker.cpp">; + +def CastSizeChecker : Checker<"CastSize">, + InPackage<CoreExperimental>, + HelpText<"Check when casting a malloc'ed type T, whether the size is a multiple of the size of T">, + DescFile<"CastSizeChecker.cpp">; + def ObjCDeallocChecker : Checker<"Dealloc">, InPackage<CocoaExperimental>, HelpText<"Warn about Objective-C classes that lack a correct implementation of -dealloc">, diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp index 36e76d0..b6eef6d 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp @@ -12,9 +12,10 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" #include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" @@ -37,38 +38,30 @@ bool isRootChanged(intptr_t k) { return k == ROOT_CHANGED; } // ROOT_CHANGED<--chdir(..)-- JAIL_ENTERED<--chdir(..)-- // | | // bug<--foo()-- JAIL_ENTERED<--foo()-- -class ChrootChecker : public CheckerVisitor<ChrootChecker> { - IdentifierInfo *II_chroot, *II_chdir; +class ChrootChecker : public CheckerV2<eval::Call, check::PreStmt<CallExpr> > { + mutable IdentifierInfo *II_chroot, *II_chdir; // This bug refers to possibly break out of a chroot() jail. - BuiltinBug *BT_BreakJail; + mutable llvm::OwningPtr<BuiltinBug> BT_BreakJail; public: - ChrootChecker() : II_chroot(0), II_chdir(0), BT_BreakJail(0) {} + ChrootChecker() : II_chroot(0), II_chdir(0) {} static void *getTag() { static int x; return &x; } - virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE); - virtual void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE); + bool evalCall(const CallExpr *CE, CheckerContext &C) const; + void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; private: - void Chroot(CheckerContext &C, const CallExpr *CE); - void Chdir(CheckerContext &C, const CallExpr *CE); + void Chroot(CheckerContext &C, const CallExpr *CE) const; + void Chdir(CheckerContext &C, const CallExpr *CE) const; }; } // end anonymous namespace -static void RegisterChrootChecker(ExprEngine &Eng) { - Eng.registerCheck(new ChrootChecker()); -} - -void ento::registerChrootChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterChrootChecker); -} - -bool ChrootChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) { +bool ChrootChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { const GRState *state = C.getState(); const Expr *Callee = CE->getCallee(); SVal L = state->getSVal(Callee); @@ -94,7 +87,7 @@ bool ChrootChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) { return false; } -void ChrootChecker::Chroot(CheckerContext &C, const CallExpr *CE) { +void ChrootChecker::Chroot(CheckerContext &C, const CallExpr *CE) const { const GRState *state = C.getState(); GRStateManager &Mgr = state->getStateManager(); @@ -104,7 +97,7 @@ void ChrootChecker::Chroot(CheckerContext &C, const CallExpr *CE) { C.addTransition(state); } -void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) { +void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) const { const GRState *state = C.getState(); GRStateManager &Mgr = state->getStateManager(); @@ -131,7 +124,7 @@ void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) { } // Check the jail state before any function call except chroot and chdir(). -void ChrootChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) { +void ChrootChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const { const GRState *state = C.getState(); const Expr *Callee = CE->getCallee(); SVal L = state->getSVal(Callee); @@ -155,9 +148,9 @@ void ChrootChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) { if (isRootChanged((intptr_t) *k)) if (ExplodedNode *N = C.generateNode()) { if (!BT_BreakJail) - BT_BreakJail = new BuiltinBug("Break out of jail", + BT_BreakJail.reset(new BuiltinBug("Break out of jail", "No call of chdir(\"/\") immediately " - "after chroot"); + "after chroot")); BugReport *R = new BugReport(*BT_BreakJail, BT_BreakJail->getDescription(), N); C.EmitReport(R); @@ -165,3 +158,7 @@ void ChrootChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) { return; } + +void ento::registerChrootChecker(CheckerManager &mgr) { + mgr.registerChecker<ChrootChecker>(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp index 94f200f..5c0c950 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp @@ -16,7 +16,9 @@ #include "ClangSACheckers.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/CheckerProvider.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/ADT/DenseSet.h" +#include "map" using namespace clang; using namespace ento; @@ -28,6 +30,7 @@ class ClangSACheckerProvider : public CheckerProvider { public: virtual void registerCheckers(CheckerManager &checkerMgr, CheckerOptInfo *checkOpts, unsigned numCheckOpts); + virtual void printHelp(llvm::raw_ostream &OS); }; } @@ -41,6 +44,7 @@ namespace { struct StaticCheckerInfoRec { const char *FullName; void (*RegFunc)(CheckerManager &mgr); + const char *HelpText; bool Hidden; }; @@ -49,13 +53,16 @@ struct StaticCheckerInfoRec { static const StaticCheckerInfoRec StaticCheckerInfo[] = { #define GET_CHECKERS #define CHECKER(FULLNAME,CLASS,DESCFILE,HELPTEXT,HIDDEN) \ - { FULLNAME, register##CLASS, HIDDEN }, + { FULLNAME, register##CLASS, HELPTEXT, HIDDEN }, #include "Checkers.inc" - { 0, 0, 0} + { 0, 0, 0, 0} #undef CHECKER #undef GET_CHECKERS }; +static const unsigned NumCheckers = sizeof(StaticCheckerInfo) + / sizeof(StaticCheckerInfoRec) - 1; + namespace { struct CheckNameOption { @@ -104,9 +111,10 @@ static void collectCheckers(const CheckNameOption *checkName, // Enable/disable all subgroups along with this one. if (const short *subGroups = checkName->SubGroups) { - for (; *subGroups != -1; ++subGroups) - collectCheckers(&CheckNameTable[*subGroups], enable, checkers, - collectHidden && checkName->Hidden); + for (; *subGroups != -1; ++subGroups) { + const CheckNameOption *sub = &CheckNameTable[*subGroups]; + collectCheckers(sub, enable, checkers, collectHidden && !sub->Hidden); + } } } @@ -135,3 +143,41 @@ void ClangSACheckerProvider::registerCheckers(CheckerManager &checkerMgr, (*I)->RegFunc(checkerMgr); } } + +typedef std::map<std::string, const StaticCheckerInfoRec *> SortedCheckers; + +static void printCheckerOption(llvm::raw_ostream &OS,SortedCheckers &checkers) { + // Find the maximum option length. + unsigned OptionFieldWidth = 0; + for (SortedCheckers::iterator + I = checkers.begin(), E = checkers.end(); I != E; ++I) { + // Limit the amount of padding we are willing to give up for alignment. + unsigned Length = strlen(I->second->FullName); + if (Length <= 30) + OptionFieldWidth = std::max(OptionFieldWidth, Length); + } + + const unsigned InitialPad = 2; + for (SortedCheckers::iterator + I = checkers.begin(), E = checkers.end(); I != E; ++I) { + const std::string &Option = I->first; + int Pad = OptionFieldWidth - int(Option.size()); + OS.indent(InitialPad) << Option; + + // Break on long option names. + if (Pad < 0) { + OS << "\n"; + Pad = OptionFieldWidth + InitialPad; + } + OS.indent(Pad + 1) << I->second->HelpText << '\n'; + } +} + +void ClangSACheckerProvider::printHelp(llvm::raw_ostream &OS) { + // Sort checkers according to their full name. + SortedCheckers checkers; + for (unsigned i = 0; i != NumCheckers; ++i) + checkers[StaticCheckerInfo[i].FullName] = &StaticCheckerInfo[i]; + + printCheckerOption(OS, checkers); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp index d9bb480..990ba1c0 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp @@ -24,14 +24,3 @@ void ento::RegisterExperimentalChecks(ExprEngine &Eng) { // within ExprEngine. RegisterMallocChecker(Eng); // ArrayBoundChecker depends on this. } - -void ento::RegisterExperimentalInternalChecks(ExprEngine &Eng) { - // These are internal checks that should eventually migrate to - // RegisterInternalChecks() once they have been further tested. - - // Note that this must be registered after ReturnStackAddresEngsChecker. - RegisterReturnPointerRangeChecker(Eng); - - RegisterArrayBoundChecker(Eng); - RegisterCastSizeChecker(Eng); -} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp index ab8d564..c1b1e65 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprEngine.cpp @@ -92,12 +92,13 @@ void ExprEngine::CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst, } if (CO->empty()) { - // If there are no checkers, return early without doing any - // more work. - Dst.insert(Src); + // If there are no checkers, just delegate to the checker manager. + getCheckerManager().runCheckersForStmt(Kind == PreVisitStmtCallback, + Dst, Src, S, *this); return; } + ExplodedNodeSet CheckersV1Dst; ExplodedNodeSet Tmp; ExplodedNodeSet *PrevSet = &Src; unsigned checkersEvaluated = 0; @@ -108,7 +109,7 @@ void ExprEngine::CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst, break; ExplodedNodeSet *CurrSet = 0; if (I+1 == E) - CurrSet = &Dst; + CurrSet = &CheckersV1Dst; else { CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp; CurrSet->clear(); @@ -144,6 +145,9 @@ void ExprEngine::CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst, // Don't autotransition. The CheckerContext objects should do this // automatically. + + getCheckerManager().runCheckersForStmt(Kind == PreVisitStmtCallback, + Dst, CheckersV1Dst, S, *this); } void ExprEngine::CheckerVisitObjCMessage(const ObjCMessage &msg, @@ -152,10 +156,12 @@ void ExprEngine::CheckerVisitObjCMessage(const ObjCMessage &msg, bool isPrevisit) { if (Checkers.empty()) { - Dst.insert(Src); + getCheckerManager().runCheckersForObjCMessage(isPrevisit, Dst, Src, msg, + *this); return; } + ExplodedNodeSet CheckersV1Dst; ExplodedNodeSet Tmp; ExplodedNodeSet *PrevSet = &Src; @@ -163,7 +169,7 @@ void ExprEngine::CheckerVisitObjCMessage(const ObjCMessage &msg, { ExplodedNodeSet *CurrSet = 0; if (I+1 == E) - CurrSet = &Dst; + CurrSet = &CheckersV1Dst; else { CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp; CurrSet->clear(); @@ -181,8 +187,8 @@ void ExprEngine::CheckerVisitObjCMessage(const ObjCMessage &msg, PrevSet = CurrSet; } - // Don't autotransition. The CheckerContext objects should do this - // automatically. + getCheckerManager().runCheckersForObjCMessage(isPrevisit, Dst, CheckersV1Dst, + msg, *this); } void ExprEngine::CheckerEvalNilReceiver(const ObjCMessage &msg, @@ -232,11 +238,25 @@ bool ExprEngine::CheckerEvalCall(const CallExpr *CE, DstTmp.clear(); } - if (evaluated) + if (evaluated) { Dst.insert(DstTmp); - else - Dst.insert(Pred); + return evaluated; + } + + class DefaultEval : public GraphExpander { + bool &Evaluated; + public: + DefaultEval(bool &evaluated) : Evaluated(evaluated) { } + virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) { + Evaluated = false; + Dst.insert(Pred); + } + }; + evaluated = true; + DefaultEval defaultEval(evaluated); + getCheckerManager().runCheckersForEvalCall(Dst, Pred, CE, *this, + &defaultEval); return evaluated; } @@ -335,8 +355,6 @@ ExprEngine::ExprEngine(AnalysisManager &mgr, TransferFuncs *tf) // FIXME: Eventually remove the TF object entirely. TF->RegisterChecks(*this); TF->RegisterPrinters(getStateManager().Printers); - - mgr.getCheckerManager()->registerCheckersToEngine(*this); if (mgr.shouldEagerlyTrimExplodedGraph()) { // Enable eager node reclaimation when constructing the ExplodedGraph. @@ -495,7 +513,7 @@ bool ExprEngine::wantsRegionChangeUpdate(const GRState* state) { return true; } - return false; + return getCheckerManager().wantsRegionChangeUpdate(state); } const GRState * @@ -523,9 +541,9 @@ ExprEngine::processRegionChanges(const GRState *state, CO = CO_Ref; } - // If there are no checkers, just return the state as is. + // If there are no checkers, just delegate to the checker manager. if (CO->empty()) - return state; + return getCheckerManager().runCheckersForRegionChanges(state, Begin, End); for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I != E; ++I) { // If any checker declares the state infeasible (or if it starts that way), @@ -548,7 +566,7 @@ ExprEngine::processRegionChanges(const GRState *state, if (NewCO.get()) CO_Ref = NewCO.take(); - return state; + return getCheckerManager().runCheckersForRegionChanges(state, Begin, End); } void ExprEngine::processEndWorklist(bool hasWorkRemaining) { @@ -556,6 +574,7 @@ void ExprEngine::processEndWorklist(bool hasWorkRemaining) { I != E; ++I) { I->second->VisitEndAnalysis(G, BR, *this); } + getCheckerManager().runCheckersForEndAnalysis(G, BR, *this); } void ExprEngine::processCFGElement(const CFGElement E, @@ -603,6 +622,8 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) { checker->MarkLiveSymbols(St, SymReaper); } + getCheckerManager().runCheckersForLiveSymbols(St, SymReaper); + const StackFrameContext *SFC = LC->getCurrentStackFrame(); CleanedState = StateMgr.removeDeadBindings(St, SFC, SymReaper); } else { @@ -626,8 +647,9 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) { getTF().evalDeadSymbols(Tmp2, *this, *Builder, EntryNode, CleanedState, SymReaper); + ExplodedNodeSet checkersV1Tmp; if (Checkers.empty()) - Tmp.insert(Tmp2); + checkersV1Tmp.insert(Tmp2); else { ExplodedNodeSet Tmp3; ExplodedNodeSet *SrcSet = &Tmp2; @@ -635,7 +657,7 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) { I != E; ++I) { ExplodedNodeSet *DstSet = 0; if (I+1 == E) - DstSet = &Tmp; + DstSet = &checkersV1Tmp; else { DstSet = (SrcSet == &Tmp2) ? &Tmp3 : &Tmp2; DstSet->clear(); @@ -651,6 +673,9 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) { } } + getCheckerManager().runCheckersForDeadSymbols(Tmp, checkersV1Tmp, + SymReaper, currentStmt, *this); + if (!Builder->BuildSinks && !Builder->hasGeneratedNode) Tmp.Add(EntryNode); } @@ -1419,8 +1444,10 @@ void ExprEngine::processEndOfFunction(EndOfFunctionNodeBuilder& builder) { for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E;++I){ void *tag = I->first; Checker *checker = I->second; - checker->evalEndPath(builder, tag, *this); + EndOfFunctionNodeBuilder B = builder.withCheckerTag(tag); + checker->evalEndPath(B, tag, *this); } + getCheckerManager().runCheckersForEndPath(builder, *this); } /// ProcessSwitch - Called by CoreEngine. Used to generate successor @@ -1923,20 +1950,35 @@ void ExprEngine::evalLocation(ExplodedNodeSet &Dst, const Stmt *S, const GRState* state, SVal location, const void *tag, bool isLoad) { // Early checks for performance reason. - if (location.isUnknown() || Checkers.empty()) { + if (location.isUnknown()) { Dst.Add(Pred); return; } - ExplodedNodeSet Src, Tmp; + if (Checkers.empty()) { + ExplodedNodeSet Src; + if (Builder->GetState(Pred) == state) { + Src.Add(Pred); + } else { + // Associate this new state with an ExplodedNode. + Src.Add(Builder->generateNode(S, state, Pred)); + } + getCheckerManager().runCheckersForLocation(Dst, Src, location, isLoad, S, + *this); + return; + } + + ExplodedNodeSet Src; Src.Add(Pred); + ExplodedNodeSet CheckersV1Dst; + ExplodedNodeSet Tmp; ExplodedNodeSet *PrevSet = &Src; for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I) { ExplodedNodeSet *CurrSet = 0; if (I+1 == E) - CurrSet = &Dst; + CurrSet = &CheckersV1Dst; else { CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp; CurrSet->clear(); @@ -1957,6 +1999,9 @@ void ExprEngine::evalLocation(ExplodedNodeSet &Dst, const Stmt *S, // Update which NodeSet is the current one. PrevSet = CurrSet; } + + getCheckerManager().runCheckersForLocation(Dst, CheckersV1Dst, location, + isLoad, S, *this); } bool ExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, @@ -3613,14 +3658,12 @@ void ExprEngine::ViewGraph(bool trim) { const_cast<BugType*>(*I)->FlushReports(BR); // Iterate through the reports and get their nodes. - for (BugReporter::iterator I=BR.begin(), E=BR.end(); I!=E; ++I) { - for (BugType::const_iterator I2=(*I)->begin(), E2=(*I)->end(); - I2!=E2; ++I2) { - const BugReportEquivClass& EQ = *I2; - const BugReport &R = **EQ.begin(); - ExplodedNode *N = const_cast<ExplodedNode*>(R.getErrorNode()); - if (N) Src.push_back(N); - } + for (BugReporter::EQClasses_iterator + EI = BR.EQClasses_begin(), EE = BR.EQClasses_end(); EI != EE; ++EI) { + BugReportEquivClass& EQ = *EI; + const BugReport &R = **EQ.begin(); + ExplodedNode *N = const_cast<ExplodedNode*>(R.getErrorNode()); + if (N) Src.push_back(N); } ViewGraph(&Src[0], &Src[0]+Src.size()); diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp index fe628a2..d7b27b5 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp @@ -14,31 +14,26 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" using namespace clang; using namespace ento; namespace { class FixedAddressChecker - : public CheckerVisitor<FixedAddressChecker> { - BuiltinBug *BT; + : public CheckerV2< check::PreStmt<BinaryOperator> > { + mutable llvm::OwningPtr<BuiltinBug> BT; + public: - FixedAddressChecker() : BT(0) {} - static void *getTag(); - void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B); + void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const; }; } -void *FixedAddressChecker::getTag() { - static int x; - return &x; -} - -void FixedAddressChecker::PreVisitBinaryOperator(CheckerContext &C, - const BinaryOperator *B) { +void FixedAddressChecker::checkPreStmt(const BinaryOperator *B, + CheckerContext &C) const { // Using a fixed address is not portable because that address will probably // not be valid in all environments or platforms. @@ -58,20 +53,16 @@ void FixedAddressChecker::PreVisitBinaryOperator(CheckerContext &C, if (ExplodedNode *N = C.generateNode()) { if (!BT) - BT = new BuiltinBug("Use fixed address", + BT.reset(new BuiltinBug("Use fixed address", "Using a fixed address is not portable because that " "address will probably not be valid in all " - "environments or platforms."); + "environments or platforms.")); RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N); R->addRange(B->getRHS()->getSourceRange()); C.EmitReport(R); } } -static void RegisterFixedAddressChecker(ExprEngine &Eng) { - Eng.registerCheck(new FixedAddressChecker()); -} - void ento::registerFixedAddressChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterFixedAddressChecker); + mgr.registerChecker<FixedAddressChecker>(); } diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp index f49b125..83d9668 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp @@ -45,11 +45,13 @@ #include "ClangSACheckers.h" #include "clang/Analysis/CFGStmtMap.h" #include "clang/Analysis/Analyses/PseudoConstantAnalysis.h" +#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/AST/Stmt.h" @@ -64,29 +66,29 @@ using namespace ento; namespace { class IdempotentOperationChecker - : public CheckerVisitor<IdempotentOperationChecker> { + : public CheckerV2<check::PreStmt<BinaryOperator>, + check::PostStmt<BinaryOperator>, + check::EndAnalysis> { public: - static void *getTag(); - void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B); - void PostVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B); - void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B, ExprEngine &Eng); + void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const; + void checkPostStmt(const BinaryOperator *B, CheckerContext &C) const; + void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const; private: // Our assumption about a particular operation. enum Assumption { Possible = 0, Impossible, Equal, LHSis1, RHSis1, LHSis0, RHSis0 }; - void UpdateAssumption(Assumption &A, const Assumption &New); + static void UpdateAssumption(Assumption &A, const Assumption &New); // False positive reduction methods static bool isSelfAssign(const Expr *LHS, const Expr *RHS); static bool isUnused(const Expr *E, AnalysisContext *AC); static bool isTruncationExtensionAssignment(const Expr *LHS, const Expr *RHS); - bool pathWasCompletelyAnalyzed(const CFG *cfg, - const CFGBlock *CB, - const CFGStmtMap *CBM, - const CoreEngine &CE); + static bool pathWasCompletelyAnalyzed(AnalysisContext *AC, + const CFGBlock *CB, + const CoreEngine &CE); static bool CanVary(const Expr *Ex, AnalysisContext *AC); static bool isConstantOrPseudoConstant(const DeclRefExpr *DR, @@ -104,46 +106,12 @@ private: }; typedef llvm::DenseMap<const BinaryOperator *, BinaryOperatorData> AssumptionMap; - AssumptionMap hash; - - // A class that performs reachability queries for CFGBlocks. Several internal - // checks in this checker require reachability information. The requests all - // tend to have a common destination, so we lazily do a predecessor search - // from the destination node and cache the results to prevent work - // duplication. - class CFGReachabilityAnalysis { - typedef llvm::BitVector ReachableSet; - typedef llvm::DenseMap<unsigned, ReachableSet> ReachableMap; - ReachableSet analyzed; - ReachableMap reachable; - public: - CFGReachabilityAnalysis(const CFG &cfg) - : analyzed(cfg.getNumBlockIDs(), false) {} - - inline bool isReachable(const CFGBlock *Src, const CFGBlock *Dst); - private: - void MapReachability(const CFGBlock *Dst); - }; - llvm::OwningPtr<CFGReachabilityAnalysis> CRA; + mutable AssumptionMap hash; }; } -void *IdempotentOperationChecker::getTag() { - static int x = 0; - return &x; -} - -static void RegisterIdempotentOperationChecker(ExprEngine &Eng) { - Eng.registerCheck(new IdempotentOperationChecker()); -} - -void ento::registerIdempotentOperationChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterIdempotentOperationChecker); -} - -void IdempotentOperationChecker::PreVisitBinaryOperator( - CheckerContext &C, - const BinaryOperator *B) { +void IdempotentOperationChecker::checkPreStmt(const BinaryOperator *B, + CheckerContext &C) const { // Find or create an entry in the hash for this BinaryOperator instance. // If we haven't done a lookup before, it will get default initialized to // 'Possible'. At this stage we do not store the ExplodedNode, as it has not @@ -359,9 +327,8 @@ void IdempotentOperationChecker::PreVisitBinaryOperator( // At the post visit stage, the predecessor ExplodedNode will be the // BinaryOperator that was just created. We use this hook to collect the // ExplodedNode. -void IdempotentOperationChecker::PostVisitBinaryOperator( - CheckerContext &C, - const BinaryOperator *B) { +void IdempotentOperationChecker::checkPostStmt(const BinaryOperator *B, + CheckerContext &C) const { // Add the ExplodedNode we just visited BinaryOperatorData &Data = hash[B]; @@ -376,9 +343,9 @@ void IdempotentOperationChecker::PostVisitBinaryOperator( Data.explodedNodes.Add(C.getPredecessor()); } -void IdempotentOperationChecker::VisitEndAnalysis(ExplodedGraph &G, +void IdempotentOperationChecker::checkEndAnalysis(ExplodedGraph &G, BugReporter &BR, - ExprEngine &Eng) { + ExprEngine &Eng) const { BugType *BT = new BugType("Idempotent operation", "Dead code"); // Iterate over the hash to see if we have any paths with definite // idempotent operations. @@ -397,16 +364,11 @@ void IdempotentOperationChecker::VisitEndAnalysis(ExplodedGraph &G, // If the analyzer did not finish, check to see if we can still emit this // warning if (Eng.hasWorkRemaining()) { - const CFGStmtMap *CBM = CFGStmtMap::Build(AC->getCFG(), - &AC->getParentMap()); - // If we can trace back - if (!pathWasCompletelyAnalyzed(AC->getCFG(), - CBM->getBlock(B), CBM, + if (!pathWasCompletelyAnalyzed(AC, + AC->getCFGStmtMap()->getBlock(B), Eng.getCoreEngine())) continue; - - delete CBM; } // Select the error message and SourceRanges to report. @@ -464,6 +426,8 @@ void IdempotentOperationChecker::VisitEndAnalysis(ExplodedGraph &G, BR.EmitReport(report); } } + + hash.clear(); } // Updates the current assumption given the new assumption @@ -564,13 +528,11 @@ bool IdempotentOperationChecker::isTruncationExtensionAssignment( // Returns false if a path to this block was not completely analyzed, or true // otherwise. bool -IdempotentOperationChecker::pathWasCompletelyAnalyzed(const CFG *cfg, +IdempotentOperationChecker::pathWasCompletelyAnalyzed(AnalysisContext *AC, const CFGBlock *CB, - const CFGStmtMap *CBM, const CoreEngine &CE) { - if (!CRA.get()) - CRA.reset(new CFGReachabilityAnalysis(*cfg)); + CFGReachabilityAnalysis *CRA = AC->getCFGReachablityAnalysis(); // Test for reachability from any aborted blocks to this block typedef CoreEngine::BlocksAborted::const_iterator AbortedIterator; @@ -621,14 +583,14 @@ IdempotentOperationChecker::pathWasCompletelyAnalyzed(const CFG *cfg, return CRA.isReachable(B, TargetBlock); } }; - VisitWL visitWL(CBM, CB, *CRA.get()); + VisitWL visitWL(AC->getCFGStmtMap(), CB, *CRA); // Were there any items in the worklist that could potentially reach // this block? if (CE.getWorkList()->visitItemsInWorkList(visitWL)) return false; // Verify that this block is reachable from the entry block - if (!CRA->isReachable(&cfg->getEntry(), CB)) + if (!CRA->isReachable(&AC->getCFG()->getEntry(), CB)) return false; // If we get to this point, there is no connection to the entry block or an @@ -766,57 +728,7 @@ bool IdempotentOperationChecker::containsNonLocalVarDecl(const Stmt *S) { return false; } -bool IdempotentOperationChecker::CFGReachabilityAnalysis::isReachable( - const CFGBlock *Src, - const CFGBlock *Dst) { - const unsigned DstBlockID = Dst->getBlockID(); - // If we haven't analyzed the destination node, run the analysis now - if (!analyzed[DstBlockID]) { - MapReachability(Dst); - analyzed[DstBlockID] = true; - } - - // Return the cached result - return reachable[DstBlockID][Src->getBlockID()]; -} - -// Maps reachability to a common node by walking the predecessors of the -// destination node. -void IdempotentOperationChecker::CFGReachabilityAnalysis::MapReachability( - const CFGBlock *Dst) { - - llvm::SmallVector<const CFGBlock *, 11> worklist; - llvm::BitVector visited(analyzed.size()); - - ReachableSet &DstReachability = reachable[Dst->getBlockID()]; - DstReachability.resize(analyzed.size(), false); - - // Start searching from the destination node, since we commonly will perform - // multiple queries relating to a destination node. - worklist.push_back(Dst); - bool firstRun = true; - - while (!worklist.empty()) { - const CFGBlock *block = worklist.back(); - worklist.pop_back(); - - if (visited[block->getBlockID()]) - continue; - visited[block->getBlockID()] = true; - - // Update reachability information for this node -> Dst - if (!firstRun) { - // Don't insert Dst -> Dst unless it was a predecessor of itself - DstReachability[block->getBlockID()] = true; - } - else - firstRun = false; - - // Add the predecessors to the worklist. - for (CFGBlock::const_pred_iterator i = block->pred_begin(), - e = block->pred_end(); i != e; ++i) { - worklist.push_back(*i); - } - } +void ento::registerIdempotentOperationChecker(CheckerManager &mgr) { + mgr.registerChecker<IdempotentOperationChecker>(); } diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h index e855386..e7c38ee 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/InternalChecks.h @@ -23,16 +23,13 @@ class ExprEngine; // Foundational checks that handle basic semantics. void RegisterAdjustedReturnValueChecker(ExprEngine &Eng); -void RegisterArrayBoundChecker(ExprEngine &Eng); void RegisterArrayBoundCheckerV2(ExprEngine &Eng); void RegisterAttrNonNullChecker(ExprEngine &Eng); void RegisterBuiltinFunctionChecker(ExprEngine &Eng); void RegisterCallAndMessageChecker(ExprEngine &Eng); -void RegisterCastSizeChecker(ExprEngine &Eng); void RegisterDereferenceChecker(ExprEngine &Eng); void RegisterDivZeroChecker(ExprEngine &Eng); void RegisterNoReturnFunctionChecker(ExprEngine &Eng); -void RegisterReturnPointerRangeChecker(ExprEngine &Eng); void RegisterReturnUndefChecker(ExprEngine &Eng); void RegisterUndefBranchChecker(ExprEngine &Eng); void RegisterUndefCapturedBlockVarChecker(ExprEngine &Eng); diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp index 358be12..d70c65a 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp @@ -16,11 +16,12 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/Basic/TargetInfo.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" #include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" +#include "clang/Basic/TargetInfo.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/raw_ostream.h" @@ -29,31 +30,26 @@ using namespace clang; using namespace ento; namespace { -class MacOSXAPIChecker : public CheckerVisitor<MacOSXAPIChecker> { +class MacOSXAPIChecker : public CheckerV2< check::PreStmt<CallExpr> > { enum SubChecks { DispatchOnce = 0, DispatchOnceF, NumChecks }; - BugType *BTypes[NumChecks]; + mutable BugType *BTypes[NumChecks]; public: MacOSXAPIChecker() { memset(BTypes, 0, sizeof(*BTypes) * NumChecks); } - static void *getTag() { static unsigned tag = 0; return &tag; } + ~MacOSXAPIChecker() { + for (unsigned i=0; i != NumChecks; ++i) + delete BTypes[i]; + } - void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE); + void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; }; } //end anonymous namespace -static void RegisterMacOSXAPIChecker(ExprEngine &Eng) { - Eng.registerCheck(new MacOSXAPIChecker()); -} - -void ento::registerMacOSXAPIChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterMacOSXAPIChecker); -} - //===----------------------------------------------------------------------===// // dispatch_once and dispatch_once_f //===----------------------------------------------------------------------===// @@ -121,7 +117,8 @@ namespace { }; } // end anonymous namespace -void MacOSXAPIChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) { +void MacOSXAPIChecker::checkPreStmt(const CallExpr *CE, + CheckerContext &C) const { // FIXME: Mostly copy and paste from UnixAPIChecker. Should refactor. const GRState *state = C.getState(); const Expr *Callee = CE->getCallee(); @@ -144,3 +141,11 @@ void MacOSXAPIChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) { SC.run(C, CE, FI); } + +//===----------------------------------------------------------------------===// +// Registration. +//===----------------------------------------------------------------------===// + +void ento::registerMacOSXAPIChecker(CheckerManager &mgr) { + mgr.registerChecker<MacOSXAPIChecker>(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 9d3a887..794740a 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -599,7 +599,7 @@ void MallocChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, for (RegionStateTy::iterator I = M.begin(), E = M.end(); I != E; ++I) { RefState RS = I->second; if (RS.isAllocated()) { - ExplodedNode *N = B.generateNode(state, tag, B.getPredecessor()); + ExplodedNode *N = B.generateNode(state); if (N) { if (!BT_Leak) BT_Leak = new BuiltinBug("Memory leak", diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp index 9fb89d7..fed6a99 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp @@ -16,10 +16,11 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Decl.h" @@ -28,39 +29,18 @@ using namespace ento; namespace { class NSAutoreleasePoolChecker - : public CheckerVisitor<NSAutoreleasePoolChecker> { + : public CheckerV2<check::PreObjCMessage> { - Selector releaseS; + mutable Selector releaseS; public: - NSAutoreleasePoolChecker(Selector release_s) : releaseS(release_s) {} - - static void *getTag() { - static int x = 0; - return &x; - } - - void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg); + void checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const; }; } // end anonymous namespace - -static void RegisterNSAutoreleasePoolChecker(ExprEngine &Eng) { - ASTContext &Ctx = Eng.getContext(); - if (Ctx.getLangOptions().getGCMode() != LangOptions::NonGC) { - Eng.registerCheck(new NSAutoreleasePoolChecker(GetNullarySelector("release", - Ctx))); - } -} - -void ento::registerNSAutoreleasePoolChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterNSAutoreleasePoolChecker); -} - -void -NSAutoreleasePoolChecker::preVisitObjCMessage(CheckerContext &C, - ObjCMessage msg) { +void NSAutoreleasePoolChecker::checkPreObjCMessage(ObjCMessage msg, + CheckerContext &C) const { const Expr *receiver = msg.getInstanceReceiver(); if (!receiver) @@ -78,7 +58,9 @@ NSAutoreleasePoolChecker::preVisitObjCMessage(CheckerContext &C, return; if (!OD->getIdentifier()->getName().equals("NSAutoreleasePool")) return; - + + if (releaseS.isNull()) + releaseS = GetNullarySelector("release", C.getASTContext()); // Sending 'release' message? if (msg.getSelector() != releaseS) return; @@ -90,3 +72,8 @@ NSAutoreleasePoolChecker::preVisitObjCMessage(CheckerContext &C, "Use -drain instead of -release when using NSAutoreleasePool " "and garbage collection", R.getBegin(), &R, 1); } + +void ento::registerNSAutoreleasePoolChecker(CheckerManager &mgr) { + if (mgr.getLangOptions().getGCMode() != LangOptions::NonGC) + mgr.registerChecker<NSAutoreleasePoolChecker>(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp index 7d440ab..7746719 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp @@ -13,39 +13,29 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Checkers/DereferenceChecker.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" using namespace clang; using namespace ento; namespace { -class ObjCAtSyncChecker : public CheckerVisitor<ObjCAtSyncChecker> { - BuiltinBug *BT_null; - BuiltinBug *BT_undef; +class ObjCAtSyncChecker + : public CheckerV2< check::PreStmt<ObjCAtSynchronizedStmt> > { + mutable llvm::OwningPtr<BuiltinBug> BT_null; + mutable llvm::OwningPtr<BuiltinBug> BT_undef; + public: - ObjCAtSyncChecker() : BT_null(0), BT_undef(0) {} - static void *getTag() { static int tag = 0; return &tag; } - void PreVisitObjCAtSynchronizedStmt(CheckerContext &C, - const ObjCAtSynchronizedStmt *S); + void checkPreStmt(const ObjCAtSynchronizedStmt *S, CheckerContext &C) const; }; } // end anonymous namespace -static void RegisterObjCAtSyncChecker(ExprEngine &Eng) { - // @synchronized is an Objective-C 2 feature. - if (Eng.getContext().getLangOptions().ObjC2) - Eng.registerCheck(new ObjCAtSyncChecker()); -} - -void ento::registerObjCAtSyncChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterObjCAtSyncChecker); -} - -void ObjCAtSyncChecker::PreVisitObjCAtSynchronizedStmt(CheckerContext &C, - const ObjCAtSynchronizedStmt *S) { +void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S, + CheckerContext &C) const { const Expr *Ex = S->getSynchExpr(); const GRState *state = C.getState(); @@ -55,8 +45,8 @@ void ObjCAtSyncChecker::PreVisitObjCAtSynchronizedStmt(CheckerContext &C, if (isa<UndefinedVal>(V)) { if (ExplodedNode *N = C.generateSink()) { if (!BT_undef) - BT_undef = new BuiltinBug("Uninitialized value used as mutex " - "for @synchronized"); + BT_undef.reset(new BuiltinBug("Uninitialized value used as mutex " + "for @synchronized")); EnhancedBugReport *report = new EnhancedBugReport(*BT_undef, BT_undef->getDescription(), N); report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex); @@ -78,8 +68,8 @@ void ObjCAtSyncChecker::PreVisitObjCAtSynchronizedStmt(CheckerContext &C, // a null mutex just means no synchronization occurs. if (ExplodedNode *N = C.generateNode(nullState)) { if (!BT_null) - BT_null = new BuiltinBug("Nil value used as mutex for @synchronized() " - "(no synchronization will occur)"); + BT_null.reset(new BuiltinBug("Nil value used as mutex for @synchronized() " + "(no synchronization will occur)")); EnhancedBugReport *report = new EnhancedBugReport(*BT_null, BT_null->getDescription(), N); report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, @@ -98,3 +88,7 @@ void ObjCAtSyncChecker::PreVisitObjCAtSynchronizedStmt(CheckerContext &C, C.addTransition(notNullState); } +void ento::registerObjCAtSyncChecker(CheckerManager &mgr) { + if (mgr.getLangOptions().ObjC2) + mgr.registerChecker<ObjCAtSyncChecker>(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp index 4f247ea..5f32bb8 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp @@ -47,8 +47,9 @@ // http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocAllocInit.html #include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/Analysis/DomainSpecific/CocoaConventions.h" @@ -63,45 +64,23 @@ static bool isInitMessage(const ObjCMessage &msg); static bool isSelfVar(SVal location, CheckerContext &C); namespace { -enum SelfFlagEnum { - /// \brief No flag set. - SelfFlag_None = 0x0, - /// \brief Value came from 'self'. - SelfFlag_Self = 0x1, - /// \brief Value came from the result of an initializer (e.g. [super init]). - SelfFlag_InitRes = 0x2 -}; -} - -namespace { -class ObjCSelfInitChecker : public CheckerVisitor<ObjCSelfInitChecker> { - /// \brief A call receiving a reference to 'self' invalidates the object that - /// 'self' contains. This field keeps the "self flags" assigned to the 'self' - /// object before the call and assign them to the new object that 'self' - /// points to after the call. - SelfFlagEnum preCallSelfFlags; - +class ObjCSelfInitChecker : public CheckerV2< + check::PostObjCMessage, + check::PostStmt<ObjCIvarRefExpr>, + check::PreStmt<ReturnStmt>, + check::PreStmt<CallExpr>, + check::PostStmt<CallExpr>, + check::Location > { public: - static void *getTag() { static int tag = 0; return &tag; } - void postVisitObjCMessage(CheckerContext &C, ObjCMessage msg); - void PostVisitObjCIvarRefExpr(CheckerContext &C, const ObjCIvarRefExpr *E); - void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S); - void PreVisitGenericCall(CheckerContext &C, const CallExpr *CE); - void PostVisitGenericCall(CheckerContext &C, const CallExpr *CE); - virtual void visitLocation(CheckerContext &C, const Stmt *S, SVal location, - bool isLoad); + void checkPostObjCMessage(ObjCMessage msg, CheckerContext &C) const; + void checkPostStmt(const ObjCIvarRefExpr *E, CheckerContext &C) const; + void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const; + void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; + void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; + void checkLocation(SVal location, bool isLoad, CheckerContext &C) const; }; } // end anonymous namespace -static void RegisterObjCSelfInitChecker(ExprEngine &Eng) { - if (Eng.getContext().getLangOptions().ObjC1) - Eng.registerCheck(new ObjCSelfInitChecker()); -} - -void ento::registerObjCSelfInitChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterObjCSelfInitChecker); -} - namespace { class InitSelfBug : public BugType { @@ -113,22 +92,40 @@ public: } // end anonymous namespace +namespace { +enum SelfFlagEnum { + /// \brief No flag set. + SelfFlag_None = 0x0, + /// \brief Value came from 'self'. + SelfFlag_Self = 0x1, + /// \brief Value came from the result of an initializer (e.g. [super init]). + SelfFlag_InitRes = 0x2 +}; +} + typedef llvm::ImmutableMap<SymbolRef, unsigned> SelfFlag; namespace { struct CalledInit {}; } +namespace { struct PreCallSelfFlags {}; } namespace clang { namespace ento { template<> struct GRStateTrait<SelfFlag> : public GRStatePartialTrait<SelfFlag> { - static void* GDMIndex() { - static int index = 0; - return &index; - } + static void* GDMIndex() { static int index = 0; return &index; } }; template <> struct GRStateTrait<CalledInit> : public GRStatePartialTrait<bool> { static void *GDMIndex() { static int index = 0; return &index; } }; + + /// \brief A call receiving a reference to 'self' invalidates the object that + /// 'self' contains. This keeps the "self flags" assigned to the 'self' + /// object before the call so we can assign them to the new object that 'self' + /// points to after the call. + template <> + struct GRStateTrait<PreCallSelfFlags> : public GRStatePartialTrait<unsigned> { + static void *GDMIndex() { static int index = 0; return &index; } + }; } } @@ -188,8 +185,8 @@ static void checkForInvalidSelf(const Expr *E, CheckerContext &C, C.EmitReport(report); } -void ObjCSelfInitChecker::postVisitObjCMessage(CheckerContext &C, - ObjCMessage msg) { +void ObjCSelfInitChecker::checkPostObjCMessage(ObjCMessage msg, + CheckerContext &C) const { // When encountering a message that does initialization (init rule), // tag the return value so that we know later on that if self has this value // then it is properly initialized. @@ -219,8 +216,8 @@ void ObjCSelfInitChecker::postVisitObjCMessage(CheckerContext &C, // fails. } -void ObjCSelfInitChecker::PostVisitObjCIvarRefExpr(CheckerContext &C, - const ObjCIvarRefExpr *E) { +void ObjCSelfInitChecker::checkPostStmt(const ObjCIvarRefExpr *E, + CheckerContext &C) const { // FIXME: A callback should disable checkers at the start of functions. if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>( C.getCurrentAnalysisContext()->getDecl()))) @@ -231,8 +228,8 @@ void ObjCSelfInitChecker::PostVisitObjCIvarRefExpr(CheckerContext &C, "'[(super or self) init...]'"); } -void ObjCSelfInitChecker::PreVisitReturnStmt(CheckerContext &C, - const ReturnStmt *S) { +void ObjCSelfInitChecker::checkPreStmt(const ReturnStmt *S, + CheckerContext &C) const { // FIXME: A callback should disable checkers at the start of functions. if (!shouldRunOnFunctionOrMethod(dyn_cast<NamedDecl>( C.getCurrentAnalysisContext()->getDecl()))) @@ -259,40 +256,46 @@ void ObjCSelfInitChecker::PreVisitReturnStmt(CheckerContext &C, // Until we can use inter-procedural analysis, in such a call, transfer the // SelfFlags to the result of the call. -void ObjCSelfInitChecker::PreVisitGenericCall(CheckerContext &C, - const CallExpr *CE) { +void ObjCSelfInitChecker::checkPreStmt(const CallExpr *CE, + CheckerContext &C) const { const GRState *state = C.getState(); for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) { SVal argV = state->getSVal(*I); if (isSelfVar(argV, C)) { - preCallSelfFlags = getSelfFlags(state->getSVal(cast<Loc>(argV)), C); + unsigned selfFlags = getSelfFlags(state->getSVal(cast<Loc>(argV)), C); + C.addTransition(state->set<PreCallSelfFlags>(selfFlags)); return; } else if (hasSelfFlag(argV, SelfFlag_Self, C)) { - preCallSelfFlags = getSelfFlags(argV, C); + unsigned selfFlags = getSelfFlags(argV, C); + C.addTransition(state->set<PreCallSelfFlags>(selfFlags)); return; } } } -void ObjCSelfInitChecker::PostVisitGenericCall(CheckerContext &C, - const CallExpr *CE) { +void ObjCSelfInitChecker::checkPostStmt(const CallExpr *CE, + CheckerContext &C) const { const GRState *state = C.getState(); for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) { SVal argV = state->getSVal(*I); if (isSelfVar(argV, C)) { - addSelfFlag(state, state->getSVal(cast<Loc>(argV)), preCallSelfFlags, C); + SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>(); + state = state->remove<PreCallSelfFlags>(); + addSelfFlag(state, state->getSVal(cast<Loc>(argV)), prevFlags, C); return; } else if (hasSelfFlag(argV, SelfFlag_Self, C)) { - addSelfFlag(state, state->getSVal(CE), preCallSelfFlags, C); + SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>(); + state = state->remove<PreCallSelfFlags>(); + addSelfFlag(state, state->getSVal(CE), prevFlags, C); return; } } } -void ObjCSelfInitChecker::visitLocation(CheckerContext &C, const Stmt *S, - SVal location, bool isLoad) { +void ObjCSelfInitChecker::checkLocation(SVal location, bool isLoad, + CheckerContext &C) const { // Tag the result of a load from 'self' so that we can easily know that the // value is the object that 'self' points to. const GRState *state = C.getState(); @@ -354,3 +357,11 @@ static bool isInitializationMethod(const ObjCMethodDecl *MD) { static bool isInitMessage(const ObjCMessage &msg) { return cocoa::deriveNamingConvention(msg.getSelector()) == cocoa::InitRule; } + +//===----------------------------------------------------------------------===// +// Registration. +//===----------------------------------------------------------------------===// + +void ento::registerObjCSelfInitChecker(CheckerManager &mgr) { + mgr.registerChecker<ObjCSelfInitChecker>(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp index 741e48b..034a2aa 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp @@ -13,31 +13,26 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" using namespace clang; using namespace ento; namespace { class PointerArithChecker - : public CheckerVisitor<PointerArithChecker> { - BuiltinBug *BT; + : public CheckerV2< check::PreStmt<BinaryOperator> > { + mutable llvm::OwningPtr<BuiltinBug> BT; + public: - PointerArithChecker() : BT(0) {} - static void *getTag(); - void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B); + void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const; }; } -void *PointerArithChecker::getTag() { - static int x; - return &x; -} - -void PointerArithChecker::PreVisitBinaryOperator(CheckerContext &C, - const BinaryOperator *B) { +void PointerArithChecker::checkPreStmt(const BinaryOperator *B, + CheckerContext &C) const { if (B->getOpcode() != BO_Sub && B->getOpcode() != BO_Add) return; @@ -57,10 +52,10 @@ void PointerArithChecker::PreVisitBinaryOperator(CheckerContext &C, if (ExplodedNode *N = C.generateNode()) { if (!BT) - BT = new BuiltinBug("Dangerous pointer arithmetic", + BT.reset(new BuiltinBug("Dangerous pointer arithmetic", "Pointer arithmetic done on non-array variables " "means reliance on memory layout, which is " - "dangerous."); + "dangerous.")); RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N); R->addRange(B->getSourceRange()); C.EmitReport(R); @@ -68,10 +63,6 @@ void PointerArithChecker::PreVisitBinaryOperator(CheckerContext &C, } } -static void RegisterPointerArithChecker(ExprEngine &Eng) { - Eng.registerCheck(new PointerArithChecker()); -} - void ento::registerPointerArithChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterPointerArithChecker); + mgr.registerChecker<PointerArithChecker>(); } diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp index f28fe9a..bf85b95 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp @@ -14,31 +14,26 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" using namespace clang; using namespace ento; namespace { class PointerSubChecker - : public CheckerVisitor<PointerSubChecker> { - BuiltinBug *BT; + : public CheckerV2< check::PreStmt<BinaryOperator> > { + mutable llvm::OwningPtr<BuiltinBug> BT; + public: - PointerSubChecker() : BT(0) {} - static void *getTag(); - void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B); + void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const; }; } -void *PointerSubChecker::getTag() { - static int x; - return &x; -} - -void PointerSubChecker::PreVisitBinaryOperator(CheckerContext &C, - const BinaryOperator *B) { +void PointerSubChecker::checkPreStmt(const BinaryOperator *B, + CheckerContext &C) const { // When doing pointer subtraction, if the two pointers do not point to the // same memory chunk, emit a warning. if (B->getOpcode() != BO_Sub) @@ -66,19 +61,15 @@ void PointerSubChecker::PreVisitBinaryOperator(CheckerContext &C, if (ExplodedNode *N = C.generateNode()) { if (!BT) - BT = new BuiltinBug("Pointer subtraction", + BT.reset(new BuiltinBug("Pointer subtraction", "Subtraction of two pointers that do not point to " - "the same memory chunk may cause incorrect result."); + "the same memory chunk may cause incorrect result.")); RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N); R->addRange(B->getSourceRange()); C.EmitReport(R); } } -static void RegisterPointerSubChecker(ExprEngine &Eng) { - Eng.registerCheck(new PointerSubChecker()); -} - void ento::registerPointerSubChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterPointerSubChecker); + mgr.registerChecker<PointerSubChecker>(); } diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp index 34c095f..6c6901f 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp @@ -13,8 +13,9 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" #include "llvm/ADT/ImmutableSet.h" @@ -24,21 +25,15 @@ using namespace ento; namespace { class PthreadLockChecker - : public CheckerVisitor<PthreadLockChecker> { - BugType *BT; + : public CheckerV2< check::PostStmt<CallExpr> > { public: - PthreadLockChecker() : BT(0) {} - static void *getTag() { - static int x = 0; - return &x; - } - void PostVisitCallExpr(CheckerContext &C, const CallExpr *CE); + void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; void AcquireLock(CheckerContext &C, const CallExpr *CE, - SVal lock, bool isTryLock); + SVal lock, bool isTryLock) const; void ReleaseLock(CheckerContext &C, const CallExpr *CE, - SVal lock); + SVal lock) const; }; } // end anonymous namespace @@ -49,22 +44,14 @@ namespace clang { namespace ento { template <> struct GRStateTrait<LockSet> : public GRStatePartialTrait<llvm::ImmutableSet<const MemRegion*> > { - static void* GDMIndex() { return PthreadLockChecker::getTag(); } + static void* GDMIndex() { static int x = 0; return &x; } }; } // end GR namespace } // end clang namespace -static void RegisterPthreadLockChecker(ExprEngine &Eng) { - Eng.registerCheck(new PthreadLockChecker()); -} - -void ento::registerPthreadLockChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterPthreadLockChecker); -} - -void PthreadLockChecker::PostVisitCallExpr(CheckerContext &C, - const CallExpr *CE) { +void PthreadLockChecker::checkPostStmt(const CallExpr *CE, + CheckerContext &C) const { const GRState *state = C.getState(); const Expr *Callee = CE->getCallee(); const FunctionTextRegion *R = @@ -96,7 +83,7 @@ void PthreadLockChecker::PostVisitCallExpr(CheckerContext &C, } void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE, - SVal lock, bool isTryLock) { + SVal lock, bool isTryLock) const { const MemRegion *lockR = lock.getAsRegion(); if (!lockR) @@ -132,7 +119,7 @@ void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE, } void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE, - SVal lock) { + SVal lock) const { const MemRegion *lockR = lock.getAsRegion(); if (!lockR) @@ -150,3 +137,7 @@ void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE, C.addTransition(C.generateNode(CE, unlockState)); } + +void ento::registerPthreadLockChecker(CheckerManager &mgr) { + mgr.registerChecker<PthreadLockChecker>(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp index 838a00f..2985156 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp @@ -12,9 +12,11 @@ // //===----------------------------------------------------------------------===// -#include "InternalChecks.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" using namespace clang; @@ -22,25 +24,15 @@ using namespace ento; namespace { class ReturnPointerRangeChecker : - public CheckerVisitor<ReturnPointerRangeChecker> { - BuiltinBug *BT; + public CheckerV2< check::PreStmt<ReturnStmt> > { + mutable llvm::OwningPtr<BuiltinBug> BT; public: - ReturnPointerRangeChecker() : BT(0) {} - static void *getTag(); - void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS); + void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const; }; } -void ento::RegisterReturnPointerRangeChecker(ExprEngine &Eng) { - Eng.registerCheck(new ReturnPointerRangeChecker()); -} - -void *ReturnPointerRangeChecker::getTag() { - static int x = 0; return &x; -} - -void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C, - const ReturnStmt *RS) { +void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS, + CheckerContext &C) const { const GRState *state = C.getState(); const Expr *RetE = RS->getRetValue(); @@ -77,9 +69,9 @@ void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C, // FIXME: This bug correspond to CWE-466. Eventually we should have bug // types explicitly reference such exploit categories (when applicable). if (!BT) - BT = new BuiltinBug("Return of pointer value outside of expected range", + BT.reset(new BuiltinBug("Return of pointer value outside of expected range", "Returned pointer value points outside the original object " - "(potential buffer overflow)"); + "(potential buffer overflow)")); // FIXME: It would be nice to eventually make this diagnostic more clear, // e.g., by referencing the original declaration or by saying *why* this @@ -93,3 +85,7 @@ void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C, C.EmitReport(report); } } + +void ento::registerReturnPointerRangeChecker(CheckerManager &mgr) { + mgr.registerChecker<ReturnPointerRangeChecker>(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp index 363f404..6a9a37d 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp @@ -1,4 +1,4 @@ -//=== StackAddrLeakChecker.cpp ------------------------------------*- C++ -*--// +//=== StackAddrEscapeChecker.cpp ----------------------------------*- C++ -*--// // // The LLVM Compiler Infrastructure // @@ -13,9 +13,10 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" #include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/SmallString.h" @@ -23,34 +24,23 @@ using namespace clang; using namespace ento; namespace { -class StackAddrLeakChecker : public CheckerVisitor<StackAddrLeakChecker> { - BuiltinBug *BT_stackleak; - BuiltinBug *BT_returnstack; +class StackAddrEscapeChecker : public CheckerV2< check::PreStmt<ReturnStmt>, + check::EndPath > { + mutable llvm::OwningPtr<BuiltinBug> BT_stackleak; + mutable llvm::OwningPtr<BuiltinBug> BT_returnstack; public: - StackAddrLeakChecker() : BT_stackleak(0), BT_returnstack(0) {} - static void *getTag() { - static int x; - return &x; - } - void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS); - void evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, ExprEngine &Eng); + void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const; + void checkEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng) const; private: - void EmitStackError(CheckerContext &C, const MemRegion *R, const Expr *RetE); - SourceRange GenName(llvm::raw_ostream &os, const MemRegion *R, - SourceManager &SM); + void EmitStackError(CheckerContext &C, const MemRegion *R, + const Expr *RetE) const; + static SourceRange GenName(llvm::raw_ostream &os, const MemRegion *R, + SourceManager &SM); }; } -static void RegisterStackAddrLeakChecker(ExprEngine &Eng) { - Eng.registerCheck(new StackAddrLeakChecker()); -} - -void ento::registerStackAddrLeakChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterStackAddrLeakChecker); -} - -SourceRange StackAddrLeakChecker::GenName(llvm::raw_ostream &os, +SourceRange StackAddrEscapeChecker::GenName(llvm::raw_ostream &os, const MemRegion *R, SourceManager &SM) { // Get the base region, stripping away fields and elements. @@ -93,15 +83,16 @@ SourceRange StackAddrLeakChecker::GenName(llvm::raw_ostream &os, return range; } -void StackAddrLeakChecker::EmitStackError(CheckerContext &C, const MemRegion *R, - const Expr *RetE) { +void StackAddrEscapeChecker::EmitStackError(CheckerContext &C, const MemRegion *R, + const Expr *RetE) const { ExplodedNode *N = C.generateSink(); if (!N) return; if (!BT_returnstack) - BT_returnstack=new BuiltinBug("Return of address to stack-allocated memory"); + BT_returnstack.reset( + new BuiltinBug("Return of address to stack-allocated memory")); // Generate a report for this bug. llvm::SmallString<512> buf; @@ -116,8 +107,8 @@ void StackAddrLeakChecker::EmitStackError(CheckerContext &C, const MemRegion *R, C.EmitReport(report); } -void StackAddrLeakChecker::PreVisitReturnStmt(CheckerContext &C, - const ReturnStmt *RS) { +void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS, + CheckerContext &C) const { const Expr *RetE = RS->getRetValue(); if (!RetE) @@ -135,8 +126,8 @@ void StackAddrLeakChecker::PreVisitReturnStmt(CheckerContext &C, } } -void StackAddrLeakChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, - ExprEngine &Eng) { +void StackAddrEscapeChecker::checkEndPath(EndOfFunctionNodeBuilder &B, + ExprEngine &Eng) const { const GRState *state = B.getState(); @@ -180,16 +171,16 @@ void StackAddrLeakChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, return; // Generate an error node. - ExplodedNode *N = B.generateNode(state, tag, B.getPredecessor()); + ExplodedNode *N = B.generateNode(state); if (!N) return; if (!BT_stackleak) - BT_stackleak = + BT_stackleak.reset( new BuiltinBug("Stack address stored into global variable", "Stack address was saved into a global variable. " "This is dangerous because the address will become " - "invalid after returning from the function"); + "invalid after returning from the function")); for (unsigned i = 0, e = cb.V.size(); i != e; ++i) { // Generate a report for this bug. @@ -208,3 +199,7 @@ void StackAddrLeakChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, Eng.getBugReporter().EmitReport(report); } } + +void ento::registerStackAddrEscapeChecker(CheckerManager &mgr) { + mgr.registerChecker<StackAddrEscapeChecker>(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp index 2655be2..d0626b8 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -12,9 +12,10 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" #include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" @@ -55,52 +56,50 @@ struct StreamState { } }; -class StreamChecker : public CheckerVisitor<StreamChecker> { - IdentifierInfo *II_fopen, *II_tmpfile, *II_fclose, *II_fread, *II_fwrite, +class StreamChecker : public CheckerV2<eval::Call, + check::DeadSymbols, + check::EndPath, + check::PreStmt<ReturnStmt> > { + mutable IdentifierInfo *II_fopen, *II_tmpfile, *II_fclose, *II_fread, + *II_fwrite, *II_fseek, *II_ftell, *II_rewind, *II_fgetpos, *II_fsetpos, *II_clearerr, *II_feof, *II_ferror, *II_fileno; - BuiltinBug *BT_nullfp, *BT_illegalwhence, *BT_doubleclose, *BT_ResourceLeak; + mutable llvm::OwningPtr<BuiltinBug> BT_nullfp, BT_illegalwhence, + BT_doubleclose, BT_ResourceLeak; public: StreamChecker() : II_fopen(0), II_tmpfile(0) ,II_fclose(0), II_fread(0), II_fwrite(0), II_fseek(0), II_ftell(0), II_rewind(0), II_fgetpos(0), II_fsetpos(0), - II_clearerr(0), II_feof(0), II_ferror(0), II_fileno(0), - BT_nullfp(0), BT_illegalwhence(0), BT_doubleclose(0), - BT_ResourceLeak(0) {} + II_clearerr(0), II_feof(0), II_ferror(0), II_fileno(0) {} - static void *getTag() { - static int x; - return &x; - } - - virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE); - void evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper); - void evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, ExprEngine &Eng); - void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S); + bool evalCall(const CallExpr *CE, CheckerContext &C) const; + void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; + void checkEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng) const; + void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const; private: - void Fopen(CheckerContext &C, const CallExpr *CE); - void Tmpfile(CheckerContext &C, const CallExpr *CE); - void Fclose(CheckerContext &C, const CallExpr *CE); - void Fread(CheckerContext &C, const CallExpr *CE); - void Fwrite(CheckerContext &C, const CallExpr *CE); - void Fseek(CheckerContext &C, const CallExpr *CE); - void Ftell(CheckerContext &C, const CallExpr *CE); - void Rewind(CheckerContext &C, const CallExpr *CE); - void Fgetpos(CheckerContext &C, const CallExpr *CE); - void Fsetpos(CheckerContext &C, const CallExpr *CE); - void Clearerr(CheckerContext &C, const CallExpr *CE); - void Feof(CheckerContext &C, const CallExpr *CE); - void Ferror(CheckerContext &C, const CallExpr *CE); - void Fileno(CheckerContext &C, const CallExpr *CE); - - void OpenFileAux(CheckerContext &C, const CallExpr *CE); + void Fopen(CheckerContext &C, const CallExpr *CE) const; + void Tmpfile(CheckerContext &C, const CallExpr *CE) const; + void Fclose(CheckerContext &C, const CallExpr *CE) const; + void Fread(CheckerContext &C, const CallExpr *CE) const; + void Fwrite(CheckerContext &C, const CallExpr *CE) const; + void Fseek(CheckerContext &C, const CallExpr *CE) const; + void Ftell(CheckerContext &C, const CallExpr *CE) const; + void Rewind(CheckerContext &C, const CallExpr *CE) const; + void Fgetpos(CheckerContext &C, const CallExpr *CE) const; + void Fsetpos(CheckerContext &C, const CallExpr *CE) const; + void Clearerr(CheckerContext &C, const CallExpr *CE) const; + void Feof(CheckerContext &C, const CallExpr *CE) const; + void Ferror(CheckerContext &C, const CallExpr *CE) const; + void Fileno(CheckerContext &C, const CallExpr *CE) const; + + void OpenFileAux(CheckerContext &C, const CallExpr *CE) const; const GRState *CheckNullStream(SVal SV, const GRState *state, - CheckerContext &C); + CheckerContext &C) const; const GRState *CheckDoubleClose(const CallExpr *CE, const GRState *state, - CheckerContext &C); + CheckerContext &C) const; }; } // end anonymous namespace @@ -110,20 +109,12 @@ namespace ento { template <> struct GRStateTrait<StreamState> : public GRStatePartialTrait<llvm::ImmutableMap<SymbolRef, StreamState> > { - static void *GDMIndex() { return StreamChecker::getTag(); } + static void *GDMIndex() { static int x; return &x; } }; } } -static void RegisterStreamChecker(ExprEngine &Eng) { - Eng.registerCheck(new StreamChecker()); -} - -void ento::registerStreamChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterStreamChecker); -} - -bool StreamChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) { +bool StreamChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { const GRState *state = C.getState(); const Expr *Callee = CE->getCallee(); SVal L = state->getSVal(Callee); @@ -221,15 +212,15 @@ bool StreamChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) { return false; } -void StreamChecker::Fopen(CheckerContext &C, const CallExpr *CE) { +void StreamChecker::Fopen(CheckerContext &C, const CallExpr *CE) const { OpenFileAux(C, CE); } -void StreamChecker::Tmpfile(CheckerContext &C, const CallExpr *CE) { +void StreamChecker::Tmpfile(CheckerContext &C, const CallExpr *CE) const { OpenFileAux(C, CE); } -void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) { +void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) const { const GRState *state = C.getState(); unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); SValBuilder &svalBuilder = C.getSValBuilder(); @@ -255,25 +246,25 @@ void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) { } } -void StreamChecker::Fclose(CheckerContext &C, const CallExpr *CE) { +void StreamChecker::Fclose(CheckerContext &C, const CallExpr *CE) const { const GRState *state = CheckDoubleClose(CE, C.getState(), C); if (state) C.addTransition(state); } -void StreamChecker::Fread(CheckerContext &C, const CallExpr *CE) { +void StreamChecker::Fread(CheckerContext &C, const CallExpr *CE) const { const GRState *state = C.getState(); if (!CheckNullStream(state->getSVal(CE->getArg(3)), state, C)) return; } -void StreamChecker::Fwrite(CheckerContext &C, const CallExpr *CE) { +void StreamChecker::Fwrite(CheckerContext &C, const CallExpr *CE) const { const GRState *state = C.getState(); if (!CheckNullStream(state->getSVal(CE->getArg(3)), state, C)) return; } -void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) { +void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) const { const GRState *state = C.getState(); if (!(state = CheckNullStream(state->getSVal(CE->getArg(0)), state, C))) return; @@ -290,65 +281,65 @@ void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) { if (ExplodedNode *N = C.generateNode(state)) { if (!BT_illegalwhence) - BT_illegalwhence = new BuiltinBug("Illegal whence argument", + BT_illegalwhence.reset(new BuiltinBug("Illegal whence argument", "The whence argument to fseek() should be " - "SEEK_SET, SEEK_END, or SEEK_CUR."); + "SEEK_SET, SEEK_END, or SEEK_CUR.")); BugReport *R = new BugReport(*BT_illegalwhence, BT_illegalwhence->getDescription(), N); C.EmitReport(R); } } -void StreamChecker::Ftell(CheckerContext &C, const CallExpr *CE) { +void StreamChecker::Ftell(CheckerContext &C, const CallExpr *CE) const { const GRState *state = C.getState(); if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C)) return; } -void StreamChecker::Rewind(CheckerContext &C, const CallExpr *CE) { +void StreamChecker::Rewind(CheckerContext &C, const CallExpr *CE) const { const GRState *state = C.getState(); if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C)) return; } -void StreamChecker::Fgetpos(CheckerContext &C, const CallExpr *CE) { +void StreamChecker::Fgetpos(CheckerContext &C, const CallExpr *CE) const { const GRState *state = C.getState(); if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C)) return; } -void StreamChecker::Fsetpos(CheckerContext &C, const CallExpr *CE) { +void StreamChecker::Fsetpos(CheckerContext &C, const CallExpr *CE) const { const GRState *state = C.getState(); if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C)) return; } -void StreamChecker::Clearerr(CheckerContext &C, const CallExpr *CE) { +void StreamChecker::Clearerr(CheckerContext &C, const CallExpr *CE) const { const GRState *state = C.getState(); if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C)) return; } -void StreamChecker::Feof(CheckerContext &C, const CallExpr *CE) { +void StreamChecker::Feof(CheckerContext &C, const CallExpr *CE) const { const GRState *state = C.getState(); if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C)) return; } -void StreamChecker::Ferror(CheckerContext &C, const CallExpr *CE) { +void StreamChecker::Ferror(CheckerContext &C, const CallExpr *CE) const { const GRState *state = C.getState(); if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C)) return; } -void StreamChecker::Fileno(CheckerContext &C, const CallExpr *CE) { +void StreamChecker::Fileno(CheckerContext &C, const CallExpr *CE) const { const GRState *state = C.getState(); if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C)) return; } const GRState *StreamChecker::CheckNullStream(SVal SV, const GRState *state, - CheckerContext &C) { + CheckerContext &C) const { const DefinedSVal *DV = dyn_cast<DefinedSVal>(&SV); if (!DV) return 0; @@ -360,8 +351,8 @@ const GRState *StreamChecker::CheckNullStream(SVal SV, const GRState *state, if (!stateNotNull && stateNull) { if (ExplodedNode *N = C.generateSink(stateNull)) { if (!BT_nullfp) - BT_nullfp = new BuiltinBug("NULL stream pointer", - "Stream pointer might be NULL."); + BT_nullfp.reset(new BuiltinBug("NULL stream pointer", + "Stream pointer might be NULL.")); BugReport *R =new BugReport(*BT_nullfp, BT_nullfp->getDescription(), N); C.EmitReport(R); } @@ -372,7 +363,7 @@ const GRState *StreamChecker::CheckNullStream(SVal SV, const GRState *state, const GRState *StreamChecker::CheckDoubleClose(const CallExpr *CE, const GRState *state, - CheckerContext &C) { + CheckerContext &C) const { SymbolRef Sym = state->getSVal(CE->getArg(0)).getAsSymbol(); if (!Sym) return state; @@ -389,9 +380,9 @@ const GRState *StreamChecker::CheckDoubleClose(const CallExpr *CE, ExplodedNode *N = C.generateSink(); if (N) { if (!BT_doubleclose) - BT_doubleclose = new BuiltinBug("Double fclose", + BT_doubleclose.reset(new BuiltinBug("Double fclose", "Try to close a file Descriptor already" - " closed. Cause undefined behaviour."); + " closed. Cause undefined behaviour.")); BugReport *R = new BugReport(*BT_doubleclose, BT_doubleclose->getDescription(), N); C.EmitReport(R); @@ -403,7 +394,8 @@ const GRState *StreamChecker::CheckDoubleClose(const CallExpr *CE, return state->set<StreamState>(Sym, StreamState::getClosed(CE)); } -void StreamChecker::evalDeadSymbols(CheckerContext &C,SymbolReaper &SymReaper) { +void StreamChecker::checkDeadSymbols(SymbolReaper &SymReaper, + CheckerContext &C) const { for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(), E = SymReaper.dead_end(); I != E; ++I) { SymbolRef Sym = *I; @@ -416,8 +408,8 @@ void StreamChecker::evalDeadSymbols(CheckerContext &C,SymbolReaper &SymReaper) { ExplodedNode *N = C.generateSink(); if (N) { if (!BT_ResourceLeak) - BT_ResourceLeak = new BuiltinBug("Resource Leak", - "Opened File never closed. Potential Resource leak."); + BT_ResourceLeak.reset(new BuiltinBug("Resource Leak", + "Opened File never closed. Potential Resource leak.")); BugReport *R = new BugReport(*BT_ResourceLeak, BT_ResourceLeak->getDescription(), N); C.EmitReport(R); @@ -426,8 +418,8 @@ void StreamChecker::evalDeadSymbols(CheckerContext &C,SymbolReaper &SymReaper) { } } -void StreamChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, - ExprEngine &Eng) { +void StreamChecker::checkEndPath(EndOfFunctionNodeBuilder &B, + ExprEngine &Eng) const { const GRState *state = B.getState(); typedef llvm::ImmutableMap<SymbolRef, StreamState> SymMap; SymMap M = state->get<StreamState>(); @@ -435,11 +427,11 @@ void StreamChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, for (SymMap::iterator I = M.begin(), E = M.end(); I != E; ++I) { StreamState SS = I->second; if (SS.isOpened()) { - ExplodedNode *N = B.generateNode(state, tag, B.getPredecessor()); + ExplodedNode *N = B.generateNode(state); if (N) { if (!BT_ResourceLeak) - BT_ResourceLeak = new BuiltinBug("Resource Leak", - "Opened File never closed. Potential Resource leak."); + BT_ResourceLeak.reset(new BuiltinBug("Resource Leak", + "Opened File never closed. Potential Resource leak.")); BugReport *R = new BugReport(*BT_ResourceLeak, BT_ResourceLeak->getDescription(), N); Eng.getBugReporter().EmitReport(R); @@ -448,7 +440,7 @@ void StreamChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, } } -void StreamChecker::PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S) { +void StreamChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const { const Expr *RetE = S->getRetValue(); if (!RetE) return; @@ -468,3 +460,7 @@ void StreamChecker::PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S) { C.addTransition(state); } + +void ento::registerStreamChecker(CheckerManager &mgr) { + mgr.registerChecker<StreamChecker>(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp index a53ebb5..be4fbf6 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp @@ -13,10 +13,11 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/Basic/TargetInfo.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" +#include "clang/Basic/TargetInfo.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringSwitch.h" #include <fcntl.h> @@ -26,7 +27,7 @@ using namespace ento; using llvm::Optional; namespace { -class UnixAPIChecker : public CheckerVisitor<UnixAPIChecker> { +class UnixAPIChecker : public CheckerV2< check::PreStmt<CallExpr> > { enum SubChecks { OpenFn = 0, PthreadOnceFn = 1, @@ -34,27 +35,22 @@ class UnixAPIChecker : public CheckerVisitor<UnixAPIChecker> { NumChecks }; - BugType *BTypes[NumChecks]; + mutable BugType *BTypes[NumChecks]; public: - Optional<uint64_t> Val_O_CREAT; + mutable Optional<uint64_t> Val_O_CREAT; public: UnixAPIChecker() { memset(BTypes, 0, sizeof(*BTypes) * NumChecks); } - static void *getTag() { static unsigned tag = 0; return &tag; } + ~UnixAPIChecker() { + for (unsigned i=0; i != NumChecks; ++i) + delete BTypes[i]; + } - void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE); + void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; }; } //end anonymous namespace -static void RegisterUnixAPIChecker(ExprEngine &Eng) { - Eng.registerCheck(new UnixAPIChecker()); -} - -void ento::registerUnixAPIChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterUnixAPIChecker); -} - //===----------------------------------------------------------------------===// // Utility functions. //===----------------------------------------------------------------------===// @@ -69,7 +65,7 @@ static inline void LazyInitialize(BugType *&BT, const char *name) { // "open" (man 2 open) //===----------------------------------------------------------------------===// -static void CheckOpen(CheckerContext &C, UnixAPIChecker &UC, +static void CheckOpen(CheckerContext &C, const UnixAPIChecker &UC, const CallExpr *CE, BugType *&BT) { // The definition of O_CREAT is platform specific. We need a better way // of querying this information from the checking environment. @@ -141,7 +137,7 @@ static void CheckOpen(CheckerContext &C, UnixAPIChecker &UC, // pthread_once //===----------------------------------------------------------------------===// -static void CheckPthreadOnce(CheckerContext &C, UnixAPIChecker &, +static void CheckPthreadOnce(CheckerContext &C, const UnixAPIChecker &, const CallExpr *CE, BugType *&BT) { // This is similar to 'CheckDispatchOnce' in the MacOSXAPIChecker. @@ -186,7 +182,7 @@ static void CheckPthreadOnce(CheckerContext &C, UnixAPIChecker &, // FIXME: Eventually this should be rolled into the MallocChecker, but this // check is more basic and is valuable for widespread use. -static void CheckMallocZero(CheckerContext &C, UnixAPIChecker &UC, +static void CheckMallocZero(CheckerContext &C, const UnixAPIChecker &UC, const CallExpr *CE, BugType *&BT) { // Sanity check that malloc takes one argument. @@ -234,16 +230,16 @@ static void CheckMallocZero(CheckerContext &C, UnixAPIChecker &UC, // Central dispatch function. //===----------------------------------------------------------------------===// -typedef void (*SubChecker)(CheckerContext &C, UnixAPIChecker &UC, +typedef void (*SubChecker)(CheckerContext &C, const UnixAPIChecker &UC, const CallExpr *CE, BugType *&BT); namespace { class SubCheck { SubChecker SC; - UnixAPIChecker *UC; + const UnixAPIChecker *UC; BugType **BT; public: - SubCheck(SubChecker sc, UnixAPIChecker *uc, BugType *& bt) : SC(sc), UC(uc), - BT(&bt) {} + SubCheck(SubChecker sc, const UnixAPIChecker *uc, BugType *& bt) + : SC(sc), UC(uc), BT(&bt) {} SubCheck() : SC(NULL), UC(NULL), BT(NULL) {} void run(CheckerContext &C, const CallExpr *CE) const { @@ -253,7 +249,7 @@ namespace { }; } // end anonymous namespace -void UnixAPIChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) { +void UnixAPIChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const { // Get the callee. All the functions we care about are C functions // with simple identifiers. const GRState *state = C.getState(); @@ -280,3 +276,11 @@ void UnixAPIChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) { SC.run(C, CE); } + +//===----------------------------------------------------------------------===// +// Registration. +//===----------------------------------------------------------------------===// + +void ento::registerUnixAPIChecker(CheckerManager &mgr) { + mgr.registerChecker<UnixAPIChecker>(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp index 3038e29..1bc487a 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp @@ -14,15 +14,16 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" -#include "clang/AST/ParentMap.h" -#include "clang/Basic/Builtins.h" -#include "clang/Basic/SourceManager.h" +#include "clang/StaticAnalyzer/Core/CheckerV2.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" +#include "clang/AST/ParentMap.h" +#include "clang/Basic/Builtins.h" +#include "clang/Basic/SourceManager.h" #include "llvm/ADT/SmallPtrSet.h" // The number of CFGBlock pointers we want to reserve memory for. This is used @@ -33,40 +34,27 @@ using namespace clang; using namespace ento; namespace { -class UnreachableCodeChecker : public Checker { +class UnreachableCodeChecker : public CheckerV2<check::EndAnalysis> { public: - static void *getTag(); - void VisitEndAnalysis(ExplodedGraph &G, - BugReporter &B, - ExprEngine &Eng); + void checkEndAnalysis(ExplodedGraph &G, BugReporter &B, + ExprEngine &Eng) const; private: + typedef llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> CFGBlocksSet; + static inline const Stmt *getUnreachableStmt(const CFGBlock *CB); - void FindUnreachableEntryPoints(const CFGBlock *CB); + static void FindUnreachableEntryPoints(const CFGBlock *CB, + CFGBlocksSet &reachable, + CFGBlocksSet &visited); static bool isInvalidPath(const CFGBlock *CB, const ParentMap &PM); static inline bool isEmptyCFGBlock(const CFGBlock *CB); - - llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> reachable; - llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> visited; }; } -void *UnreachableCodeChecker::getTag() { - static int x = 0; - return &x; -} - -static void RegisterUnreachableCodeChecker(ExprEngine &Eng) { - Eng.registerCheck(new UnreachableCodeChecker()); -} - -void ento::registerUnreachableCodeChecker(CheckerManager &mgr) { - mgr.addCheckerRegisterFunction(RegisterUnreachableCodeChecker); -} - -void UnreachableCodeChecker::VisitEndAnalysis(ExplodedGraph &G, +void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G, BugReporter &B, - ExprEngine &Eng) { - // Bail out if we didn't cover all paths + ExprEngine &Eng) const { + CFGBlocksSet reachable, visited; + if (Eng.hasWorkRemaining()) return; @@ -109,7 +97,7 @@ void UnreachableCodeChecker::VisitEndAnalysis(ExplodedGraph &G, // Find the entry points for this block if (!visited.count(CB->getBlockID())) - FindUnreachableEntryPoints(CB); + FindUnreachableEntryPoints(CB, reachable, visited); // This block may have been pruned; check if we still want to report it if (reachable.count(CB->getBlockID())) @@ -155,7 +143,9 @@ void UnreachableCodeChecker::VisitEndAnalysis(ExplodedGraph &G, } // Recursively finds the entry point(s) for this dead CFGBlock. -void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB) { +void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB, + CFGBlocksSet &reachable, + CFGBlocksSet &visited) { visited.insert(CB->getBlockID()); for (CFGBlock::const_pred_iterator I = CB->pred_begin(), E = CB->pred_end(); @@ -166,7 +156,7 @@ void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB) { reachable.insert(CB->getBlockID()); if (!visited.count((*I)->getBlockID())) // If we haven't previously visited the unreachable predecessor, recurse - FindUnreachableEntryPoints(*I); + FindUnreachableEntryPoints(*I, reachable, visited); } } } @@ -226,3 +216,7 @@ bool UnreachableCodeChecker::isEmptyCFGBlock(const CFGBlock *CB) { && CB->size() == 0 // No statements && CB->getTerminator() == 0; // No terminator } + +void ento::registerUnreachableCodeChecker(CheckerManager &mgr) { + mgr.registerChecker<UnreachableCodeChecker>(); +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index 9a84045..672982a 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -1202,16 +1202,8 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD, //===----------------------------------------------------------------------===// // Methods for BugType and subclasses. //===----------------------------------------------------------------------===// -BugType::~BugType() { - // Free up the equivalence class objects. Observe that we get a pointer to - // the object first before incrementing the iterator, as destroying the - // node before doing so means we will read from freed memory. - for (iterator I = begin(), E = end(); I !=E; ) { - BugReportEquivClass *EQ = &*I; - ++I; - delete EQ; - } -} +BugType::~BugType() { } + void BugType::FlushReports(BugReporter &BR) {} //===----------------------------------------------------------------------===// @@ -1315,28 +1307,30 @@ void BugReporter::FlushReports() { return; // First flush the warnings for each BugType. This may end up creating new - // warnings and new BugTypes. Because ImmutableSet is a functional data - // structure, we do not need to worry about the iterators being invalidated. + // warnings and new BugTypes. + // FIXME: Only NSErrorChecker needs BugType's FlushReports. + // Turn NSErrorChecker into a proper checker and remove this. + llvm::SmallVector<const BugType*, 16> bugTypes; for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I) + bugTypes.push_back(*I); + for (llvm::SmallVector<const BugType*, 16>::iterator + I = bugTypes.begin(), E = bugTypes.end(); I != E; ++I) const_cast<BugType*>(*I)->FlushReports(*this); - // Iterate through BugTypes a second time. BugTypes may have been updated - // with new BugType objects and new warnings. - for (BugTypesTy::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I) { - BugType *BT = const_cast<BugType*>(*I); - - typedef llvm::FoldingSet<BugReportEquivClass> SetTy; - SetTy& EQClasses = BT->EQClasses; - - for (SetTy::iterator EI=EQClasses.begin(), EE=EQClasses.end(); EI!=EE;++EI){ - BugReportEquivClass& EQ = *EI; - FlushReport(EQ); - } - - // Delete the BugType object. - delete BT; + typedef llvm::FoldingSet<BugReportEquivClass> SetTy; + for (SetTy::iterator EI=EQClasses.begin(), EE=EQClasses.end(); EI!=EE;++EI){ + BugReportEquivClass& EQ = *EI; + FlushReport(EQ); } + // BugReporter owns and deletes only BugTypes created implicitly through + // EmitBasicReport. + // FIXME: There are leaks from checkers that assume that the BugTypes they + // create will be destroyed by the BugReporter. + for (llvm::StringMap<BugType*>::iterator + I = StrBugTypes.begin(), E = StrBugTypes.end(); I != E; ++I) + delete I->second; + // Remove all references to the BugType objects. BugTypes = F.getEmptySet(); } @@ -1632,11 +1626,11 @@ void BugReporter::EmitReport(BugReport* R) { BugType& BT = R->getBugType(); Register(&BT); void *InsertPos; - BugReportEquivClass* EQ = BT.EQClasses.FindNodeOrInsertPos(ID, InsertPos); + BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos); if (!EQ) { EQ = new BugReportEquivClass(R); - BT.EQClasses.InsertNode(EQ, InsertPos); + EQClasses.InsertNode(EQ, InsertPos); } else EQ->AddReport(R); @@ -1887,10 +1881,24 @@ void BugReporter::EmitBasicReport(llvm::StringRef name, llvm::StringRef str, SourceLocation Loc, SourceRange* RBeg, unsigned NumRanges) { - // 'BT' will be owned by BugReporter as soon as we call 'EmitReport'. - BugType *BT = new BugType(name, category); + // 'BT' is owned by BugReporter. + BugType *BT = getBugTypeForName(name, category); FullSourceLoc L = getContext().getFullLoc(Loc); RangedBugReport *R = new DiagBugReport(*BT, str, L); for ( ; NumRanges > 0 ; --NumRanges, ++RBeg) R->addRange(*RBeg); EmitReport(R); } + +BugType *BugReporter::getBugTypeForName(llvm::StringRef name, + llvm::StringRef category) { + llvm::SmallString<136> fullDesc; + llvm::raw_svector_ostream(fullDesc) << name << ":" << category; + llvm::StringMapEntry<BugType *> & + entry = StrBugTypes.GetOrCreateValue(fullDesc); + BugType *BT = entry.getValue(); + if (!BT) { + BT = new BugType(name, category); + entry.setValue(BT); + } + return BT; +} diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp index 1989b82..75d331a 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp @@ -13,11 +13,17 @@ #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/CheckerProvider.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/Analysis/ProgramPoint.h" #include "clang/AST/DeclBase.h" using namespace clang; using namespace ento; +//===----------------------------------------------------------------------===// +// Functions for running checkers for AST traversing.. +//===----------------------------------------------------------------------===// + void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, BugReporter &BR) { assert(D); @@ -33,53 +39,398 @@ void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) { DeclCheckerInfo &info = DeclCheckers[i]; if (info.IsForDeclFn(D)) - checkers->push_back(std::make_pair(info.Checker, info.CheckFn)); + checkers->push_back(info.CheckFn); } } assert(checkers); for (CachedDeclCheckers::iterator - I = checkers->begin(), E = checkers->end(); I != E; ++I) { - CheckerRef checker = I->first; - CheckDeclFunc fn = I->second; - fn(checker, D, mgr, BR); - } + I = checkers->begin(), E = checkers->end(); I != E; ++I) + (*I)(D, mgr, BR); } void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, BugReporter &BR) { assert(D && D->hasBody()); - for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i) { - CheckerRef checker = BodyCheckers[i].first; - CheckDeclFunc fn = BodyCheckers[i].second; - fn(checker, D, mgr, BR); + for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i) + BodyCheckers[i](D, mgr, BR); +} + +//===----------------------------------------------------------------------===// +// Functions for running checkers for path-sensitive checking. +//===----------------------------------------------------------------------===// + +template <typename CHECK_CTX> +static void expandGraphWithCheckers(CHECK_CTX checkCtx, + ExplodedNodeSet &Dst, + const ExplodedNodeSet &Src) { + + typename CHECK_CTX::CheckersTy::const_iterator + I = checkCtx.checkers_begin(), E = checkCtx.checkers_end(); + if (I == E) { + Dst.insert(Src); + return; + } + + ExplodedNodeSet Tmp1, Tmp2; + const ExplodedNodeSet *PrevSet = &Src; + + for (; I != E; ++I) { + ExplodedNodeSet *CurrSet = 0; + if (I+1 == E) + CurrSet = &Dst; + else { + CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1; + CurrSet->clear(); + } + + for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end(); + NI != NE; ++NI) + checkCtx.runChecker(*I, *CurrSet, *NI); + + // Update which NodeSet is the current one. + PrevSet = CurrSet; + } +} + +namespace { + struct CheckStmtContext { + typedef llvm::SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy; + bool IsPreVisit; + const CheckersTy &Checkers; + const Stmt *S; + ExprEngine &Eng; + + CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } + CheckersTy::const_iterator checkers_end() { return Checkers.end(); } + + CheckStmtContext(bool isPreVisit, const CheckersTy &checkers, + const Stmt *s, ExprEngine &eng) + : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng) { } + + void runChecker(CheckerManager::CheckStmtFunc checkFn, + ExplodedNodeSet &Dst, ExplodedNode *Pred) { + // FIXME: Remove respondsToCallback from CheckerContext; + CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, + IsPreVisit ? ProgramPoint::PreStmtKind : + ProgramPoint::PostStmtKind, 0, S); + checkFn(S, C); + } + }; +} + +/// \brief Run checkers for visiting Stmts. +void CheckerManager::runCheckersForStmt(bool isPreVisit, + ExplodedNodeSet &Dst, + const ExplodedNodeSet &Src, + const Stmt *S, + ExprEngine &Eng) { + CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit), + S, Eng); + expandGraphWithCheckers(C, Dst, Src); +} + +namespace { + struct CheckObjCMessageContext { + typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy; + bool IsPreVisit; + const CheckersTy &Checkers; + const ObjCMessage &Msg; + ExprEngine &Eng; + + CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } + CheckersTy::const_iterator checkers_end() { return Checkers.end(); } + + CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers, + const ObjCMessage &msg, ExprEngine &eng) + : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { } + + void runChecker(CheckerManager::CheckObjCMessageFunc checkFn, + ExplodedNodeSet &Dst, ExplodedNode *Pred) { + CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, + IsPreVisit ? ProgramPoint::PreStmtKind : + ProgramPoint::PostStmtKind, 0, + Msg.getOriginExpr()); + checkFn(Msg, C); + } + }; +} + +/// \brief Run checkers for visiting obj-c messages. +void CheckerManager::runCheckersForObjCMessage(bool isPreVisit, + ExplodedNodeSet &Dst, + const ExplodedNodeSet &Src, + const ObjCMessage &msg, + ExprEngine &Eng) { + CheckObjCMessageContext C(isPreVisit, + isPreVisit ? PreObjCMessageCheckers + : PostObjCMessageCheckers, + msg, Eng); + expandGraphWithCheckers(C, Dst, Src); +} + +namespace { + struct CheckLocationContext { + typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy; + const CheckersTy &Checkers; + SVal Loc; + bool IsLoad; + const Stmt *S; + ExprEngine &Eng; + + CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } + CheckersTy::const_iterator checkers_end() { return Checkers.end(); } + + CheckLocationContext(const CheckersTy &checkers, + SVal loc, bool isLoad, const Stmt *s, ExprEngine &eng) + : Checkers(checkers), Loc(loc), IsLoad(isLoad), S(s), Eng(eng) { } + + void runChecker(CheckerManager::CheckLocationFunc checkFn, + ExplodedNodeSet &Dst, ExplodedNode *Pred) { + CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, + IsLoad ? ProgramPoint::PreLoadKind : + ProgramPoint::PreStoreKind, 0, S); + checkFn(Loc, IsLoad, C); + } + }; +} + +/// \brief Run checkers for load/store of a location. +void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst, + const ExplodedNodeSet &Src, + SVal location, bool isLoad, + const Stmt *S, ExprEngine &Eng) { + CheckLocationContext C(LocationCheckers, location, isLoad, S, Eng); + expandGraphWithCheckers(C, Dst, Src); +} + +void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G, + BugReporter &BR, + ExprEngine &Eng) { + for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i) + EndAnalysisCheckers[i](G, BR, Eng); +} + +/// \brief Run checkers for end of path. +void CheckerManager::runCheckersForEndPath(EndOfFunctionNodeBuilder &B, + ExprEngine &Eng) { + for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) { + CheckEndPathFunc fn = EndPathCheckers[i]; + EndOfFunctionNodeBuilder specialB = B.withCheckerTag(fn.Checker); + fn(specialB, Eng); + } +} + +/// \brief Run checkers for live symbols. +void CheckerManager::runCheckersForLiveSymbols(const GRState *state, + SymbolReaper &SymReaper) { + for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i) + LiveSymbolsCheckers[i](state, SymReaper); +} + +namespace { + struct CheckDeadSymbolsContext { + typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy; + const CheckersTy &Checkers; + SymbolReaper &SR; + const Stmt *S; + ExprEngine &Eng; + + CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } + CheckersTy::const_iterator checkers_end() { return Checkers.end(); } + + CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr, + const Stmt *s, ExprEngine &eng) + : Checkers(checkers), SR(sr), S(s), Eng(eng) { } + + void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn, + ExplodedNodeSet &Dst, ExplodedNode *Pred) { + CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, + ProgramPoint::PostPurgeDeadSymbolsKind, 0, S); + checkFn(SR, C); + } + }; +} + +/// \brief Run checkers for dead symbols. +void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst, + const ExplodedNodeSet &Src, + SymbolReaper &SymReaper, + const Stmt *S, + ExprEngine &Eng) { + CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng); + expandGraphWithCheckers(C, Dst, Src); +} + +/// \brief True if at least one checker wants to check region changes. +bool CheckerManager::wantsRegionChangeUpdate(const GRState *state) { + for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) + if (RegionChangesCheckers[i].WantUpdateFn(state)) + return true; + + return false; +} + +/// \brief Run checkers for region changes. +const GRState * +CheckerManager::runCheckersForRegionChanges(const GRState *state, + const MemRegion * const *Begin, + const MemRegion * const *End) { + for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) { + // If any checker declares the state infeasible (or if it starts that way), + // bail out. + if (!state) + return NULL; + state = RegionChangesCheckers[i].CheckFn(state, Begin, End); } + return state; } -void CheckerManager::_registerForDecl(CheckerRef checker, CheckDeclFunc checkfn, +/// \brief Run checkers for evaluating a call. +/// Only one checker will evaluate the call. +void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst, + const ExplodedNodeSet &Src, + const CallExpr *CE, + ExprEngine &Eng, + GraphExpander *defaultEval) { + if (EvalCallCheckers.empty() && defaultEval == 0) { + Dst.insert(Src); + return; + } + + for (ExplodedNodeSet::iterator + NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) { + + ExplodedNode *Pred = *NI; + bool anyEvaluated = false; + for (std::vector<EvalCallFunc>::iterator + EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end(); + EI != EE; ++EI) { + ExplodedNodeSet checkDst; + CheckerContext C(checkDst, Eng.getBuilder(), Eng, Pred, EI->Checker, + ProgramPoint::PostStmtKind, 0, CE); + bool evaluated = (*EI)(CE, C); + assert(!(evaluated && anyEvaluated) + && "There are more than one checkers evaluating the call"); + if (evaluated) { + anyEvaluated = true; + Dst.insert(checkDst); +#ifdef NDEBUG + break; // on release don't check that no other checker also evals. +#endif + } + } + + if (!anyEvaluated) { + if (defaultEval) + defaultEval->expandGraph(Dst, Pred); + else + Dst.insert(Pred); + } + } +} + +//===----------------------------------------------------------------------===// +// Internal registration functions for AST traversing. +//===----------------------------------------------------------------------===// + +void CheckerManager::_registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn) { - DeclCheckerInfo info = { checker, checkfn, isForDeclFn }; + DeclCheckerInfo info = { checkfn, isForDeclFn }; DeclCheckers.push_back(info); } -void CheckerManager::_registerForBody(CheckerRef checker, - CheckDeclFunc checkfn) { - BodyCheckers.push_back(std::make_pair(checker, checkfn)); +void CheckerManager::_registerForBody(CheckDeclFunc checkfn) { + BodyCheckers.push_back(checkfn); } -void CheckerManager::registerCheckersToEngine(ExprEngine &eng) { - for (unsigned i = 0, e = Funcs.size(); i != e; ++i) - Funcs[i](eng); +//===----------------------------------------------------------------------===// +// Internal registration functions for path-sensitive checking. +//===----------------------------------------------------------------------===// + +void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn, + HandlesStmtFunc isForStmtFn) { + StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true }; + StmtCheckers.push_back(info); +} +void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn, + HandlesStmtFunc isForStmtFn) { + StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false }; + StmtCheckers.push_back(info); } -CheckerManager::~CheckerManager() { - for (unsigned i = 0, e = Checkers.size(); i != e; ++i) { - CheckerRef checker = Checkers[i].first; - Dtor dtor = Checkers[i].second; - dtor(checker); +void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) { + PreObjCMessageCheckers.push_back(checkfn); +} +void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) { + PostObjCMessageCheckers.push_back(checkfn); +} + +void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) { + LocationCheckers.push_back(checkfn); +} + +void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) { + EndAnalysisCheckers.push_back(checkfn); +} + +void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) { + EndPathCheckers.push_back(checkfn); +} + +void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) { + LiveSymbolsCheckers.push_back(checkfn); +} + +void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) { + DeadSymbolsCheckers.push_back(checkfn); +} + +void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn, + WantsRegionChangeUpdateFunc wantUpdateFn) { + RegionChangesCheckerInfo info = {checkfn, wantUpdateFn}; + RegionChangesCheckers.push_back(info); +} + +void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) { + EvalCallCheckers.push_back(checkfn); +} + +//===----------------------------------------------------------------------===// +// Implementation details. +//===----------------------------------------------------------------------===// + +CheckerManager::CachedStmtCheckers * +CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) { + assert(S); + + CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit); + CachedStmtCheckers *checkers = 0; + CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key); + if (CCI != CachedStmtCheckersMap.end()) { + checkers = &(CCI->second); + } else { + // Find the checkers that should run for this Stmt and cache them. + checkers = &CachedStmtCheckersMap[key]; + for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) { + StmtCheckerInfo &info = StmtCheckers[i]; + if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S)) + checkers->push_back(info.CheckFn); + } } + + assert(checkers); + return checkers; +} + +CheckerManager::~CheckerManager() { + for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i) + CheckerDtors[i](); } // Anchor for the vtable. CheckerProvider::~CheckerProvider() { } + +// Anchor for the vtable. +GraphExpander::~GraphExpander() { } diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp index 070042a..08a2068 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -718,13 +718,14 @@ EndOfFunctionNodeBuilder::~EndOfFunctionNodeBuilder() { } ExplodedNode* -EndOfFunctionNodeBuilder::generateNode(const GRState* State, const void *tag, - ExplodedNode* P) { +EndOfFunctionNodeBuilder::generateNode(const GRState* State, + ExplodedNode* P, const void *tag) { hasGeneratedNode = true; bool IsNew; ExplodedNode* Node = Eng.G->getNode(BlockEntrance(&B, - Pred->getLocationContext(), tag), State, &IsNew); + Pred->getLocationContext(), tag ? tag : Tag), + State, &IsNew); Node->addPredecessor(P ? P : Pred, *Eng.G); diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp index ecaff29..1bffa30 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp @@ -32,6 +32,11 @@ SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder) const { switch (E->getStmtClass()) { case Stmt::AddrLabelExprClass: return svalBuilder.makeLoc(cast<AddrLabelExpr>(E)); + case Stmt::OpaqueValueExprClass: { + const OpaqueValueExpr *ope = cast<OpaqueValueExpr>(E); + E = ope->getSourceExpr(); + continue; + } case Stmt::ParenExprClass: // ParenExprs are no-ops. E = cast<ParenExpr>(E)->getSubExpr(); diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index dbfebcc..e3e7ee9 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -175,7 +175,8 @@ public: virtual void Initialize(ASTContext &Context) { Ctx = &Context; - checkerMgr.reset(registerCheckers(Opts, PP.getDiagnostics())); + checkerMgr.reset(registerCheckers(Opts, PP.getLangOptions(), + PP.getDiagnostics())); Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(), PP.getLangOptions(), PD, CreateStoreMgr, CreateConstraintMgr, @@ -339,9 +340,6 @@ static void ActionExprEngine(AnalysisConsumer &C, AnalysisManager& mgr, return; ExprEngine Eng(mgr, TF.take()); - if (C.Opts.EnableExperimentalInternalChecks) - RegisterExperimentalInternalChecks(Eng); - RegisterNSErrorChecks(Eng.getBugReporter(), Eng, *D); if (C.Opts.EnableExperimentalChecks) diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp index 6625729..677e20c 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp @@ -12,12 +12,14 @@ //===----------------------------------------------------------------------===// #include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h" +#include "clang/StaticAnalyzer/Frontend/FrontendActions.h" #include "../Checkers/ClangSACheckerProvider.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/CheckerProvider.h" #include "clang/Frontend/AnalyzerOptions.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Basic/Diagnostic.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" @@ -25,8 +27,9 @@ using namespace clang; using namespace ento; CheckerManager *ento::registerCheckers(const AnalyzerOptions &opts, + const LangOptions &langOpts, Diagnostic &diags) { - llvm::OwningPtr<CheckerManager> checkerMgr(new CheckerManager()); + llvm::OwningPtr<CheckerManager> checkerMgr(new CheckerManager(langOpts)); llvm::SmallVector<CheckerOptInfo, 8> checkerOpts; for (unsigned i = 0, e = opts.CheckersControlList.size(); i != e; ++i) { @@ -48,3 +51,16 @@ CheckerManager *ento::registerCheckers(const AnalyzerOptions &opts, return checkerMgr.take(); } + +void ento::printCheckerHelp(llvm::raw_ostream &OS) { + OS << "OVERVIEW: Clang Static Analyzer Checkers List\n"; + OS << '\n'; + OS << "USAGE: -analyzer-checker <check1,check2,...>\n"; + OS << '\n'; + OS << "CHECKERS:\n"; + + llvm::OwningPtr<CheckerProvider> provider(createClangSACheckerProvider()); + provider->printHelp(OS); + + // FIXME: Load CheckerProviders from plugins. +} diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp index 448ebad..cd31e0c 100644 --- a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp +++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp @@ -542,7 +542,255 @@ void AsmWriterEmitter::EmitGetInstructionName(raw_ostream &O) { << "}\n\n#endif\n"; } +void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { + CodeGenTarget Target(Records); + Record *AsmWriter = Target.getAsmWriter(); + + O << "\n#ifdef PRINT_ALIAS_INSTR\n"; + O << "#undef PRINT_ALIAS_INSTR\n\n"; + + // Enumerate the register classes. + const std::vector<CodeGenRegisterClass> &RegisterClasses = + Target.getRegisterClasses(); + + O << "namespace { // Register classes\n"; + O << " enum RegClass {\n"; + + // Emit the register enum value for each RegisterClass. + for (unsigned I = 0, E = RegisterClasses.size(); I != E; ++I) { + if (I != 0) O << ",\n"; + O << " RC_" << RegisterClasses[I].TheDef->getName(); + } + + O << "\n };\n"; + O << "} // end anonymous namespace\n\n"; + + // Emit a function that returns 'true' if a regsiter is part of a particular + // register class. I.e., RAX is part of GR64 on X86. + O << "static bool regIsInRegisterClass" + << "(unsigned RegClass, unsigned Reg) {\n"; + + // Emit the switch that checks if a register belongs to a particular register + // class. + O << " switch (RegClass) {\n"; + O << " default: break;\n"; + + for (unsigned I = 0, E = RegisterClasses.size(); I != E; ++I) { + const CodeGenRegisterClass &RC = RegisterClasses[I]; + + // Give the register class a legal C name if it's anonymous. + std::string Name = RC.TheDef->getName(); + O << " case RC_" << Name << ":\n"; + + // Emit the register list now. + unsigned IE = RC.Elements.size(); + if (IE == 1) { + O << " if (Reg == " << getQualifiedName(RC.Elements[0]) << ")\n"; + O << " return true;\n"; + } else { + O << " switch (Reg) {\n"; + O << " default: break;\n"; + + for (unsigned II = 0; II != IE; ++II) { + Record *Reg = RC.Elements[II]; + O << " case " << getQualifiedName(Reg) << ":\n"; + } + + O << " return true;\n"; + O << " }\n"; + } + + O << " break;\n"; + } + + O << " }\n\n"; + O << " return false;\n"; + O << "}\n\n"; + + // Emit the method that prints the alias instruction. + std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); + bool isMC = AsmWriter->getValueAsBit("isMCAsmWriter"); + const char *MachineInstrClassName = isMC ? "MCInst" : "MachineInstr"; + + O << "bool " << Target.getName() << ClassName + << "::printAliasInstr(const " << MachineInstrClassName + << " *MI, raw_ostream &OS) {\n"; + + std::vector<Record*> AllInstAliases = + Records.getAllDerivedDefinitions("InstAlias"); + + // Create a map from the qualified name to a list of potential matches. + std::map<std::string, std::vector<CodeGenInstAlias*> > AliasMap; + for (std::vector<Record*>::iterator + I = AllInstAliases.begin(), E = AllInstAliases.end(); I != E; ++I) { + CodeGenInstAlias *Alias = new CodeGenInstAlias(*I, Target); + const Record *R = *I; + const DagInit *DI = R->getValueAsDag("ResultInst"); + const DefInit *Op = dynamic_cast<const DefInit*>(DI->getOperator()); + AliasMap[getQualifiedName(Op->getDef())].push_back(Alias); + } + + if (AliasMap.empty() || !isMC) { + // FIXME: Support MachineInstr InstAliases? + O << " return true;\n"; + O << "}\n\n"; + O << "#endif // PRINT_ALIAS_INSTR\n"; + return; + } + + O << " StringRef AsmString;\n"; + O << " std::map<StringRef, unsigned> OpMap;\n"; + O << " switch (MI->getOpcode()) {\n"; + O << " default: return true;\n"; + + for (std::map<std::string, std::vector<CodeGenInstAlias*> >::iterator + I = AliasMap.begin(), E = AliasMap.end(); I != E; ++I) { + std::vector<CodeGenInstAlias*> &Aliases = I->second; + + std::map<std::string, unsigned> CondCount; + std::map<std::string, std::string> BodyMap; + + std::string AsmString = ""; + + for (std::vector<CodeGenInstAlias*>::iterator + II = Aliases.begin(), IE = Aliases.end(); II != IE; ++II) { + const CodeGenInstAlias *CGA = *II; + AsmString = CGA->AsmString; + unsigned Indent = 8; + unsigned LastOpNo = CGA->ResultInstOperandIndex.size(); + + std::string Cond; + raw_string_ostream CondO(Cond); + + CondO << "if (MI->getNumOperands() == " << LastOpNo; + + std::map<StringRef, unsigned> OpMap; + bool CantHandle = false; + + for (unsigned i = 0, e = LastOpNo; i != e; ++i) { + const CodeGenInstAlias::ResultOperand &RO = CGA->ResultOperands[i]; + + switch (RO.Kind) { + default: assert(0 && "unexpected InstAlias operand kind"); + case CodeGenInstAlias::ResultOperand::K_Record: { + const Record *Rec = RO.getRecord(); + StringRef ROName = RO.getName(); + + if (Rec->isSubClassOf("RegisterClass")) { + CondO << " &&\n"; + CondO.indent(Indent) << "MI->getOperand(" << i << ").isReg() &&\n"; + if (OpMap.find(ROName) == OpMap.end()) { + OpMap[ROName] = i; + CondO.indent(Indent) + << "regIsInRegisterClass(RC_" + << CGA->ResultOperands[i].getRecord()->getName() + << ", MI->getOperand(" << i << ").getReg())"; + } else { + CondO.indent(Indent) + << "MI->getOperand(" << i + << ").getReg() == MI->getOperand(" + << OpMap[ROName] << ").getReg()"; + } + } else { + assert(Rec->isSubClassOf("Operand") && "Unexpected operand!"); + // FIXME: We need to handle these situations. + CantHandle = true; + break; + } + + break; + } + case CodeGenInstAlias::ResultOperand::K_Imm: + CondO << " &&\n"; + CondO.indent(Indent) << "MI->getOperand(" << i << ").getImm() == "; + CondO << CGA->ResultOperands[i].getImm(); + break; + case CodeGenInstAlias::ResultOperand::K_Reg: + CondO << " &&\n"; + CondO.indent(Indent) << "MI->getOperand(" << i << ").getReg() == "; + CondO << Target.getName() << "::" + << CGA->ResultOperands[i].getRegister()->getName(); + break; + } + + if (CantHandle) break; + } + + if (CantHandle) continue; + + CondO << ")"; + + std::string Body; + raw_string_ostream BodyO(Body); + + BodyO << " // " << CGA->Result->getAsString() << "\n"; + BodyO << " AsmString = \"" << AsmString << "\";\n"; + + for (std::map<StringRef, unsigned>::iterator + III = OpMap.begin(), IIE = OpMap.end(); III != IIE; ++III) + BodyO << " OpMap[\"" << III->first << "\"] = " + << III->second << ";\n"; + + ++CondCount[CondO.str()]; + BodyMap[CondO.str()] = BodyO.str(); + } + + std::string Code; + raw_string_ostream CodeO(Code); + + bool EmitElse = false; + for (std::map<std::string, unsigned>::iterator + II = CondCount.begin(), IE = CondCount.end(); II != IE; ++II) { + if (II->second != 1) continue; + CodeO << " "; + if (EmitElse) CodeO << "} else "; + CodeO << II->first << " {\n"; + CodeO << BodyMap[II->first]; + EmitElse = true; + } + + if (CodeO.str().empty()) continue; + + O << " case " << I->first << ":\n"; + O << CodeO.str(); + O << " }\n"; + O << " break;\n"; + } + + O << " }\n\n"; + + // Code that prints the alias, replacing the operands with the ones from the + // MCInst. + O << " if (AsmString.empty()) return true;\n"; + O << " std::pair<StringRef, StringRef> ASM = AsmString.split(' ');\n"; + O << " OS << '\\t' << ASM.first;\n"; + + O << " if (!ASM.second.empty()) {\n"; + O << " OS << '\\t';\n"; + O << " for (StringRef::iterator\n"; + O << " I = ASM.second.begin(), E = ASM.second.end(); I != E; ) {\n"; + O << " if (*I == '$') {\n"; + O << " StringRef::iterator Start = ++I;\n"; + O << " while (I != E &&\n"; + O << " ((*I >= 'a' && *I <= 'z') ||\n"; + O << " (*I >= 'A' && *I <= 'Z') ||\n"; + O << " (*I >= '0' && *I <= '9') ||\n"; + O << " *I == '_'))\n"; + O << " ++I;\n"; + O << " StringRef Name(Start, I - Start);\n"; + O << " printOperand(MI, OpMap[Name], OS);\n"; + O << " } else {\n"; + O << " OS << *I++;\n"; + O << " }\n"; + O << " }\n"; + O << " }\n\n"; + + O << " return false;\n"; + O << "}\n\n"; + + O << "#endif // PRINT_ALIAS_INSTR\n"; +} void AsmWriterEmitter::run(raw_ostream &O) { EmitSourceFileHeader("Assembly Writer Source Fragment", O); @@ -550,5 +798,6 @@ void AsmWriterEmitter::run(raw_ostream &O) { EmitPrintInstruction(O); EmitGetRegisterName(O); EmitGetInstructionName(O); + EmitPrintAliasInstruction(O); } diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.h b/contrib/llvm/utils/TableGen/AsmWriterEmitter.h index 9f7d776..5e8d6f5 100644 --- a/contrib/llvm/utils/TableGen/AsmWriterEmitter.h +++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.h @@ -38,6 +38,7 @@ private: void EmitPrintInstruction(raw_ostream &o); void EmitGetRegisterName(raw_ostream &o); void EmitGetInstructionName(raw_ostream &o); + void EmitPrintAliasInstruction(raw_ostream &O); AsmWriterInst *getAsmWriterInstByID(unsigned ID) const { assert(ID < NumberedInstructions.size()); diff --git a/contrib/llvm/utils/TableGen/ClangSACheckersEmitter.cpp b/contrib/llvm/utils/TableGen/ClangSACheckersEmitter.cpp index 3e49ab1..8865db3 100644 --- a/contrib/llvm/utils/TableGen/ClangSACheckersEmitter.cpp +++ b/contrib/llvm/utils/TableGen/ClangSACheckersEmitter.cpp @@ -148,6 +148,7 @@ void ClangSACheckersEmitter::run(raw_ostream &OS) { // Create a pseudo-group to hold this checker. std::string fullName = getCheckerFullName(R); GroupInfo &info = groupInfoByName[fullName]; + info.Hidden = R->getValueAsBit("Hidden"); recordGroupMap[R] = &info; info.Checkers.push_back(R); } else { diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp index ccd3efd..b0839c3 100644 --- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp +++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp @@ -34,7 +34,9 @@ using namespace llvm; MAP(E8, 39) \ MAP(F0, 40) \ MAP(F8, 41) \ - MAP(F9, 42) + MAP(F9, 42) \ + MAP(D0, 45) \ + MAP(D1, 46) // A clone of X86 since we can't depend on something that is generated. namespace X86Local { diff --git a/lib/clang/include/clang/Basic/Version.inc b/lib/clang/include/clang/Basic/Version.inc index 053c13b..1d6509c 100644 --- a/lib/clang/include/clang/Basic/Version.inc +++ b/lib/clang/include/clang/Basic/Version.inc @@ -5,6 +5,6 @@ #define CLANG_VERSION_MINOR 9 #define CLANG_VENDOR "FreeBSD " -#define CLANG_VENDOR_SUFFIX " 20110220" +#define CLANG_VENDOR_SUFFIX " 20110226" -#define SVN_REVISION "126079" +#define SVN_REVISION "126547" diff --git a/lib/clang/libclanganalysis/Makefile b/lib/clang/libclanganalysis/Makefile index 9f482e3..e122469 100644 --- a/lib/clang/libclanganalysis/Makefile +++ b/lib/clang/libclanganalysis/Makefile @@ -5,6 +5,7 @@ LIB= clanganalysis SRCDIR= tools/clang/lib/Analysis SRCS= AnalysisContext.cpp \ CFG.cpp \ + CFGReachabilityAnalysis.cpp \ CFGStmtMap.cpp \ CocoaConventions.cpp \ FormatString.cpp \ diff --git a/lib/clang/libclangstaticanalyzercheckers/Makefile b/lib/clang/libclangstaticanalyzercheckers/Makefile index 8dca68e..496d107 100644 --- a/lib/clang/libclangstaticanalyzercheckers/Makefile +++ b/lib/clang/libclangstaticanalyzercheckers/Makefile @@ -43,7 +43,7 @@ SRCS= AdjustedReturnValueChecker.cpp \ PthreadLockChecker.cpp \ ReturnPointerRangeChecker.cpp \ ReturnUndefChecker.cpp \ - StackAddrLeakChecker.cpp \ + StackAddrEscapeChecker.cpp \ StreamChecker.cpp \ UndefBranchChecker.cpp \ UndefCapturedBlockVarChecker.cpp \ |