diff options
84 files changed, 1498 insertions, 245 deletions
diff --git a/docs/Makefile b/docs/Makefile index 9b706c7f36d2..e9bbb28f68c4 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -48,11 +48,11 @@ generated:: doxygen install-html: $(PROJ_OBJ_DIR)/html.tar.gz $(Echo) Installing HTML documentation - $(Verb) $(MKDIR) $(PROJ_docsdir)/html - $(Verb) $(MKDIR) $(PROJ_docsdir)/html/img - $(Verb) $(DataInstall) $(HTML) $(PROJ_docsdir)/html -# $(Verb) $(DataInstall) $(IMAGES) $(PROJ_docsdir)/html/img - $(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/html.tar.gz $(PROJ_docsdir) + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_docsdir)/html + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_docsdir)/html/img + $(Verb) $(DataInstall) $(HTML) $(DESTDIR)$(PROJ_docsdir)/html +# $(Verb) $(DataInstall) $(IMAGES) $(DESTDIR)$(PROJ_docsdir)/html/img + $(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/html.tar.gz $(DESTDIR)$(PROJ_docsdir) $(PROJ_OBJ_DIR)/html.tar.gz: $(HTML) $(Echo) Packaging HTML documentation @@ -63,11 +63,11 @@ $(PROJ_OBJ_DIR)/html.tar.gz: $(HTML) install-doxygen: doxygen $(Echo) Installing doxygen documentation - $(Verb) $(MKDIR) $(PROJ_docsdir)/html/doxygen - $(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/doxygen.tar.gz $(PROJ_docsdir) + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_docsdir)/html/doxygen + $(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/doxygen.tar.gz $(DESTDIR)$(PROJ_docsdir) $(Verb) cd $(PROJ_OBJ_DIR)/doxygen && \ $(FIND) . -type f -exec \ - $(DataInstall) {} $(PROJ_docsdir)/html/doxygen \; + $(DataInstall) {} $(DESTDIR)$(PROJ_docsdir)/html/doxygen \; doxygen: regendoc $(PROJ_OBJ_DIR)/doxygen.tar.gz @@ -94,4 +94,4 @@ $(LLVM_SRC_ROOT)/docs/userloc.html: uninstall-local:: $(Echo) Uninstalling Documentation - $(Verb) $(RM) -rf $(PROJ_docsdir) + $(Verb) $(RM) -rf $(DESTDIR)$(PROJ_docsdir) diff --git a/docs/tools/Makefile b/docs/tools/Makefile index 12696ef0b659..91bc447c083f 100644 --- a/docs/tools/Makefile +++ b/docs/tools/Makefile @@ -84,9 +84,9 @@ EXTRA_DIST := $(POD) clean-local:: $(Verb) $(RM) -f pod2htm*.*~~ $(HTML) $(MAN) $(PS) -HTML_DIR := $(PROJ_docsdir)/html/clang -MAN_DIR := $(PROJ_mandir)/man1 -PS_DIR := $(PROJ_docsdir)/ps +HTML_DIR := $(DESTDIR)$(PROJ_docsdir)/html/clang +MAN_DIR := $(DESTDIR)$(PROJ_mandir)/man1 +PS_DIR := $(DESTDIR)$(PROJ_docsdir)/ps install-html:: $(HTML) $(Echo) Installing HTML Clang Tools Documentation diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 6767f52f4d83..0838a3d0ebe6 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -621,7 +621,8 @@ public: /// given interface decl and the conforming protocol list. QualType getObjCObjectPointerType(QualType OIT, ObjCProtocolDecl **ProtocolList = 0, - unsigned NumProtocols = 0); + unsigned NumProtocols = 0, + unsigned Quals = 0); /// getTypeOfType - GCC extension. QualType getTypeOfExprType(Expr *e); diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 7fb5f9daae17..0bdc6f54b7ca 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -268,7 +268,7 @@ public: /// setInvalidDecl - Indicates the Decl had a semantic error. This /// allows for graceful error recovery. - void setInvalidDecl(bool Invalid = true) { InvalidDecl = Invalid; } + void setInvalidDecl(bool Invalid = true); bool isInvalidDecl() const { return (bool) InvalidDecl; } /// isImplicit - Indicates whether the declaration was implicitly diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 9442ac328700..af233b81e0a5 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -240,6 +240,11 @@ BUILTIN(__builtin_isinf_sign, "i.", "nc") BUILTIN(__builtin_isnan, "i.", "nc") BUILTIN(__builtin_isnormal, "i.", "nc") +// FP signbit builtins +BUILTIN(__builtin_signbit, "id", "nc") +BUILTIN(__builtin_signbitf, "if", "nc") +BUILTIN(__builtin_signbitl, "iLd", "nc") + // Builtins for arithmetic. BUILTIN(__builtin_clz , "iUi" , "nc") BUILTIN(__builtin_clzl , "iULi" , "nc") diff --git a/include/clang/Basic/BuiltinsARM.def b/include/clang/Basic/BuiltinsARM.def new file mode 100644 index 000000000000..4973076ae24d --- /dev/null +++ b/include/clang/Basic/BuiltinsARM.def @@ -0,0 +1,20 @@ +//===--- BuiltinsARM.def - ARM Builtin function database ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ARM-specific builtin function database. Users of +// this file must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +// The format of this database matches clang/Basic/Builtins.def. + +// FIXME: This is just a placeholder. NEON intrinsics should be listed here. +BUILTIN(__builtin_thread_pointer, "v*", "") + +#undef BUILTIN diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 0062846a7a52..5d80528817c4 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -281,8 +281,8 @@ BUILTIN(__builtin_ia32_pmovzxwq128, "V2LLiV8s", "") BUILTIN(__builtin_ia32_pmuldq128, "V2LLiV4iV4i", "") BUILTIN(__builtin_ia32_pmulld128, "V4iV4iV4i", "") BUILTIN(__builtin_ia32_roundps, "V4fV4fi", "") -BUILTIN(__builtin_ia32_roundss, "V4fV4fi", "") -BUILTIN(__builtin_ia32_roundsd, "V2dV2di", "") +BUILTIN(__builtin_ia32_roundss, "V4fV4fV4fi", "") +BUILTIN(__builtin_ia32_roundsd, "V2dV2dV2di", "") BUILTIN(__builtin_ia32_roundpd, "V2dV2di", "") diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 9f77655052eb..badd64c31b56 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1587,11 +1587,12 @@ def err_undeclared_label_use : Error<"use of undeclared label '%0'">; def err_goto_into_protected_scope : Error<"illegal goto into protected scope">; def err_switch_into_protected_scope : Error< "illegal switch case into protected scope">; -def err_indirect_goto_in_protected_scope : Error< - "illegal indirect goto in protected scope, unknown effect on scopes">; -def err_addr_of_label_in_protected_scope : Error< +def err_indirect_goto_in_protected_scope : Warning< + "illegal indirect goto in protected scope, unknown effect on scopes">, + InGroup<DiagGroup<"label-address-scope">>; +def err_addr_of_label_in_protected_scope : Warning< "address taken of label in protected scope, jump to it would have " - "unknown effect on scope">; + "unknown effect on scope">, InGroup<DiagGroup<"label-address-scope">>; def note_protected_by_variable_init : Note< "jump bypasses variable initialization">; def note_protected_by_vla_typedef : Note< diff --git a/include/clang/Basic/TargetBuiltins.h b/include/clang/Basic/TargetBuiltins.h index d2e949501748..f1edd1d45162 100644 --- a/include/clang/Basic/TargetBuiltins.h +++ b/include/clang/Basic/TargetBuiltins.h @@ -14,12 +14,13 @@ #undef PPC namespace clang { - /// X86 builtins - namespace X86 { + + /// ARM builtins + namespace ARM { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, #define BUILTIN(ID, TYPE, ATTRS) BI##ID, -#include "clang/Basic/BuiltinsX86.def" +#include "clang/Basic/BuiltinsARM.def" LastTSBuiltin }; } @@ -33,6 +34,17 @@ namespace clang { LastTSBuiltin }; } + + /// X86 builtins + namespace X86 { + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#include "clang/Basic/BuiltinsX86.def" + LastTSBuiltin + }; + } + } // end namespace clang. #endif diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 522ac13b4e32..52e83f4045ef 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -336,8 +336,6 @@ KEYWORD(__declspec , KEYALL) KEYWORD(__cdecl , KEYALL) KEYWORD(__stdcall , KEYALL) KEYWORD(__fastcall , KEYALL) -KEYWORD(__ptr64 , KEYALL) -KEYWORD(__w64 , KEYALL) KEYWORD(__forceinline , KEYALL) // Altivec Extension. @@ -368,6 +366,8 @@ ALIAS("__volatile" , volatile , KEYALL) ALIAS("__volatile__" , volatile , KEYALL) // Microsoft extensions which should be disabled in strict conformance mode +KEYWORD(__ptr64 , KEYMS) +KEYWORD(__w64 , KEYMS) ALIAS("_asm" , asm , KEYMS) ALIAS("_cdecl" , __cdecl , KEYMS) ALIAS("_fastcall" , __fastcall , KEYMS) diff --git a/include/clang/Checker/PathSensitive/Environment.h b/include/clang/Checker/PathSensitive/Environment.h index 0852c31faeb6..6051654f4855 100644 --- a/include/clang/Checker/PathSensitive/Environment.h +++ b/include/clang/Checker/PathSensitive/Environment.h @@ -26,7 +26,6 @@ namespace clang { -class AnalysisContext; class EnvironmentManager; class ValueManager; class LiveVariables; @@ -41,10 +40,9 @@ private: // Data. BindingsTy ExprBindings; - AnalysisContext *ACtx; - Environment(BindingsTy eb, AnalysisContext *aCtx) - : ExprBindings(eb), ACtx(aCtx) {} + Environment(BindingsTy eb) + : ExprBindings(eb) {} public: typedef BindingsTy::iterator iterator; @@ -58,8 +56,6 @@ public: SVal GetSVal(const Stmt* Ex, ValueManager& ValMgr) const; - AnalysisContext &getAnalysisContext() const { return *ACtx; } - /// Profile - Profile the contents of an Environment object for use /// in a FoldingSet. static void Profile(llvm::FoldingSetNodeID& ID, const Environment* E) { @@ -86,8 +82,8 @@ public: EnvironmentManager(llvm::BumpPtrAllocator& Allocator) : F(Allocator) {} ~EnvironmentManager() {} - Environment getInitialEnvironment(AnalysisContext *ACtx) { - return Environment(F.GetEmptyMap(), ACtx); + Environment getInitialEnvironment() { + return Environment(F.GetEmptyMap()); } Environment BindExpr(Environment Env, const Stmt *S, SVal V, diff --git a/include/clang/Checker/PathSensitive/GRState.h b/include/clang/Checker/PathSensitive/GRState.h index 9194ee88a1a9..1178143bccdd 100644 --- a/include/clang/Checker/PathSensitive/GRState.h +++ b/include/clang/Checker/PathSensitive/GRState.h @@ -109,12 +109,6 @@ public: return *StateMgr; } - /// getAnalysisContext - Return the AnalysisContext associated with this - /// state. - AnalysisContext &getAnalysisContext() const { - return Env.getAnalysisContext(); - } - /// getEnvironment - Return the environment associated with this state. /// The environment is the mapping from expressions to values. const Environment& getEnvironment() const { return Env; } @@ -133,7 +127,6 @@ public: /// Profile - Profile the contents of a GRState object for use /// in a FoldingSet. static void Profile(llvm::FoldingSetNodeID& ID, const GRState* V) { - // FIXME: Do we need to include the AnalysisContext in the profile? V->Env.Profile(ID); ID.AddPointer(V->St); V->GDM.Profile(ID); @@ -337,12 +330,12 @@ public: }; // Pretty-printing. - void print(llvm::raw_ostream& Out, const char *nl = "\n", + void print(llvm::raw_ostream& Out, CFG &C, const char *nl = "\n", const char *sep = "") const; - void printStdErr() const; + void printStdErr(CFG &C) const; - void printDOT(llvm::raw_ostream& Out) const; + void printDOT(llvm::raw_ostream& Out, CFG &C) const; }; class GRStateSet { diff --git a/include/clang/Checker/PathSensitive/SymbolManager.h b/include/clang/Checker/PathSensitive/SymbolManager.h index d49f5e81c802..b6630c3d97d2 100644 --- a/include/clang/Checker/PathSensitive/SymbolManager.h +++ b/include/clang/Checker/PathSensitive/SymbolManager.h @@ -331,23 +331,20 @@ class SymbolReaper { SetTy TheLiving; SetTy TheDead; - LiveVariables& Liveness; + const LocationContext *LCtx; SymbolManager& SymMgr; - const StackFrameContext *CurrentStackFrame; public: - SymbolReaper(LiveVariables& liveness, SymbolManager& symmgr, - const StackFrameContext *currentStackFrame) - : Liveness(liveness), SymMgr(symmgr), CurrentStackFrame(currentStackFrame) - {} + SymbolReaper(const LocationContext *ctx, SymbolManager& symmgr) + : LCtx(ctx), SymMgr(symmgr) {} ~SymbolReaper() {} + const LocationContext *getLocationContext() const { return LCtx; } + bool isLive(SymbolRef sym); - bool isLive(const Stmt* Loc, const Stmt* ExprVal) const { - return Liveness.isLive(Loc, ExprVal); - } + bool isLive(const Stmt* Loc, const Stmt* ExprVal) const; bool isLive(const Stmt* Loc, const VarRegion *VR) const; diff --git a/include/clang/Driver/HostInfo.h b/include/clang/Driver/HostInfo.h index bf67c343f326..ca1ee9aa7766 100644 --- a/include/clang/Driver/HostInfo.h +++ b/include/clang/Driver/HostInfo.h @@ -80,6 +80,8 @@ const HostInfo *createDragonFlyHostInfo(const Driver &D, const llvm::Triple& Triple); const HostInfo *createLinuxHostInfo(const Driver &D, const llvm::Triple& Triple); +const HostInfo *createTCEHostInfo(const Driver &D, + const llvm::Triple& Triple); const HostInfo *createUnknownHostInfo(const Driver &D, const llvm::Triple& Triple); diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index b462a4d48ed5..3eb74ca59525 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -64,6 +64,7 @@ def clang_ignored_m_Group : OptionGroup<"<clang ignored m group>">, // , => _COMMA // = => _EQ // C++ => CXX +// . => _ // Developer Driver Options @@ -420,6 +421,8 @@ def mno_sse2 : Flag<"-mno-sse2">, Group<m_x86_Features_Group>; def mno_sse3 : Flag<"-mno-sse3">, Group<m_x86_Features_Group>; def mno_sse4a : Flag<"-mno-sse4a">, Group<m_x86_Features_Group>; def mno_sse4 : Flag<"-mno-sse4">, Group<m_x86_Features_Group>; +def mno_sse4_1 : Flag<"-mno-sse4.1">, Group<m_x86_Features_Group>; +def mno_sse4_2 : Flag<"-mno-sse4.2">, Group<m_x86_Features_Group>; def mno_sse : Flag<"-mno-sse">, Group<m_x86_Features_Group>; def mno_ssse3 : Flag<"-mno-ssse3">, Group<m_x86_Features_Group>; @@ -434,6 +437,8 @@ def msse2 : Flag<"-msse2">, Group<m_x86_Features_Group>; def msse3 : Flag<"-msse3">, Group<m_x86_Features_Group>; def msse4a : Flag<"-msse4a">, Group<m_x86_Features_Group>; def msse4 : Flag<"-msse4">, Group<m_x86_Features_Group>; +def msse4_1 : Flag<"-msse4.1">, Group<m_x86_Features_Group>; +def msse4_2 : Flag<"-msse4.2">, Group<m_x86_Features_Group>; def msse : Flag<"-msse">, Group<m_x86_Features_Group>; def mssse3 : Flag<"-mssse3">, Group<m_x86_Features_Group>; def mthumb : Flag<"-mthumb">, Group<m_Group>; diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 626a162371bd..7f11c85ae35b 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -88,11 +88,39 @@ class ASTUnit { /// \brief Temporary files that should be removed when the ASTUnit is /// destroyed. llvm::SmallVector<llvm::sys::Path, 4> TemporaryFiles; + + /// \brief Simple hack to allow us to assert that ASTUnit is not being + /// used concurrently, which is not supported. + /// + /// Clients should create instances of the ConcurrencyCheck class whenever + /// using the ASTUnit in a way that isn't intended to be concurrent, which is + /// just about any usage. + unsigned int ConcurrencyCheckValue; + static const unsigned int CheckLocked = 28573289; + static const unsigned int CheckUnlocked = 9803453; ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT - + public: + class ConcurrencyCheck { + volatile ASTUnit &Self; + + public: + explicit ConcurrencyCheck(ASTUnit &Self) + : Self(Self) + { + assert(Self.ConcurrencyCheckValue == CheckUnlocked && + "Concurrent access to ASTUnit!"); + Self.ConcurrencyCheckValue = CheckLocked; + } + + ~ConcurrencyCheck() { + Self.ConcurrencyCheckValue = CheckUnlocked; + } + }; + friend class ConcurrencyCheck; + ASTUnit(bool MainFileIsAST); ~ASTUnit(); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index e091bf10b629..d8c1c8485824 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2240,14 +2240,16 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols, /// the given interface decl and the conforming protocol list. QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT, ObjCProtocolDecl **Protocols, - unsigned NumProtocols) { + unsigned NumProtocols, + unsigned Quals) { llvm::FoldingSetNodeID ID; ObjCObjectPointerType::Profile(ID, InterfaceT, Protocols, NumProtocols); + Qualifiers Qs = Qualifiers::fromCVRMask(Quals); void *InsertPos = 0; if (ObjCObjectPointerType *QT = ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos)) - return QualType(QT, 0); + return getQualifiedType(QualType(QT, 0), Qs); // Sort the protocol list alphabetically to canonicalize it. QualType Canonical; @@ -2282,7 +2284,7 @@ QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT, Types.push_back(QType); ObjCObjectPointerTypes.InsertNode(QType, InsertPos); - return QualType(QType, 0); + return getQualifiedType(QualType(QType, 0), Qs); } /// getObjCInterfaceType - Return the unique reference to the type for the diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 47b7e7efb60e..9db6ae1329e4 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -46,6 +46,16 @@ const char *Decl::getDeclKindName() const { } } +void Decl::setInvalidDecl(bool Invalid) { + InvalidDecl = Invalid; + if (Invalid) { + // Defensive maneuver for ill-formed code: we're likely not to make it to + // a point where we set the access specifier, so default it to "public" + // to avoid triggering asserts elsewhere in the front end. + setAccess(AS_public); + } +} + const char *DeclContext::getDeclKindName() const { switch (DeclKind) { default: assert(0 && "Declaration context not in DeclNodes.def!"); diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index b8fe53599b52..ae6d5df673c0 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -734,8 +734,10 @@ void X86TargetInfo::getDefaultFeatures(const std::string &CPU, bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, const std::string &Name, bool Enabled) const { - // FIXME: This *really* should not be here. - if (!Features.count(Name) && Name != "sse4") + // FIXME: This *really* should not be here. We need some way of translating + // options into llvm subtarget features. + if (!Features.count(Name) && + (Name != "sse4" && Name != "sse4.2" && Name != "sse4.1")) return false; if (Enabled) { @@ -751,9 +753,12 @@ bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, else if (Name == "ssse3") Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = Features["ssse3"] = true; - else if (Name == "sse4") + else if (Name == "sse4" || Name == "sse4.2") Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = Features["ssse3"] = Features["sse41"] = Features["sse42"] = true; + else if (Name == "sse4.1") + Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] = + Features["ssse3"] = Features["sse41"] = true; else if (Name == "3dnow") Features["3dnowa"] = true; else if (Name == "3dnowa") @@ -775,6 +780,10 @@ bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, Features["ssse3"] = Features["sse41"] = Features["sse42"] = false; else if (Name == "sse4") Features["sse41"] = Features["sse42"] = false; + else if (Name == "sse4.2") + Features["sse42"] = false; + else if (Name == "sse4.1") + Features["sse41"] = Features["sse42"] = false; else if (Name == "3dnow") Features["3dnow"] = Features["3dnowa"] = false; else if (Name == "3dnowa") @@ -1207,6 +1216,8 @@ class ARMTargetInfo : public TargetInfo { unsigned SoftFloat : 1; unsigned SoftFloatABI : 1; + static const Builtin::Info BuiltinInfo[]; + public: ARMTargetInfo(const std::string &TripleStr) : TargetInfo(TripleStr), ABI("aapcs-linux"), CPU("arm1136j-s") @@ -1393,9 +1404,8 @@ public: } virtual void getTargetBuiltins(const Builtin::Info *&Records, unsigned &NumRecords) const { - // FIXME: Implement. - Records = 0; - NumRecords = 0; + Records = BuiltinInfo; + NumRecords = clang::ARM::LastTSBuiltin-Builtin::FirstTSBuiltin; } virtual const char *getVAListDeclaration() const { return "typedef char* __builtin_va_list;"; @@ -1460,6 +1470,12 @@ void ARMTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases, Aliases = GCCRegAliases; NumAliases = llvm::array_lengthof(GCCRegAliases); } + +const Builtin::Info ARMTargetInfo::BuiltinInfo[] = { +#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, false }, +#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER, false }, +#include "clang/Basic/BuiltinsARM.def" +}; } // end anonymous namespace. @@ -1892,9 +1908,10 @@ namespace { FloatFormat = &llvm::APFloat::IEEEsingle; DoubleFormat = &llvm::APFloat::IEEEsingle; LongDoubleFormat = &llvm::APFloat::IEEEsingle; - DescriptionString = "E-p:32:32:32-a0:32:32" - "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64" - "-f32:32:32-f64:32:64-n32"; + DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:32-" + "i16:16:32-i32:32:32-i64:32:32-" + "f32:32:32-f64:64:64-v64:64:64-" + "v128:128:128-a0:0:64-n32"; } virtual void getTargetDefines(const LangOptions &Opts, diff --git a/lib/Basic/Version.cpp b/lib/Basic/Version.cpp index 4d903055b5b9..dc87d148ed34 100644 --- a/lib/Basic/Version.cpp +++ b/lib/Basic/Version.cpp @@ -45,7 +45,7 @@ std::string getClangRevision() { std::string revision; llvm::raw_string_ostream OS(revision); OS << strtol(SVN_REVISION, 0, 10); - return revision; + return OS.str(); } #endif return ""; @@ -58,7 +58,7 @@ std::string getClangFullRepositoryVersion() { const std::string &Revision = getClangRevision(); if (!Revision.empty()) OS << ' ' << Revision; - return buf; + return OS.str(); } std::string getClangFullVersion() { @@ -69,7 +69,7 @@ std::string getClangFullVersion() { #endif OS << "clang version " CLANG_VERSION_STRING " (" << getClangFullRepositoryVersion() << ')'; - return buf; + return OS.str(); } } // end namespace clang diff --git a/lib/Checker/Environment.cpp b/lib/Checker/Environment.cpp index c2c9190fc9ff..671cf89119f3 100644 --- a/lib/Checker/Environment.cpp +++ b/lib/Checker/Environment.cpp @@ -78,12 +78,12 @@ Environment EnvironmentManager::BindExpr(Environment Env, const Stmt *S, if (V.isUnknown()) { if (Invalidate) - return Environment(F.Remove(Env.ExprBindings, S), Env.ACtx); + return Environment(F.Remove(Env.ExprBindings, S)); else return Env; } - return Environment(F.Add(Env.ExprBindings, S, V), Env.ACtx); + return Environment(F.Add(Env.ExprBindings, S, V)); } namespace { @@ -109,12 +109,12 @@ EnvironmentManager::RemoveDeadBindings(Environment Env, const Stmt *S, const GRState *ST, llvm::SmallVectorImpl<const MemRegion*> &DRoots) { - CFG &C = *Env.getAnalysisContext().getCFG(); + CFG &C = *SymReaper.getLocationContext()->getCFG(); // We construct a new Environment object entirely, as this is cheaper than // individually removing all the subexpression bindings (which will greatly // outnumber block-level expression bindings). - Environment NewEnv = getInitialEnvironment(&Env.getAnalysisContext()); + Environment NewEnv = getInitialEnvironment(); // Iterate over the block-expr bindings. for (Environment::iterator I = Env.begin(), E = Env.end(); diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index ad229c7b8fbc..2ea689e56a82 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -477,8 +477,9 @@ void GRExprEngine::ProcessStmt(CFGElement CE, GRStmtNodeBuilder& builder) { // Create the cleaned state. const ExplodedNode *BasePred = Builder->getBasePredecessor(); - SymbolReaper SymReaper(BasePred->getLiveVariables(), SymMgr, - BasePred->getLocationContext()->getCurrentStackFrame()); + + SymbolReaper SymReaper(BasePred->getLocationContext(), SymMgr); + CleanedState = AMgr.shouldPurgeDead() ? StateMgr.RemoveDeadBindings(EntryNode->getState(), CurrentStmt, SymReaper) : EntryNode->getState(); @@ -3319,7 +3320,7 @@ struct DOTGraphTraits<ExplodedNode*> : Out << "\\|StateID: " << (void*) N->getState() << "\\|"; const GRState *state = N->getState(); - state->printDOT(Out); + state->printDOT(Out, *N->getLocationContext()->getCFG()); Out << "\\l"; return Out.str(); diff --git a/lib/Checker/GRState.cpp b/lib/Checker/GRState.cpp index 592f930316e1..97ede1d480f9 100644 --- a/lib/Checker/GRState.cpp +++ b/lib/Checker/GRState.cpp @@ -99,7 +99,7 @@ const GRState *GRState::BindExpr(const Stmt* Ex, SVal V, bool Invalidate) const{ const GRState* GRStateManager::getInitialState(const LocationContext *InitLoc) { GRState State(this, - EnvMgr.getInitialEnvironment(InitLoc->getAnalysisContext()), + EnvMgr.getInitialEnvironment(), StoreMgr->getInitialStore(InitLoc), GDMFactory.GetEmptyMap()); @@ -131,14 +131,12 @@ const GRState* GRState::makeWithStore(Store store) const { // State pretty-printing. //===----------------------------------------------------------------------===// -void GRState::print(llvm::raw_ostream& Out, const char* nl, +void GRState::print(llvm::raw_ostream& Out, CFG &C, const char* nl, const char* sep) const { // Print the store. GRStateManager &Mgr = getStateManager(); Mgr.getStoreManager().print(getStore(), Out, nl, sep); - CFG &C = *getAnalysisContext().getCFG(); - // Print Subexpression bindings. bool isFirst = true; @@ -186,12 +184,12 @@ void GRState::print(llvm::raw_ostream& Out, const char* nl, } } -void GRState::printDOT(llvm::raw_ostream& Out) const { - print(Out, "\\l", "\\|"); +void GRState::printDOT(llvm::raw_ostream& Out, CFG &C) const { + print(Out, C, "\\l", "\\|"); } -void GRState::printStdErr() const { - print(llvm::errs()); +void GRState::printStdErr(CFG &C) const { + print(llvm::errs(), C); } //===----------------------------------------------------------------------===// diff --git a/lib/Checker/SymbolManager.cpp b/lib/Checker/SymbolManager.cpp index f2d630cdf64b..65a46e31fefa 100644 --- a/lib/Checker/SymbolManager.cpp +++ b/lib/Checker/SymbolManager.cpp @@ -215,13 +215,17 @@ bool SymbolReaper::isLive(SymbolRef sym) { return isa<SymbolRegionValue>(sym); } +bool SymbolReaper::isLive(const Stmt* Loc, const Stmt* ExprVal) const { + return LCtx->getLiveVariables()->isLive(Loc, ExprVal); +} + bool SymbolReaper::isLive(const Stmt *Loc, const VarRegion *VR) const { const StackFrameContext *SFC = VR->getStackFrame(); - if (SFC == CurrentStackFrame) - return Liveness.isLive(Loc, VR->getDecl()); + if (SFC == LCtx->getCurrentStackFrame()) + return LCtx->getLiveVariables()->isLive(Loc, VR->getDecl()); else - return SFC->isParentOf(CurrentStackFrame); + return SFC->isParentOf(LCtx->getCurrentStackFrame()); } SymbolVisitor::~SymbolVisitor() {} diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 7076067e4381..c10a401d8abf 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -154,7 +154,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { { // C = BuildBlockStructInitlist(); - unsigned int flags = BLOCK_HAS_OBJC_TYPE; + unsigned int flags = BLOCK_HAS_SIGNATURE; // We run this first so that we set BlockHasCopyDispose from the entire // block literal. @@ -184,6 +184,18 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { Elts[0] = C; // __flags + { + QualType BPT = BE->getType(); + const FunctionType *ftype = BPT->getPointeeType()->getAs<FunctionType>(); + QualType ResultType = ftype->getResultType(); + + CallArgList Args; + CodeGenTypes &Types = CGM.getTypes(); + const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, Args, + CC_Default, false); + if (CGM.ReturnTypeUsesSret(FnInfo)) + flags |= BLOCK_USE_STRET; + } const llvm::IntegerType *IntTy = cast<llvm::IntegerType>( CGM.getTypes().ConvertType(CGM.getContext().IntTy)); C = llvm::ConstantInt::get(IntTy, flags); @@ -200,6 +212,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { // Optimize to being a global block. Elts[0] = CGM.getNSConcreteGlobalBlock(); + Elts[1] = llvm::ConstantInt::get(IntTy, flags|BLOCK_IS_GLOBAL); C = llvm::ConstantStruct::get(VMContext, Elts, false); @@ -604,7 +617,7 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) { // Flags LiteralFields[1] = - llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_OBJC_TYPE); + llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE); // Reserved LiteralFields[2] = llvm::Constant::getNullValue(IntTy); diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h index 39f26f8b1363..e91319f6ddab 100644 --- a/lib/CodeGen/CGBlocks.h +++ b/lib/CodeGen/CGBlocks.h @@ -54,10 +54,12 @@ public: BLOCK_HAS_COPY_DISPOSE = (1 << 25), BLOCK_HAS_CXX_OBJ = (1 << 26), BLOCK_IS_GLOBAL = (1 << 28), - BLOCK_HAS_OBJC_TYPE = (1 << 30) + BLOCK_USE_STRET = (1 << 29), + BLOCK_HAS_SIGNATURE = (1 << 30) }; }; + class BlockModule : public BlockBase { ASTContext &Context; llvm::Module &TheModule; diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 0f5e90fb15aa..706e4411fc79 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -387,6 +387,22 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Value *Result = getTargetHooks().encodeReturnAddress(*this, Address); return RValue::get(Result); } + case Builtin::BI__builtin_dwarf_sp_column: { + const llvm::IntegerType *Ty + = cast<llvm::IntegerType>(ConvertType(E->getType())); + int Column = getTargetHooks().getDwarfEHStackPointer(CGM); + if (Column == -1) { + CGM.ErrorUnsupported(E, "__builtin_dwarf_sp_column"); + return RValue::get(llvm::UndefValue::get(Ty)); + } + return RValue::get(llvm::ConstantInt::get(Ty, Column, true)); + } + case Builtin::BI__builtin_init_dwarf_reg_size_table: { + Value *Address = EmitScalarExpr(E->getArg(0)); + if (getTargetHooks().initDwarfEHRegSizeTable(*this, Address)) + CGM.ErrorUnsupported(E, "__builtin_init_dwarf_reg_size_table"); + return RValue::get(llvm::UndefValue::get(ConvertType(E->getType()))); + } case Builtin::BI__builtin_eh_return: { Value *Int = EmitScalarExpr(E->getArg(0)); Value *Ptr = EmitScalarExpr(E->getArg(1)); @@ -666,6 +682,23 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Value *F = CGM.getIntrinsic(Intrinsic::pow, &ArgType, 1); return RValue::get(Builder.CreateCall2(F, Base, Exponent, "tmp")); } + + case Builtin::BI__builtin_signbit: + case Builtin::BI__builtin_signbitf: + case Builtin::BI__builtin_signbitl: { + LLVMContext &C = CGM.getLLVMContext(); + + Value *Arg = EmitScalarExpr(E->getArg(0)); + const llvm::Type *ArgTy = Arg->getType(); + if (ArgTy->isPPC_FP128Ty()) + break; // FIXME: I'm not sure what the right implementation is here. + int ArgWidth = ArgTy->getPrimitiveSizeInBits(); + const llvm::Type *ArgIntTy = llvm::IntegerType::get(C, ArgWidth); + Value *BCArg = Builder.CreateBitCast(Arg, ArgIntTy); + Value *ZeroCmp = llvm::Constant::getNullValue(ArgIntTy); + Value *Result = Builder.CreateICmpSLT(BCArg, ZeroCmp); + return RValue::get(Builder.CreateZExt(Result, ConvertType(E->getType()))); + } } // If this is an alias for a libm function (e.g. __builtin_sin) turn it into @@ -735,6 +768,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { switch (Target.getTriple().getArch()) { + case llvm::Triple::arm: + case llvm::Triple::thumb: + return EmitARMBuiltinExpr(BuiltinID, E); case llvm::Triple::x86: case llvm::Triple::x86_64: return EmitX86BuiltinExpr(BuiltinID, E); @@ -746,6 +782,18 @@ Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID, } } +Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, + const CallExpr *E) { + switch (BuiltinID) { + default: return 0; + + case ARM::BI__builtin_thread_pointer: { + Value *AtomF = CGM.getIntrinsic(Intrinsic::arm_thread_pointer, 0, 0); + return Builder.CreateCall(AtomF); + } + } +} + Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E) { diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 4889fc08f488..7752cf79a28d 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -142,6 +142,12 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl, return true; } + llvm::GlobalValue::LinkageTypes TargetLinkage + = getFunctionLinkage(cast<FunctionDecl>(TargetDecl.getDecl())); + + if (llvm::GlobalValue::isWeakForLinker(TargetLinkage)) + return true; + // Derive the type for the alias. const llvm::PointerType *AliasType = getTypes().GetFunctionType(AliasDecl)->getPointerTo(); diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 030d2c9c9f84..dc9ecd64f4e4 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1062,6 +1062,16 @@ static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF, LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { const NamedDecl *ND = E->getDecl(); + if (ND->hasAttr<WeakRefAttr>()) { + const ValueDecl* VD = cast<ValueDecl>(ND); + llvm::Constant *Aliasee = CGM.GetWeakRefReference(VD); + + Qualifiers Quals = MakeQualifiers(E->getType()); + LValue LV = LValue::MakeAddr(Aliasee, Quals); + + return LV; + } + if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) { // Check if this is a global variable. diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 3df552d75bb6..f0d82a8f0dc6 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -761,7 +761,9 @@ public: return C; } case Expr::DeclRefExprClass: { - NamedDecl *Decl = cast<DeclRefExpr>(E)->getDecl(); + ValueDecl *Decl = cast<DeclRefExpr>(E)->getDecl(); + if (Decl->hasAttr<WeakRefAttr>()) + return CGM.GetWeakRefReference(Decl); if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl)) return CGM.GetAddrOfFunction(FD); if (const VarDecl* VD = dyn_cast<VarDecl>(Decl)) { diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index db0998b4dedc..7e26971414b4 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1888,6 +1888,8 @@ LValue CodeGenFunction::EmitObjCIsaExpr(const ObjCIsaExpr *E) { V = CreateTempAlloca(ClassPtrTy, "resval"); llvm::Value *Src = EmitScalarExpr(BaseExpr); Builder.CreateStore(Src, V); + LValue LV = LValue::MakeAddr(V, MakeQualifiers(E->getType())); + V = ScalarExprEmitter(*this).EmitLoadOfLValue(LV, E->getType()); } else { if (E->isArrow()) diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 008a480b9c12..a889e55a9e80 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -915,18 +915,17 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) { TargetInfo::ConstraintInfo Info(S.getOutputConstraint(i), S.getOutputName(i)); - assert(Target.validateOutputConstraint(Info) && - "Failed to parse output constraint"); + bool IsValid = Target.validateOutputConstraint(Info); (void)IsValid; + assert(IsValid && "Failed to parse output constraint"); OutputConstraintInfos.push_back(Info); } for (unsigned i = 0, e = S.getNumInputs(); i != e; i++) { TargetInfo::ConstraintInfo Info(S.getInputConstraint(i), S.getInputName(i)); - assert(Target.validateInputConstraint(OutputConstraintInfos.data(), - S.getNumOutputs(), - Info) && - "Failed to parse input constraint"); + bool IsValid = Target.validateInputConstraint(OutputConstraintInfos.data(), + S.getNumOutputs(), Info); + assert(IsValid && "Failed to parse input constraint"); (void)IsValid; InputConstraintInfos.push_back(Info); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index d582c0def346..88d641330009 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1122,6 +1122,7 @@ public: /// is unhandled by the current target. llvm::Value *EmitTargetBuiltinExpr(unsigned BuiltinID, const CallExpr *E); + llvm::Value *EmitARMBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitPPCBuiltinExpr(unsigned BuiltinID, const CallExpr *E); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 91c7322c6767..d6a56dad0ba5 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -33,6 +33,7 @@ #include "llvm/Module.h" #include "llvm/Intrinsics.h" #include "llvm/LLVMContext.h" +#include "llvm/ADT/Triple.h" #include "llvm/Target/TargetData.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; @@ -89,6 +90,10 @@ void CodeGenModule::Release() { EmitLLVMUsed(); } +bool CodeGenModule::isTargetDarwin() const { + return getContext().Target.getTriple().getOS() == llvm::Triple::Darwin; +} + /// ErrorUnsupported - Print out an error that codegen doesn't support the /// specified stmt yet. void CodeGenModule::ErrorUnsupported(const Stmt *S, const char *Type, @@ -619,9 +624,41 @@ bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) { return false; } +llvm::Constant *CodeGenModule::GetWeakRefReference(const ValueDecl *VD) { + const AliasAttr *AA = VD->getAttr<AliasAttr>(); + assert(AA && "No alias?"); + + const llvm::Type *DeclTy = getTypes().ConvertTypeForMem(VD->getType()); + + // Unique the name through the identifier table. + const char *AliaseeName = + getContext().Idents.get(AA->getAliasee()).getNameStart(); + + // See if there is already something with the target's name in the module. + llvm::GlobalValue *Entry = GlobalDeclMap[AliaseeName]; + + llvm::Constant *Aliasee; + if (isa<llvm::FunctionType>(DeclTy)) + Aliasee = GetOrCreateLLVMFunction(AliaseeName, DeclTy, GlobalDecl()); + else + Aliasee = GetOrCreateLLVMGlobal(AliaseeName, + llvm::PointerType::getUnqual(DeclTy), 0); + if (!Entry) { + llvm::GlobalValue* F = cast<llvm::GlobalValue>(Aliasee); + F->setLinkage(llvm::Function::ExternalWeakLinkage); + WeakRefReferences.insert(F); + } + + return Aliasee; +} + void CodeGenModule::EmitGlobal(GlobalDecl GD) { const ValueDecl *Global = cast<ValueDecl>(GD.getDecl()); + // Weak references don't produce any output by themselves. + if (Global->hasAttr<WeakRefAttr>()) + return; + // If this is an alias definition (which otherwise looks like a declaration) // emit it now. if (Global->hasAttr<AliasAttr>()) @@ -708,6 +745,14 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName, // Lookup the entry, lazily creating it if necessary. llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName]; if (Entry) { + if (WeakRefReferences.count(Entry)) { + const FunctionDecl *FD = cast_or_null<FunctionDecl>(D.getDecl()); + if (FD && !FD->hasAttr<WeakAttr>()) + Entry->setLinkage(llvm::Function::ExternalLinkage); + + WeakRefReferences.erase(Entry); + } + if (Entry->getType()->getElementType() == Ty) return Entry; @@ -753,17 +798,17 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName, // synthesized. else if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) { if (CD->isImplicit()) { - assert (CD->isUsed()); + assert(CD->isUsed() && "Sema doesn't consider constructor as used."); DeferredDeclsToEmit.push_back(D); } } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) { if (DD->isImplicit()) { - assert (DD->isUsed()); + assert(DD->isUsed() && "Sema doesn't consider destructor as used."); DeferredDeclsToEmit.push_back(D); } } else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { if (MD->isCopyAssignment() && MD->isImplicit()) { - assert (MD->isUsed()); + assert(MD->isUsed() && "Sema doesn't consider CopyAssignment as used."); DeferredDeclsToEmit.push_back(D); } } @@ -817,6 +862,13 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMGlobal(const char *MangledName, // Lookup the entry, lazily creating it if necessary. llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName]; if (Entry) { + if (WeakRefReferences.count(Entry)) { + if (D && !D->hasAttr<WeakAttr>()) + Entry->setLinkage(llvm::Function::ExternalLinkage); + + WeakRefReferences.erase(Entry); + } + if (Entry->getType() == Ty) return Entry; @@ -1203,7 +1255,7 @@ static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old, void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) { const FunctionDecl *D = cast<FunctionDecl>(GD.getDecl()); const llvm::FunctionType *Ty = getTypes().GetFunctionType(GD); - + getMangleContext().mangleInitDiscriminator(); // Get or create the prototype for the function. llvm::Constant *Entry = GetAddrOfFunction(GD, Ty); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index ac8332647b77..c86f8b45bcdd 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -29,6 +29,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/ValueHandle.h" #include <list> @@ -117,6 +118,11 @@ class CodeGenModule : public BlockModule { /// pointer lookups instead of full string lookups. llvm::DenseMap<const char*, llvm::GlobalValue*> GlobalDeclMap; + // WeakRefReferences - A set of references that have only been seen via + // a weakref so far. This is used to remove the weak of the reference if we ever + // see a direct reference or a definition. + llvm::SmallPtrSet<llvm::GlobalValue*, 10> WeakRefReferences; + /// \brief Contains the strings used for mangled names. /// /// FIXME: Eventually, this should map from the semantic/canonical @@ -198,6 +204,7 @@ public: const llvm::TargetData &getTargetData() const { return TheTargetData; } llvm::LLVMContext &getLLVMContext() { return VMContext; } const TargetCodeGenInfo &getTargetCodeGenInfo() const; + bool isTargetDarwin() const; /// getDeclVisibilityMode - Compute the visibility of the decl \arg D. LangOptions::VisibilityMode getDeclVisibilityMode(const Decl *D) const; @@ -243,6 +250,9 @@ public: void BuildThunksForVirtual(GlobalDecl GD); void BuildThunksForVirtualRecursive(GlobalDecl GD, GlobalDecl BaseOGD); + /// GetWeakRefReference - Get a reference to the target of VD. + llvm::Constant *GetWeakRefReference(const ValueDecl *VD); + /// BuildThunk - Build a thunk for the given method. llvm::Constant *BuildThunk(GlobalDecl GD, bool Extern, const ThunkAdjustment &ThisAdjustment); diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 64743c7696f7..20d54b34105d 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -37,7 +37,19 @@ using namespace clang; using namespace CodeGen; namespace { - + +static const DeclContext *GetLocalClassFunctionDeclContext( + const DeclContext *DC) { + if (isa<CXXRecordDecl>(DC)) { + while (!DC->isNamespace() && !DC->isTranslationUnit() && + !isa<FunctionDecl>(DC)) + DC = DC->getParent(); + if (isa<FunctionDecl>(DC)) + return DC; + } + return 0; +} + static const CXXMethodDecl *getStructor(const CXXMethodDecl *MD) { assert((isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) && "Passed in decl is not a ctor or dtor!"); @@ -61,7 +73,7 @@ class CXXNameMangler { const CXXMethodDecl *Structor; unsigned StructorType; - + llvm::DenseMap<uintptr_t, unsigned> Substitutions; ASTContext &getASTContext() const { return Context.getASTContext(); } @@ -128,11 +140,12 @@ private: void mangleUnscopedTemplateName(const TemplateDecl *ND); void mangleSourceName(const IdentifierInfo *II); void mangleLocalName(const NamedDecl *ND); - void mangleNestedName(const NamedDecl *ND, const DeclContext *DC); + void mangleNestedName(const NamedDecl *ND, const DeclContext *DC, + bool NoFunction=false); void mangleNestedName(const TemplateDecl *TD, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs); - void manglePrefix(const DeclContext *DC); + void manglePrefix(const DeclContext *DC, bool NoFunction=false); void mangleTemplatePrefix(const TemplateDecl *ND); void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity); void mangleQualifiers(Qualifiers Quals); @@ -342,7 +355,12 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { // ::= <local-name> // const DeclContext *DC = ND->getDeclContext(); - + + if (GetLocalClassFunctionDeclContext(DC)) { + mangleLocalName(ND); + return; + } + // If this is an extern variable declared locally, the relevant DeclContext // is that of the containing namespace, or the translation unit. if (isa<FunctionDecl>(DC) && ND->hasLinkage()) @@ -603,7 +621,8 @@ void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) { } void CXXNameMangler::mangleNestedName(const NamedDecl *ND, - const DeclContext *DC) { + const DeclContext *DC, + bool NoFunction) { // <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E // ::= N [<CV-qualifiers>] <template-prefix> <template-args> E @@ -616,8 +635,9 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND, if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { mangleTemplatePrefix(TD); mangleTemplateArgs(*TemplateArgs); - } else { - manglePrefix(DC); + } + else { + manglePrefix(DC, NoFunction); mangleUnqualifiedName(ND); } @@ -640,18 +660,35 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { // <local-name> := Z <function encoding> E <entity name> [<discriminator>] // := Z <function encoding> E s [<discriminator>] // <discriminator> := _ <non-negative number> + const DeclContext *DC = ND->getDeclContext(); Out << 'Z'; - if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ND->getDeclContext())) + if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) mangleObjCMethodName(MD); + else if (const DeclContext *CDC = GetLocalClassFunctionDeclContext(DC)) { + mangleFunctionEncoding(cast<FunctionDecl>(CDC)); + Out << 'E'; + mangleNestedName(ND, DC, true /*NoFunction*/); + + // FIXME. This still does not cover all cases. + unsigned disc; + if (Context.getNextDiscriminator(ND, disc)) { + if (disc < 10) + Out << '_' << disc; + else + Out << "__" << disc << '_'; + } + + return; + } else - mangleFunctionEncoding(cast<FunctionDecl>(ND->getDeclContext())); + mangleFunctionEncoding(cast<FunctionDecl>(DC)); Out << 'E'; mangleUnqualifiedName(ND); } -void CXXNameMangler::manglePrefix(const DeclContext *DC) { +void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { // <prefix> ::= <prefix> <unqualified-name> // ::= <template-prefix> <template-args> // ::= <template-param> @@ -672,8 +709,11 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC) { if (const TemplateDecl *TD = isTemplate(cast<NamedDecl>(DC), TemplateArgs)) { mangleTemplatePrefix(TD); mangleTemplateArgs(*TemplateArgs); - } else { - manglePrefix(DC->getParent()); + } + else if(NoFunction && isa<FunctionDecl>(DC)) + return; + else { + manglePrefix(DC->getParent(), NoFunction); mangleUnqualifiedName(cast<NamedDecl>(DC)); } diff --git a/lib/CodeGen/Mangle.h b/lib/CodeGen/Mangle.h index 8d9629528d63..97f94b69b432 100644 --- a/lib/CodeGen/Mangle.h +++ b/lib/CodeGen/Mangle.h @@ -44,7 +44,9 @@ class MangleContext { ASTContext &Context; llvm::DenseMap<const TagDecl *, uint64_t> AnonStructIds; - + unsigned Discriminator; + llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier; + public: explicit MangleContext(ASTContext &Context) : Context(Context) { } @@ -85,7 +87,20 @@ public: llvm::SmallVectorImpl<char> &); void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, llvm::SmallVectorImpl<char> &); + + void mangleInitDiscriminator() { + Discriminator = 0; + } + bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { + unsigned &discriminator = Uniquifier[ND]; + if (!discriminator) + discriminator = ++Discriminator; + if (discriminator == 1) + return false; + disc = discriminator-2; + return true; + } /// @} }; diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index f4ec914a4e05..cb6a7df68d45 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -328,6 +328,16 @@ public: void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const; + + int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const { + // Darwin uses different dwarf register numbers for EH. + if (CGM.isTargetDarwin()) return 5; + + return 4; + } + + bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, + llvm::Value *Address) const; }; } @@ -568,6 +578,51 @@ void X86_32TargetCodeGenInfo::SetTargetAttributes(const Decl *D, } } +bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable( + CodeGen::CodeGenFunction &CGF, + llvm::Value *Address) const { + CodeGen::CGBuilderTy &Builder = CGF.Builder; + llvm::LLVMContext &Context = CGF.getLLVMContext(); + + const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); + llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4); + + // 0-7 are the eight integer registers; the order is different + // on Darwin (for EH), but the range is the same. + // 8 is %eip. + for (unsigned I = 0, E = 9; I != E; ++I) { + llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); + Builder.CreateStore(Four8, Slot); + } + + if (CGF.CGM.isTargetDarwin()) { + // 12-16 are st(0..4). Not sure why we stop at 4. + // These have size 16, which is sizeof(long double) on + // platforms with 8-byte alignment for that type. + llvm::Value *Sixteen8 = llvm::ConstantInt::get(i8, 16); + for (unsigned I = 12, E = 17; I != E; ++I) { + llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); + Builder.CreateStore(Sixteen8, Slot); + } + + } else { + // 9 is %eflags, which doesn't get a size on Darwin for some + // reason. + Builder.CreateStore(Four8, Builder.CreateConstInBoundsGEP1_32(Address, 9)); + + // 11-16 are st(0..5). Not sure why we stop at 5. + // These have size 12, which is sizeof(long double) on + // platforms with 4-byte alignment for that type. + llvm::Value *Twelve8 = llvm::ConstantInt::get(i8, 12); + for (unsigned I = 11, E = 17; I != E; ++I) { + llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); + Builder.CreateStore(Twelve8, Slot); + } + } + + return false; +} + namespace { /// X86_64ABIInfo - The X86_64 ABI information. class X86_64ABIInfo : public ABIInfo { @@ -656,6 +711,28 @@ public: class X86_64TargetCodeGenInfo : public TargetCodeGenInfo { public: X86_64TargetCodeGenInfo():TargetCodeGenInfo(new X86_64ABIInfo()) {} + + int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const { + return 7; + } + + bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, + llvm::Value *Address) const { + CodeGen::CGBuilderTy &Builder = CGF.Builder; + llvm::LLVMContext &Context = CGF.getLLVMContext(); + + const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context); + llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8); + + // 0-16 are the 16 integer registers. + // 17 is %rip. + for (unsigned I = 0, E = 17; I != E; ++I) { + llvm::Value *Slot = Builder.CreateConstInBoundsGEP1_32(Address, I); + Builder.CreateStore(Eight8, Slot); + } + + return false; + } }; } @@ -1559,6 +1636,10 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo { public: ARMTargetCodeGenInfo(ARMABIInfo::ABIKind K) :TargetCodeGenInfo(new ARMABIInfo(K)) {} + + int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const { + return 13; + } }; } diff --git a/lib/CodeGen/TargetInfo.h b/lib/CodeGen/TargetInfo.h index 9e80081429cc..f0a78243ff79 100644 --- a/lib/CodeGen/TargetInfo.h +++ b/lib/CodeGen/TargetInfo.h @@ -56,6 +56,23 @@ namespace clang { /// through such registers. virtual bool extendPointerWithSExt() const { return false; } + /// Determines the DWARF register number for the stack pointer, for + /// exception-handling purposes. Implements __builtin_dwarf_sp_column. + /// + /// Returns -1 if the operation is unsupported by this target. + virtual int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const { + return -1; + } + + /// Initializes the given DWARF EH register-size table, a char*. + /// Implements __builtin_init_dwarf_reg_size_table. + /// + /// Returns true if the operation is unsupported by this target. + virtual bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, + llvm::Value *Address) const { + return true; + } + /// Performs the code-generation required to convert a return /// address as stored by the system into the actual address of the /// next instruction that will be executed. diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index ec8227efb332..64168b4d8395 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1145,6 +1145,10 @@ const HostInfo *Driver::GetHostInfo(const char *TripleStr) const { llvm::PrettyStackTraceString CrashInfo("Constructing host"); llvm::Triple Triple(TripleStr); + // TCE is an osless target + if (Triple.getArchName() == "tce") + return createTCEHostInfo(*this, Triple); + switch (Triple.getOS()) { case llvm::Triple::AuroraUX: return createAuroraUXHostInfo(*this, Triple); diff --git a/lib/Driver/HostInfo.cpp b/lib/Driver/HostInfo.cpp index 18bb78659305..98b64f16635f 100644 --- a/lib/Driver/HostInfo.cpp +++ b/lib/Driver/HostInfo.cpp @@ -157,6 +157,46 @@ ToolChain *DarwinHostInfo::CreateToolChain(const ArgList &Args, return TC; } +// TCE Host Info + +/// TCEHostInfo - TCE host information implementation (see http://tce.cs.tut.fi) +class TCEHostInfo : public HostInfo { + +public: + TCEHostInfo(const Driver &D, const llvm::Triple &Triple); + ~TCEHostInfo() {}; + + virtual bool useDriverDriver() const; + + virtual types::ID lookupTypeForExtension(const char *Ext) const { + types::ID Ty = types::lookupTypeForExtension(Ext); + + if (Ty == types::TY_PP_Asm) + return types::TY_Asm; + + return Ty; + } + + virtual ToolChain *CreateToolChain(const ArgList &Args, + const char *ArchName) const; +}; + +TCEHostInfo::TCEHostInfo(const Driver &D, const llvm::Triple& Triple) + : HostInfo(D, Triple) { +} + +bool TCEHostInfo::useDriverDriver() const { + return false; +} + +ToolChain *TCEHostInfo::CreateToolChain(const ArgList &Args, + const char *ArchName) const { + llvm::Triple TCTriple(getTriple()); +// TCTriple.setArchName(ArchName); + return new toolchains::TCEToolChain(*this, TCTriple); +} + + // Unknown Host Info /// UnknownHostInfo - Generic host information to use for unknown hosts. @@ -536,6 +576,12 @@ clang::driver::createLinuxHostInfo(const Driver &D, } const HostInfo * +clang::driver::createTCEHostInfo(const Driver &D, + const llvm::Triple& Triple) { + return new TCEHostInfo(D, Triple); +} + +const HostInfo * clang::driver::createUnknownHostInfo(const Driver &D, const llvm::Triple& Triple) { return new UnknownHostInfo(D, Triple); diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index a7cd711df1bc..2f8d714504ba 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -728,6 +728,66 @@ DerivedArgList *Generic_GCC::TranslateArgs(InputArgList &Args, return new DerivedArgList(Args, true); } + +/// TCEToolChain - A tool chain using the llvm bitcode tools to perform +/// all subcommands. See http://tce.cs.tut.fi for our peculiar target. +/// Currently does not support anything else but compilation. + +TCEToolChain::TCEToolChain(const HostInfo &Host, const llvm::Triple& Triple) + : ToolChain(Host, Triple) { + // Path mangling to find libexec + std::string Path(getDriver().Dir); + + Path += "/../libexec"; + getProgramPaths().push_back(Path); +} + +TCEToolChain::~TCEToolChain() { + for (llvm::DenseMap<unsigned, Tool*>::iterator + it = Tools.begin(), ie = Tools.end(); it != ie; ++it) + delete it->second; +} + +bool TCEToolChain::IsMathErrnoDefault() const { + return true; +} + +bool TCEToolChain::IsUnwindTablesDefault() const { + return false; +} + +const char *TCEToolChain::GetDefaultRelocationModel() const { + return "static"; +} + +const char *TCEToolChain::GetForcedPicModel() const { + return 0; +} + +Tool &TCEToolChain::SelectTool(const Compilation &C, + const JobAction &JA) const { + Action::ActionClass Key; + Key = Action::AnalyzeJobClass; + + Tool *&T = Tools[Key]; + if (!T) { + switch (Key) { + case Action::PreprocessJobClass: + T = new tools::gcc::Preprocess(*this); break; + case Action::AnalyzeJobClass: + T = new tools::Clang(*this); break; + default: + assert(false && "Unsupported action for TCE target."); + } + } + return *T; +} + +DerivedArgList *TCEToolChain::TranslateArgs(InputArgList &Args, + const char *BoundArch) const { + return new DerivedArgList(Args, true); +} + /// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly. OpenBSD::OpenBSD(const HostInfo &Host, const llvm::Triple& Triple) diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h index fda08758c9bc..6dd64dec9ee3 100644 --- a/lib/Driver/ToolChains.h +++ b/lib/Driver/ToolChains.h @@ -267,6 +267,26 @@ public: }; +/// TCEToolChain - A tool chain using the llvm bitcode tools to perform +/// all subcommands. See http://tce.cs.tut.fi for our peculiar target. +class VISIBILITY_HIDDEN TCEToolChain : public ToolChain { +public: + TCEToolChain(const HostInfo &Host, const llvm::Triple& Triple); + ~TCEToolChain(); + + virtual DerivedArgList *TranslateArgs(InputArgList &Args, + const char *BoundArch) const; + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; + bool IsMathErrnoDefault() const; + bool IsUnwindTablesDefault() const; + const char* GetDefaultRelocationModel() const; + const char* GetForcedPicModel() const; + +private: + mutable llvm::DenseMap<unsigned, Tool*> Tools; + +}; + } // end namespace toolchains } // end namespace driver } // end namespace clang diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index ef14df10345e..63cf98d3da5d 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -36,9 +36,10 @@ using namespace clang; ASTUnit::ASTUnit(bool _MainFileIsAST) - : MainFileIsAST(_MainFileIsAST) { + : MainFileIsAST(_MainFileIsAST), ConcurrencyCheckValue(CheckUnlocked) { } ASTUnit::~ASTUnit() { + ConcurrencyCheckValue = CheckLocked; for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I) TemporaryFiles[I].eraseFromDisk(); } diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp index 09b5b458e93a..702c1d0025d9 100644 --- a/lib/Frontend/CacheTokens.cpp +++ b/lib/Frontend/CacheTokens.cpp @@ -184,9 +184,7 @@ class PTHWriter { /// Emit a token to the PTH file. void EmitToken(const Token& T); - void Emit8(uint32_t V) { - Out << (unsigned char)(V); - } + void Emit8(uint32_t V) { ::Emit8(Out, V); } void Emit16(uint32_t V) { ::Emit16(Out, V); } diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index 34cb9ec3b82a..4f972f0baff3 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -566,6 +566,17 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &tripl AddGnuCPlusPlusIncludePaths( "/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4", "i686-pc-linux-gnu", "", "", triple); + + // Gentoo amd64 gcc 4.3.2 + AddGnuCPlusPlusIncludePaths( + "/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.2/include/g++-v4", + "x86_64-pc-linux-gnu", "", "", triple); + + // Gentoo amd64 gcc 4.4.3 + AddGnuCPlusPlusIncludePaths( + "/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4", + "x86_64-pc-linux-gnu", "32", "", triple); + break; case llvm::Triple::FreeBSD: AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2", "", "", "", triple); diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp index a13bccbb91ec..378b4225c53e 100644 --- a/lib/Frontend/RewriteObjC.cpp +++ b/lib/Frontend/RewriteObjC.cpp @@ -4266,6 +4266,17 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart, // Insert declaration for the function in which block literal is used. if (CurFunctionDeclToDeclareForBlock && !Blocks.empty()) RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock); + bool RewriteSC = (GlobalVarDecl && + !Blocks.empty() && + GlobalVarDecl->getStorageClass() == VarDecl::Static && + GlobalVarDecl->getType().getCVRQualifiers()); + if (RewriteSC) { + std::string SC(" void __"); + SC += GlobalVarDecl->getNameAsString(); + SC += "() {}"; + InsertText(FunLocStart, SC); + } + // Insert closures that were part of the function. for (unsigned i = 0, count=0; i < Blocks.size(); i++) { CollectBlockDeclRefInfo(Blocks[i]); @@ -4311,6 +4322,21 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart, BlockByCopyDeclsPtrSet.clear(); ImportedBlockDecls.clear(); } + if (RewriteSC) { + // Must insert any 'const/volatile/static here. Since it has been + // removed as result of rewriting of block literals. + std::string SC; + if (GlobalVarDecl->getStorageClass() == VarDecl::Static) + SC = "static "; + if (GlobalVarDecl->getType().isConstQualified()) + SC += "const "; + if (GlobalVarDecl->getType().isVolatileQualified()) + SC += "volatile "; + if (GlobalVarDecl->getType().isRestrictQualified()) + SC += "restrict "; + InsertText(FunLocStart, SC); + } + Blocks.clear(); InnerDeclRefsCount.clear(); InnerDeclRefs.clear(); diff --git a/lib/Headers/smmintrin.h b/lib/Headers/smmintrin.h new file mode 100644 index 000000000000..d91ed1da7b28 --- /dev/null +++ b/lib/Headers/smmintrin.h @@ -0,0 +1,130 @@ +/*===---- smmintrin.h - SSE intrinsics -------------------------------------=== +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +* +*===-----------------------------------------------------------------------=== +*/ + +#ifndef _SMMINTRIN_H +#define _SMMINTRIN_H + +#ifndef __SSE4_1__ +#error "SSE4.1 instruction set not enabled" +#else + +#include <tmmintrin.h> + +/* Type defines. */ +typedef double __v2df __attribute__ ((__vector_size__ (16))); + +/* SSE4 Rounding macros. */ +#define _MM_FROUND_TO_NEAREST_INT 0x00 +#define _MM_FROUND_TO_NEG_INF 0x01 +#define _MM_FROUND_TO_POS_INF 0x02 +#define _MM_FROUND_TO_ZERO 0x03 +#define _MM_FROUND_CUR_DIRECTION 0x04 + +#define _MM_FROUND_RAISE_EXC 0x00 +#define _MM_FROUND_NO_EXC 0x08 + +#define _MM_FROUND_NINT (_MM_FROUND_RAISE_EXC | _MM_FROUND_TO_NEAREST_INT) +#define _MM_FROUND_FLOOR (_MM_FROUND_RAISE_EXC | _MM_FROUND_TO_NEG_INF) +#define _MM_FROUND_CEIL (_MM_FROUND_RAISE_EXC | _MM_FROUND_TO_POS_INF) +#define _MM_FROUND_TRUNC (_MM_FROUND_RAISE_EXC | _MM_FROUND_TO_ZERO) +#define _MM_FROUND_RINT (_MM_FROUND_RAISE_EXC | _MM_FROUND_CUR_DIRECTION) +#define _MM_FROUND_NEARBYINT (_MM_FROUND_RAISE_EXC | _MM_FROUND_CUR_DIRECTION) + +#define _mm_ceil_ps(X) _mm_round_ps((X), _MM_FROUND_CEIL) +#define _mm_ceil_pd(X) _mm_round_pd((X), _MM_FROUND_CEIL) +#define _mm_ceil_ss(X, Y) _mm_round_ss((X), (Y), _MM_FROUND_CEIL) +#define _mm_ceil_sd(X, Y) _mm_round_sd((X), (Y), _MM_FROUND_CEIL) + +#define _mm_floor_ps(X) _mm_round_ps((X), _MM_FROUND_FLOOR) +#define _mm_floor_pd(X) _mm_round_pd((X), _MM_FROUND_FLOOR) +#define _mm_floor_ss(X, Y) _mm_round_ss((X), (Y), _MM_FROUND_FLOOR) +#define _mm_floor_sd(X, Y) _mm_round_sd((X), (Y), _MM_FROUND_FLOOR) + +/* SSE4 Rounding Intrinsics. */ +static inline __m128 __attribute__((__always_inline__, __nodebug__)) +_mm_round_ps (__m128 __V, const int __M) +{ + return (__m128) __builtin_ia32_roundps ((__v4sf)__V, __M); +} + +static inline __m128 __attribute__((__always_inline__, __nodebug__)) +_mm_round_ss (__m128 __V1, __m128 __V2, const int __M) +{ + return (__m128) __builtin_ia32_roundss ((__v4sf)__V1, (__v4sf)__V2, __M); +} + +static inline __m128d __attribute__((__always_inline__, __nodebug__)) +_mm_round_pd (__m128d __V, const int __M) +{ + return (__m128d) __builtin_ia32_roundpd ((__v2df)__V, __M); +} + +static inline __m128d __attribute__((__always_inline__, __nodebug__)) +_mm_round_sd(__m128d __V1, __m128d __V2, const int __M) +{ + return (__m128d) __builtin_ia32_roundsd ((__v2df)__V1, (__v2df)__V2, __M); +} + +/* SSE4 Packed Blending Intrinsics. */ +static inline __m128d __attribute__((__always_inline__, __nodebug__)) +_mm_blend_pd (__m128d __V1, __m128d __V2, const int __M) +{ + return (__m128d) __builtin_ia32_blendpd ((__v2df)__V1, (__v2df)__V2, __M); +} + +static inline __m128 __attribute__((__always_inline__, __nodebug__)) +_mm_blend_ps (__m128 __V1, __m128 __V2, const int __M) +{ + return (__m128) __builtin_ia32_blendps ((__v4sf)__V1, (__v4sf)__V2, __M); +} + +static inline __m128d __attribute__((__always_inline__, __nodebug__)) +_mm_blendv_pd (__m128d __V1, __m128d __V2, __m128d __M) +{ + return (__m128d) __builtin_ia32_blendvpd ((__v2df)__V1, (__v2df)__V2, + (__v2df)__M); +} + +static inline __m128 __attribute__((__always_inline__, __nodebug__)) +_mm_blendv_ps (__m128 __V1, __m128 __V2, __m128 __M) +{ + return (__m128) __builtin_ia32_blendvps ((__v4sf)__V1, (__v4sf)__V2, + (__v4sf)__M); +} + +static inline __m128i __attribute__((__always_inline__, __nodebug__)) +_mm_blendv_epi8 (__m128i __V1, __m128i __V2, __m128i __M) +{ + return (__m128i) __builtin_ia32_pblendvb128 ((__v16qi)__V1, (__v16qi)__V2, + (__v16qi)__M); +} + +static inline __m128i __attribute__((__always_inline__, __nodebug__)) +_mm_blend_epi16 (__m128i __V1, __m128i __V2, const int __M) +{ + return (__m128i) __builtin_ia32_pblendw128 ((__v8hi)__V1, (__v8hi)__V2, __M); +} + +#endif /* __SSE4_1__ */ + +#endif /* _SMMINTRIN_H */ diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index d60cf0804f53..5fe2ef172e2f 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -505,6 +505,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { .Case("attribute_cf_returns_retained", true) .Case("attribute_ns_returns_not_retained", true) .Case("attribute_ns_returns_retained", true) + .Case("attribute_objc_ivar_unused", true) .Default(false); } diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index efd04e8eddd0..a94d07a6acc8 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1097,12 +1097,16 @@ public: ImplicitConversionSequence TryObjectArgumentInitialization(QualType FromType, CXXMethodDecl *Method, CXXRecordDecl *ActingContext); - bool PerformObjectArgumentInitialization(Expr *&From, CXXMethodDecl *Method); + bool PerformObjectArgumentInitialization(Expr *&From, + NestedNameSpecifier *Qualifier, + CXXMethodDecl *Method); ImplicitConversionSequence TryContextuallyConvertToBool(Expr *From); bool PerformContextuallyConvertToBool(Expr *&From); - bool PerformObjectMemberConversion(Expr *&From, NamedDecl *Member); + bool PerformObjectMemberConversion(Expr *&From, + NestedNameSpecifier *Qualifier, + NamedDecl *Member); // Members have to be NamespaceDecl* or TranslationUnitDecl*. // TODO: make this is a typesafe union. diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 574b22502789..0708d4176a4f 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -5212,14 +5212,35 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType, AbstractVariableType)) Invalid = true; - // FIXME: Need to test for ability to copy-construct and destroy the - // exception variable. - - // FIXME: Need to check for abstract classes. - VarDecl *ExDecl = VarDecl::Create(Context, CurContext, Loc, Name, ExDeclType, TInfo, VarDecl::None); + if (!Invalid) { + if (const RecordType *RecordTy = ExDeclType->getAs<RecordType>()) { + // C++ [except.handle]p16: + // The object declared in an exception-declaration or, if the + // exception-declaration does not specify a name, a temporary (12.2) is + // copy-initialized (8.5) from the exception object. [...] + // The object is destroyed when the handler exits, after the destruction + // of any automatic objects initialized within the handler. + // + // We just pretend to initialize the object with itself, then make sure + // it can be destroyed later. + InitializedEntity Entity = InitializedEntity::InitializeVariable(ExDecl); + Expr *ExDeclRef = DeclRefExpr::Create(Context, 0, SourceRange(), ExDecl, + Loc, ExDeclType, 0); + InitializationKind Kind = InitializationKind::CreateCopy(Loc, + SourceLocation()); + InitializationSequence InitSeq(*this, Entity, Kind, &ExDeclRef, 1); + OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, (void**)&ExDeclRef, 1)); + if (Result.isInvalid()) + Invalid = true; + else + FinalizeVarWithDestructor(ExDecl, RecordTy); + } + } + if (Invalid) ExDecl->setInvalidDecl(); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index d9464ad8c009..10001c356d1c 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -635,7 +635,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, MemberType = Context.getQualifiedType(MemberType, NewQuals); MarkDeclarationReferenced(Loc, *FI); - PerformObjectMemberConversion(Result, *FI); + PerformObjectMemberConversion(Result, /*FIXME:Qualifier=*/0, *FI); // FIXME: Might this end up being a qualified name? Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI, OpLoc, MemberType); @@ -1357,29 +1357,111 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, /// \brief Cast member's object to its own class if necessary. bool -Sema::PerformObjectMemberConversion(Expr *&From, NamedDecl *Member) { - if (FieldDecl *FD = dyn_cast<FieldDecl>(Member)) - if (CXXRecordDecl *RD = - dyn_cast<CXXRecordDecl>(FD->getDeclContext())) { - QualType DestType = - Context.getCanonicalType(Context.getTypeDeclType(RD)); - if (DestType->isDependentType() || From->getType()->isDependentType()) - return false; - QualType FromRecordType = From->getType(); - QualType DestRecordType = DestType; - if (FromRecordType->getAs<PointerType>()) { - DestType = Context.getPointerType(DestType); - FromRecordType = FromRecordType->getPointeeType(); - } - if (!Context.hasSameUnqualifiedType(FromRecordType, DestRecordType) && - CheckDerivedToBaseConversion(FromRecordType, - DestRecordType, - From->getSourceRange().getBegin(), - From->getSourceRange())) - return true; - ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase, - /*isLvalue=*/true); +Sema::PerformObjectMemberConversion(Expr *&From, + NestedNameSpecifier *Qualifier, + NamedDecl *Member) { + CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Member->getDeclContext()); + if (!RD) + return false; + + QualType DestRecordType; + QualType DestType; + QualType FromRecordType; + QualType FromType = From->getType(); + bool PointerConversions = false; + if (isa<FieldDecl>(Member)) { + DestRecordType = Context.getCanonicalType(Context.getTypeDeclType(RD)); + + if (FromType->getAs<PointerType>()) { + DestType = Context.getPointerType(DestRecordType); + FromRecordType = FromType->getPointeeType(); + PointerConversions = true; + } else { + DestType = DestRecordType; + FromRecordType = FromType; } + } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member)) { + if (Method->isStatic()) + return false; + + DestType = Method->getThisType(Context); + DestRecordType = DestType->getPointeeType(); + + if (FromType->getAs<PointerType>()) { + FromRecordType = FromType->getPointeeType(); + PointerConversions = true; + } else { + FromRecordType = FromType; + DestType = DestRecordType; + } + } else { + // No conversion necessary. + return false; + } + + if (DestType->isDependentType() || FromType->isDependentType()) + return false; + + // If the unqualified types are the same, no conversion is necessary. + if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType)) + return false; + + // C++ [class.member.lookup]p8: + // [...] Ambiguities can often be resolved by qualifying a name with its + // class name. + // + // If the member was a qualified name and the qualified referred to a + // specific base subobject type, we'll cast to that intermediate type + // first and then to the object in which the member is declared. That allows + // one to resolve ambiguities in, e.g., a diamond-shaped hierarchy such as: + // + // class Base { public: int x; }; + // class Derived1 : public Base { }; + // class Derived2 : public Base { }; + // class VeryDerived : public Derived1, public Derived2 { void f(); }; + // + // void VeryDerived::f() { + // x = 17; // error: ambiguous base subobjects + // Derived1::x = 17; // okay, pick the Base subobject of Derived1 + // } + QualType IntermediateRecordType; + QualType IntermediateType; + if (Qualifier) { + if (const RecordType *IntermediateRecord + = Qualifier->getAsType()->getAs<RecordType>()) { + IntermediateRecordType = QualType(IntermediateRecord, 0); + IntermediateType = IntermediateRecordType; + if (PointerConversions) + IntermediateType = Context.getPointerType(IntermediateType); + } + } + + if (!IntermediateType.isNull() && + IsDerivedFrom(FromRecordType, IntermediateRecordType) && + IsDerivedFrom(IntermediateRecordType, DestRecordType)) { + if (CheckDerivedToBaseConversion(FromRecordType, IntermediateRecordType, + From->getSourceRange().getBegin(), + From->getSourceRange()) || + CheckDerivedToBaseConversion(IntermediateRecordType, DestRecordType, + From->getSourceRange().getBegin(), + From->getSourceRange())) + return true; + + ImpCastExprToType(From, IntermediateType, CastExpr::CK_DerivedToBase, + /*isLvalue=*/!PointerConversions); + ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase, + /*isLvalue=*/!PointerConversions); + return false; + } + + if (CheckDerivedToBaseConversion(FromRecordType, + DestRecordType, + From->getSourceRange().getBegin(), + From->getSourceRange())) + return true; + + ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase, + /*isLvalue=*/true); return false; } @@ -1609,7 +1691,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, return ExprError(); } - if (VD->getType()->isArrayType()) { + if (VD->getType()->isArrayType() && !VD->hasAttr<BlocksAttr>()) { Diag(Loc, diag::err_ref_array_type); Diag(D->getLocation(), diag::note_declared_at); return ExprError(); @@ -2666,7 +2748,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType, } MarkDeclarationReferenced(MemberLoc, FD); - if (PerformObjectMemberConversion(BaseExpr, FD)) + if (PerformObjectMemberConversion(BaseExpr, Qualifier, FD)) return ExprError(); return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, FD, MemberLoc, MemberType)); @@ -6651,7 +6733,7 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, Res = BuildAnonymousStructUnionMemberReference( OC.LocEnd, MemberDecl, Res, OC.LocEnd).takeAs<Expr>(); } else { - PerformObjectMemberConversion(Res, MemberDecl); + PerformObjectMemberConversion(Res, /*Qualifier=*/0, MemberDecl); // MemberDecl->getType() doesn't get the right qualifiers, but it // doesn't matter here. Res = new (Context) MemberExpr(Res, false, MemberDecl, OC.LocEnd, diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 5f4601961c8e..309da292e137 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2881,7 +2881,7 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp, CXXMethodDecl *Method) { - if (PerformObjectArgumentInitialization(Exp, Method)) + if (PerformObjectArgumentInitialization(Exp, /*Qualifier=*/0, Method)) assert(0 && "Calling BuildCXXMemberCallExpr with invalid call?"); MemberExpr *ME = diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 0f8107ac5e49..bf9f73c96150 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -3365,7 +3365,8 @@ InitializationSequence::Perform(Sema &S, // FIXME: Should we move this initialization into a separate // derived-to-base conversion? I believe the answer is "no", because // we don't want to turn off access control here for c-style casts. - if (S.PerformObjectArgumentInitialization(CurInitExpr, Conversion)) + if (S.PerformObjectArgumentInitialization(CurInitExpr, /*Qualifier=*/0, + Conversion)) return S.ExprError(); // Do a little dance to make sure that CurInit has the proper diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index ed0d137d806c..ff59fc3a7d36 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -1282,8 +1282,8 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, QualType FromPointeeType = FromPtrType->getPointeeType(), ToPointeeType = ToPtrType->getPointeeType(); - if (FromPointeeType->isRecordType() && - ToPointeeType->isRecordType()) { + if (FromPointeeType->isRecordType() && ToPointeeType->isRecordType() && + !Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType)) { // We must have a derived-to-base conversion. Check an // ambiguous or inaccessible conversion. if (CheckDerivedToBaseConversion(FromPointeeType, ToPointeeType, @@ -2304,7 +2304,9 @@ Sema::TryObjectArgumentInitialization(QualType OrigFromType, /// the implicit object parameter for the given Method with the given /// expression. bool -Sema::PerformObjectArgumentInitialization(Expr *&From, CXXMethodDecl *Method) { +Sema::PerformObjectArgumentInitialization(Expr *&From, + NestedNameSpecifier *Qualifier, + CXXMethodDecl *Method) { QualType FromRecordType, DestType; QualType ImplicitParamRecordType = Method->getThisType(Context)->getAs<PointerType>()->getPointeeType(); @@ -2327,15 +2329,12 @@ Sema::PerformObjectArgumentInitialization(Expr *&From, CXXMethodDecl *Method) { diag::err_implicit_object_parameter_init) << ImplicitParamRecordType << FromRecordType << From->getSourceRange(); - if (ICS.Standard.Second == ICK_Derived_To_Base && - CheckDerivedToBaseConversion(FromRecordType, - ImplicitParamRecordType, - From->getSourceRange().getBegin(), - From->getSourceRange())) - return true; + if (ICS.Standard.Second == ICK_Derived_To_Base) + return PerformObjectMemberConversion(From, Qualifier, Method); - ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase, - /*isLvalue=*/true); + if (!Context.hasSameType(From->getType(), DestType)) + ImpCastExprToType(From, DestType, CastExpr::CK_NoOp, + /*isLvalue=*/!From->getType()->getAs<PointerType>()); return false; } @@ -5545,7 +5544,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { CheckMemberOperatorAccess(OpLoc, Args[0], Method, Best->getAccess()); - if (PerformObjectArgumentInitialization(Input, Method)) + if (PerformObjectArgumentInitialization(Input, /*Qualifier=*/0, Method)) return ExprError(); } else { // Convert the arguments. @@ -5738,7 +5737,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, if (Arg1.isInvalid()) return ExprError(); - if (PerformObjectArgumentInitialization(Args[0], Method)) + if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, + Method)) return ExprError(); Args[1] = RHS = Arg1.takeAs<Expr>(); @@ -5904,7 +5904,8 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // Convert the arguments. CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl); - if (PerformObjectArgumentInitialization(Args[0], Method)) + if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, + Method)) return ExprError(); // Convert the arguments. @@ -6009,12 +6010,15 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, MemberExpr *MemExpr; CXXMethodDecl *Method = 0; + NestedNameSpecifier *Qualifier = 0; if (isa<MemberExpr>(NakedMemExpr)) { MemExpr = cast<MemberExpr>(NakedMemExpr); Method = cast<CXXMethodDecl>(MemExpr->getMemberDecl()); + Qualifier = MemExpr->getQualifier(); } else { UnresolvedMemberExpr *UnresExpr = cast<UnresolvedMemberExpr>(NakedMemExpr); - + Qualifier = UnresExpr->getQualifier(); + QualType ObjectType = UnresExpr->getBaseType(); // Add overload candidates @@ -6113,7 +6117,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, // Convert the object argument (for a non-static member function call). Expr *ObjectArg = MemExpr->getBase(); if (!Method->isStatic() && - PerformObjectArgumentInitialization(ObjectArg, Method)) + PerformObjectArgumentInitialization(ObjectArg, Qualifier, Method)) return ExprError(); MemExpr->setBase(ObjectArg); @@ -6333,7 +6337,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, bool IsError = false; // Initialize the implicit object parameter. - IsError |= PerformObjectArgumentInitialization(Object, Method); + IsError |= PerformObjectArgumentInitialization(Object, /*Qualifier=*/0, + Method); TheCall->setArg(0, Object); @@ -6458,7 +6463,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { // Convert the object parameter. CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function); - if (PerformObjectArgumentInitialization(Base, Method)) + if (PerformObjectArgumentInitialization(Base, /*Qualifier=*/0, Method)) return ExprError(); // No concerns about early exits now. diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 2fb5c84ac90e..a79853afdc6b 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1034,7 +1034,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>(); T = Context.getObjCObjectPointerType(T, (ObjCProtocolDecl **)OIT->qual_begin(), - OIT->getNumProtocols()); + OIT->getNumProtocols(), + DeclType.Ptr.TypeQuals); break; } T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclType.Loc, Name); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 2f3c48232174..24ea62cde1b4 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -969,7 +969,7 @@ public: assert(!Qualifier && "Can't have an unnamed field with a qualifier!"); Expr *BaseExpr = Base.takeAs<Expr>(); - if (getSema().PerformObjectMemberConversion(BaseExpr, Member)) + if (getSema().PerformObjectMemberConversion(BaseExpr, Qualifier, Member)) return getSema().ExprError(); MemberExpr *ME = diff --git a/test/Analysis/inline3.c b/test/Analysis/inline3.c new file mode 100644 index 000000000000..3661263b6bae --- /dev/null +++ b/test/Analysis/inline3.c @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -analyze -inline-call -analyzer-store region -analyze-function f2 -verify %s + + +// Test when entering f1(), we set the right AnalysisContext to Environment. +// Otherwise, block-level expr '1 && a' would not be block-level. +int a; + +void f1() { + if (1 && a) + return; +} + +void f2() { + f1(); +} diff --git a/test/CXX/class.derived/class.member.lookup/p8.cpp b/test/CXX/class.derived/class.member.lookup/p8.cpp new file mode 100644 index 000000000000..4d4acc3460e4 --- /dev/null +++ b/test/CXX/class.derived/class.member.lookup/p8.cpp @@ -0,0 +1,63 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// FIXME: Access control checks + +namespace PR5820 { + // also <rdar://problem/7535045> + struct Base { + void Foo(); + int Member; + }; + + struct D1 : public Base {}; + struct D2 : public Base {}; + + struct Derived : public D1, public D2 { + void Inner(); + }; + + void Test() { + Derived d; + d.D1::Foo(); + d.D1::Member = 17; + } + + void Derived::Inner() { + D1::Foo(); + D1::Member = 42; + this->D1::Foo(); + this->D1::Member = 42; + } +} + +template<typename T> +struct BaseT { + void Foo(); // expected-note{{found by ambiguous name lookup}} + int Member; +}; + +template<typename T> struct Derived1T : BaseT<T> { }; +template<typename T> struct Derived2T : BaseT<T> { }; + +template<typename T> +struct DerivedT : public Derived1T<T>, public Derived2T<T> { + void Inner(); +}; + +template<typename T> +void DerivedT<T>::Inner() { + Derived1T<T>::Foo(); + Derived2T<T>::Member = 42; + this->Derived1T<T>::Foo(); + this->Derived2T<T>::Member = 42; + this->Foo(); // expected-error{{non-static member 'Foo' found in multiple base-class subobjects of type 'BaseT<int>'}} +} + +template<typename T> +void Test(DerivedT<T> d) { + d.template Derived1T<T>::Foo(); + d.template Derived2T<T>::Member = 17; + d.Inner(); // expected-note{{in instantiation}} +} + +template void Test(DerivedT<int>); diff --git a/test/CXX/except/except.handle/p16.cpp b/test/CXX/except/except.handle/p16.cpp new file mode 100644 index 000000000000..87972f59856e --- /dev/null +++ b/test/CXX/except/except.handle/p16.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// The object declared in an exception-declaration or, if the +// exception-declaration does not specify a name, a temporary (12.2) +// is copy-initialized (8.5) from the exception object. +// +template<typename T> +class X { + T* ptr; + +public: + X(const X<T> &) { + int *ip = 0; + ptr = ip; // expected-error{{incompatible type assigning 'int *', expected 'float *'}} + } + + ~X() { + float *fp = 0; + ptr = fp; // expected-error{{incompatible type assigning 'float *', expected 'int *'}} + } +}; + +void f() { + try { + } catch (X<float>) { // expected-note{{instantiation}} + // copy constructor + } catch (X<int> xi) { // expected-note{{instantiation}} + // destructor + } +} + +struct Abstract { + virtual void f() = 0; // expected-note{{pure virtual}} +}; + +void g() { + try { + } catch (Abstract) { // expected-error{{variable type 'Abstract' is an abstract class}} + } +} diff --git a/test/CodeGen/asm-2.c b/test/CodeGen/asm-2.c deleted file mode 100644 index 9d73608a4c18..000000000000 --- a/test/CodeGen/asm-2.c +++ /dev/null @@ -1,10 +0,0 @@ -// RUN: %clang_cc1 -emit-llvm %s -o %t -triple i386-pc-linux-gnu -O2 -// RUN: not grep "load" %t - -// <rdar://problem/6841383> -int cpuid(unsigned data) { - int a, b; - - asm("xyz" :"=a"(a), "=d"(b) : "a"(data)); - return a + b; -} diff --git a/test/CodeGen/asm-inout.c b/test/CodeGen/asm-inout.c deleted file mode 100644 index 407660927100..000000000000 --- a/test/CodeGen/asm-inout.c +++ /dev/null @@ -1,18 +0,0 @@ -// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm %s -o %t -// RUN: grep "load i8\*\*\* %p.addr" %t | count 1 -// XFAIL: * - -// PR3800 -void f(void **p) -{ - __asm__ volatile("" :"+m"(*p)); -} - -#if 0 -// FIXME: Once this works again, we must verify that the code below behaves as expected -// See PR4677. -void f() { - unsigned _data = 42; - __asm__("bswap %0":"+r"(_data)); -} -#endif diff --git a/test/CodeGen/asm.c b/test/CodeGen/asm.c index df593d79fa17..bf1c806a2c47 100644 --- a/test/CodeGen/asm.c +++ b/test/CodeGen/asm.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm %s -o %t +// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s void t1(int len) { __asm__ volatile("" : "=&r"(len), "+&r"(len)); } @@ -28,14 +28,16 @@ void t6(void) { __asm__ volatile("" : : "i" (t6)); } -// RUN: grep "T7 NAMED: \$1" %t void t7(int a) { __asm__ volatile("T7 NAMED: %[input]" : "+r"(a): [input] "i" (4)); + // CHECK: @t7(i32 + // CHECK: T7 NAMED: $1 } -// RUN: grep "T8 NAMED MODIFIER: \${0:c}" %t void t8() { __asm__ volatile("T8 NAMED MODIFIER: %c[input]" :: [input] "i" (4)); + // CHECK: @t8() + // CHECK: T8 NAMED MODIFIER: ${0:c} } // PR3682 @@ -45,9 +47,11 @@ unsigned t9(unsigned int a) { } // PR3908 -// RUN: grep "PR3908 \$1 \$3 \$2 \$0" %t void t10(int r) { __asm__("PR3908 %[lf] %[xx] %[li] %[r]" : [r] "+r" (r) : [lf] "mx" (0), [li] "mr" (0), [xx] "x" ((double)(0))); + +// CHECK: @t10( +// CHECK:PR3908 $1 $3 $2 $0 } @@ -110,3 +114,24 @@ int t16() { ); return 0; } + +// PR6475 +void t17() { + int i; + __asm__ ( "nop": "=m"(i)); + +// CHECK: @t17() +// CHECK: call void asm "nop", "=*m, +} + +// <rdar://problem/6841383> +int t18(unsigned data) { + int a, b; + + asm("xyz" :"=a"(a), "=d"(b) : "a"(data)); + return a + b; +// CHECK: t18(i32 +// CHECK: = call {{.*}}asm "xyz" +// CHECK-NEXT: extractvalue +// CHECK-NEXT: extractvalue +} diff --git a/test/CodeGen/attr-weakref.c b/test/CodeGen/attr-weakref.c new file mode 100644 index 000000000000..c1cc03b668d9 --- /dev/null +++ b/test/CodeGen/attr-weakref.c @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -emit-llvm -triple i386-linux-gnu -o %t %s +// RUN: FileCheck --input-file=%t %s + +// CHECK: declare extern_weak void @test1_f() +void test1_f(void); +static void test1_g(void) __attribute__((weakref("test1_f"))); +void test1_h(void) { + test1_g(); +} + +// CHECK: define void @test2_f() +void test2_f(void) {} +static void test2_g(void) __attribute__((weakref("test2_f"))); +void test2_h(void) { + test2_g(); +} + +// CHECK: declare void @test3_f() +void test3_f(void); +static void test3_g(void) __attribute__((weakref("test3_f"))); +void test3_foo(void) { + test3_f(); +} +void test3_h(void) { + test3_g(); +} + +// CHECK: define void @test4_f() +void test4_f(void); +static void test4_g(void) __attribute__((weakref("test4_f"))); +void test4_h(void) { + test4_g(); +} +void test4_f(void) {} + +// CHECK: declare void @test5_f() +void test5_f(void); +static void test5_g(void) __attribute__((weakref("test5_f"))); +void test5_h(void) { + test5_g(); +} +void test5_foo(void) { + test5_f(); +} + +// CHECK: declare extern_weak void @test6_f() +void test6_f(void) __attribute__((weak)); +static void test6_g(void) __attribute__((weakref("test6_f"))); +void test6_h(void) { + test6_g(); +} +void test6_foo(void) { + test6_f(); +} + +// CHECK: declare extern_weak void @test7_f() +void test7_f(void); +static void test7_g(void) __attribute__((weakref("test7_f"))); +static void *const test7_zed = (void *) &test7_g; +void* test7_h(void) { + return test7_zed; +} diff --git a/test/CodeGen/attr-weakref2.c b/test/CodeGen/attr-weakref2.c new file mode 100644 index 000000000000..99760635581d --- /dev/null +++ b/test/CodeGen/attr-weakref2.c @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 -emit-llvm -triple i386-linux-gnu -o %t %s +// RUN: FileCheck --input-file=%t %s + +// CHECK: @test1_f = extern_weak global i32 +extern int test1_f; +static int test1_g __attribute__((weakref("test1_f"))); +int test1_h(void) { + return test1_g; +} + +// CHECK: @test2_f = common global i32 0, align 4 +int test2_f; +static int test2_g __attribute__((weakref("test2_f"))); +int test2_h(void) { + return test2_g; +} + +// CHECK: @test3_f = external global i32 +extern int test3_f; +static int test3_g __attribute__((weakref("test3_f"))); +int test3_foo(void) { + return test3_f; +} +int test3_h(void) { + return test3_g; +} + +// CHECK: @test4_f = common global i32 0, align 4 +extern int test4_f; +static int test4_g __attribute__((weakref("test4_f"))); +int test4_h(void) { + return test4_g; +} +int test4_f; + +// CHECK: @test5_f = external global i32 +extern int test5_f; +static int test5_g __attribute__((weakref("test5_f"))); +int test5_h(void) { + return test5_g; +} +int test5_foo(void) { + return test5_f; +} + +// CHECK: @test6_f = extern_weak global i32 +extern int test6_f __attribute__((weak)); +static int test6_g __attribute__((weakref("test6_f"))); +int test6_h(void) { + return test6_g; +} +int test6_foo(void) { + return test6_f; +} diff --git a/test/CodeGen/attributes.c b/test/CodeGen/attributes.c index 4fdf1a51762b..770ce766dfba 100644 --- a/test/CodeGen/attributes.c +++ b/test/CodeGen/attributes.c @@ -30,12 +30,6 @@ int t12 __attribute__((section("SECT"))); void __t8() {} void t9() __attribute__((weak, alias("__t8"))); -static void t22(void) __attribute__((weakref("t8"))); -// CHECK: @t22 = alias weak void ()* @t8 - -static void t23(void) __attribute__((weakref, alias("t8"))); -// CHECK: @t23 = alias weak void ()* @t8 - // CHECK: declare extern_weak i32 @t15() int __attribute__((weak_import)) t15(void); int t17() { diff --git a/test/CodeGen/blockstret.c b/test/CodeGen/blockstret.c new file mode 100644 index 000000000000..09292b809f5a --- /dev/null +++ b/test/CodeGen/blockstret.c @@ -0,0 +1,106 @@ +// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin9 %s -emit-llvm -o - | FileCheck %s -check-prefix=X64 +// RUN: %clang_cc1 -fblocks -triple i686-apple-darwin9 %s -emit-llvm -o - | FileCheck %s -check-prefix=X32 + +// X64: internal constant %2 { i8** @_NSConcreteGlobalBlock, i32 1879048192 +// X64: store i32 1610612736, i32* %want + +// X32: @_NSConcreteGlobalBlock, i32 1879048192, i32 0, +// X32: store i32 1610612736, i32* %want + +// rdar://7677537 +int printf(const char *, ...); +void *malloc(__SIZE_TYPE__ size); + +typedef struct bigbig { + int array[512]; + char more[32]; +} BigStruct_t; + +BigStruct_t (^global)(void) = ^{ return *(BigStruct_t *)malloc(sizeof(struct bigbig)); }; + +const char * getBlockSignature(void *); + +BigStruct_t foo(int param) { + BigStruct_t x; + BigStruct_t (^f)(int) = ^(int param) { + BigStruct_t *result = malloc(sizeof(BigStruct_t)); + result->array[23] = param; + return *result; + }; + getBlockSignature(f); + return x; +} + +enum { + BLOCK_HAS_COPY_DISPOSE = (1 << 25), + BLOCK_HAS_CXX_OBJ = (1 << 26), + BLOCK_IS_GLOBAL = (1 << 28), + BLOCK_USE_STRET = (1 << 29), + BLOCK_HAS_OBJC_TYPE = (1 << 30) +}; + +struct block_descriptor_big { + unsigned long int reserved; + unsigned long int size; + void (*copy)(void *dst, void *src); // conditional on BLOCK_HAS_COPY_DISPOSE + void (*dispose)(void *); // conditional on BLOCK_HAS_COPY_DISPOSE + const char *signature; // conditional on BLOCK_HAS_OBJC + const char *layout; // conditional on BLOCK_HAS_OBJC +}; +struct block_descriptor_small { + unsigned long int reserved; + unsigned long int size; + const char *signature; // conditional on BLOCK_HAS_OBJC + const char *layout; // conditional on BLOCK_HAS_OBJC +}; + +struct block_layout_abi { // can't change + void *isa; + int flags; + int reserved; + void (*invoke)(void *, ...); + struct block_descriptor_big *descriptor; +}; + +const char *getBlockSignature(void *block) { + struct block_layout_abi *layout = (struct block_layout_abi *)block; + if ((layout->flags & BLOCK_HAS_OBJC_TYPE) != BLOCK_HAS_OBJC_TYPE) return 0; + if (layout->flags & BLOCK_HAS_COPY_DISPOSE) + return layout->descriptor->signature; + else + return ((struct block_descriptor_small *)layout->descriptor)->signature; +} + +int usesStruct(void *block) { + struct block_layout_abi *layout = (struct block_layout_abi *)block; + int want = BLOCK_HAS_OBJC_TYPE | BLOCK_USE_STRET; + return (layout->flags & want) == want; +} + + +int main(int argc, char *argv[]) { + printf("desired global flags: %d\n", BLOCK_USE_STRET | BLOCK_IS_GLOBAL | BLOCK_HAS_OBJC_TYPE); + printf("desired stack flags: %d\n", BLOCK_USE_STRET | BLOCK_HAS_OBJC_TYPE); + + printf("should be non-zero: %d\n", usesStruct(global)); + BigStruct_t x; + BigStruct_t (^local)(int) = ^(int param) { + BigStruct_t *result = (BigStruct_t *)malloc(sizeof(BigStruct_t)); + result->array[23] = argc; + return *result; + }; + printf("should be non-zero: %d\n", usesStruct(global)); + printf("should be non-zero: %d\n", usesStruct(local)); + printf("should be zero: %d\n", usesStruct(^void(int x){ })); + return 0; +} + +/* +desired global flags: 1879048192 +desired stack flags: 1610612736 +should be non-zero: 0 +should be non-zero: 0 +should be non-zero: 1 +should be zero: 0 + +*/ diff --git a/test/CodeGen/builtins-arm.c b/test/CodeGen/builtins-arm.c new file mode 100644 index 000000000000..555375754959 --- /dev/null +++ b/test/CodeGen/builtins-arm.c @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -triple thumbv7-eabi -target-cpu cortex-a8 -O3 -emit-llvm -o %t %s + +void *f0() +{ + return __builtin_thread_pointer(); +} diff --git a/test/CodeGen/builtins-x86.c b/test/CodeGen/builtins-x86.c index 2eadd7f884d8..b5878144981f 100644 --- a/test/CodeGen/builtins-x86.c +++ b/test/CodeGen/builtins-x86.c @@ -360,8 +360,8 @@ void f0() { tmp_V2LLi = __builtin_ia32_pmuldq128(tmp_V4i, tmp_V4i); tmp_V4i = __builtin_ia32_pmulld128(tmp_V4i, tmp_V4i); tmp_V4f = __builtin_ia32_roundps(tmp_V4f, imm_i_0_16); - // tmp_V4f = __builtin_ia32_roundss(tmp_V4f, tmp_V4f, imm_i_0_16); - // tmp_V2d = __builtin_ia32_roundsd(tmp_V2d, tmp_V2d, imm_i_0_16); + tmp_V4f = __builtin_ia32_roundss(tmp_V4f, tmp_V4f, imm_i_0_16); + tmp_V2d = __builtin_ia32_roundsd(tmp_V2d, tmp_V2d, imm_i_0_16); tmp_V2d = __builtin_ia32_roundpd(tmp_V2d, imm_i_0_16); tmp_V4f = __builtin_ia32_insertps128(tmp_V4f, tmp_V4f, tmp_i); #endif diff --git a/test/CodeGen/builtins.c b/test/CodeGen/builtins.c index 417ca7def5f2..a4424d77428f 100644 --- a/test/CodeGen/builtins.c +++ b/test/CodeGen/builtins.c @@ -118,6 +118,7 @@ int main() { // V(clear_cache, (&N, &N+1)); V(trap, ()); R(extract_return_addr, (&N)); + P(signbit, (1.0)); return 0; } diff --git a/test/CodeGenCXX/mangle-local-class-names.cpp b/test/CodeGenCXX/mangle-local-class-names.cpp new file mode 100644 index 000000000000..332146076ae5 --- /dev/null +++ b/test/CodeGenCXX/mangle-local-class-names.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s + +// CHECK: @_ZZ4FUNCvEN4SSSSC1ERKf +// CHECK: @_ZZ4FUNCvEN4SSSSC2E_0RKf +// CHECK: @_ZZ4GORFfEN4SSSSC1ERKf +// CHECK: @_ZZ4GORFfEN4SSSSC2E_0RKf + +void FUNC () +{ + { + float IVAR1 ; + + struct SSSS + { + float bv; + SSSS( const float& from): bv(from) { } + }; + + SSSS VAR1(IVAR1); + } + + { + float IVAR2 ; + + struct SSSS + { + SSSS( const float& from) {} + }; + + SSSS VAR2(IVAR2); + } +} + +void GORF (float IVAR1) +{ + { + struct SSSS + { + float bv; + SSSS( const float& from): bv(from) { } + }; + + SSSS VAR1(IVAR1); + } + + { + float IVAR2 ; + + struct SSSS + { + SSSS( const float& from) {} + }; + + SSSS VAR2(IVAR2); + } +} + diff --git a/test/CodeGenObjC/id-isa-codegen.m b/test/CodeGenObjC/id-isa-codegen.m index 3179e11b7f39..e893aaa4f3c2 100644 --- a/test/CodeGenObjC/id-isa-codegen.m +++ b/test/CodeGenObjC/id-isa-codegen.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm -o %t %s +// RUN: %clang_cc1 -emit-llvm -o - %s typedef struct objc_class *Class; @@ -48,3 +48,19 @@ id Test2() { return (*[Foo method]).isa; return [Foo method]->isa; } + +// rdar 7709015 +@interface Cat {} +@end + +@interface SuperCat : Cat {} ++(void)geneticallyAlterCat:(Cat *)cat; +@end + +@implementation SuperCat ++ (void)geneticallyAlterCat:(Cat *)cat { + Class dynamicSubclass; + ((id)cat)->isa = dynamicSubclass; +} +@end + diff --git a/test/Index/linkage.c b/test/Index/linkage.c index b597c263a03c..d1f1c5bca541 100644 --- a/test/Index/linkage.c +++ b/test/Index/linkage.c @@ -9,15 +9,18 @@ void bar(int y) { int k; } extern int n; +static int wibble(int); // CHECK: EnumDecl=Baz:3:6 (Definition)linkage=External // CHECK: EnumConstantDecl=Qux:3:12 (Definition)linkage=External // CHECK: VarDecl=x:4:5linkage=External // CHECK: FunctionDecl=foo:5:6linkage=External -// CHECK: VarDecl=w:6:12linkage=External +// CHECK: VarDecl=w:6:12linkage=Internal // CHECK: FunctionDecl=bar:7:6 (Definition)linkage=External -// CHECK: ParmDecl=y:7:14 (Definition)linkage=External -// CHECK: VarDecl=z:8:14 (Definition)linkage=External -// CHECK: VarDecl=k:9:7 (Definition)linkage=External -// CHECK: VarDecl=n:11:12 +// CHECK: ParmDecl=y:7:14 (Definition)linkage=NoLinkage +// CHECK: VarDecl=z:8:14 (Definition)linkage=NoLinkage +// CHECK: VarDecl=k:9:7 (Definition)linkage=NoLinkage +// CHECK: VarDecl=n:11:12linkage=External +// CHECK: FunctionDecl=wibble:12:12linkage=Internal +// CHECL: ParmDecl=:12:22 (Definition)linkage=NoLinkage diff --git a/test/Rewriter/rewrite-byref-vars.mm b/test/Rewriter/rewrite-byref-vars.mm index 58b925a2b28c..007ab43d097b 100644 --- a/test/Rewriter/rewrite-byref-vars.mm +++ b/test/Rewriter/rewrite-byref-vars.mm @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -fms-extensions -rewrite-objc -x objective-c++ -fblocks -o - %s +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp // radar 7540194 extern "C" __declspec(dllexport) void BreakTheRewriter(int i) { diff --git a/test/Rewriter/rewrite-nested-ivar.mm b/test/Rewriter/rewrite-nested-ivar.mm index bbc9d28d2513..1787cc76af07 100644 --- a/test/Rewriter/rewrite-nested-ivar.mm +++ b/test/Rewriter/rewrite-nested-ivar.mm @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -x objective-c++ -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp -// RUN: FileCheck -check-prefix LP --input-file=%t-rw.cpp %s +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp // radar 7583971 @@ -29,5 +29,3 @@ _internal->response->InnerResponse = 0; } @end - -// CHECK-LP: ((struct NSURLResponse_IMPL *)((struct NSCachedURLResponseInternal_IMPL *)((struct NSCachedURLResponse_IMPL *)self)->_internal)->response)->InnerResponse diff --git a/test/Rewriter/rewrite-protocol-qualified.mm b/test/Rewriter/rewrite-protocol-qualified.mm index e91c3db8616f..5f12010afd4e 100644 --- a/test/Rewriter/rewrite-protocol-qualified.mm +++ b/test/Rewriter/rewrite-protocol-qualified.mm @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -x objective-c++ -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp -// RUN: FileCheck -check-prefix LP --input-file=%t-rw.cpp %s +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"SEL=void*" -D"id=void*" -D"__declspec(X)=" %t-rw.cpp // radar 7589414 @protocol NSPortDelegate; @@ -30,12 +30,3 @@ void f() { id a; id b = bar((id <Proto>)a); } - -// CHECK-LP: NSConnection /*<NSPortDelegate>*/ *conn = 0; - -// CHECK-LP: id /*<NSPortDelegate>*/ *idc = 0; - -// CHECK-LP: func(id/*<Proto1, Proto2>*/ inProxy); - -// CHECK-LP: bar((id /*<Proto>*/)a); - diff --git a/test/Rewriter/rewrite-static-block.mm b/test/Rewriter/rewrite-static-block.mm new file mode 100644 index 000000000000..c99557f52ef3 --- /dev/null +++ b/test/Rewriter/rewrite-static-block.mm @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp -emit-llvm -o %t-rw.ll +// RUN: FileCheck --input-file=%t-rw.ll %s + +typedef void (^void_block_t)(void); + +static const void_block_t myblock = ^{ + +}; + +// CHECK: myblock = internal global diff --git a/test/Sema/block-byref-args.c b/test/Sema/block-byref-args.c index 7b7cc3d2c49b..255c97b280c9 100644 --- a/test/Sema/block-byref-args.c +++ b/test/Sema/block-byref-args.c @@ -13,6 +13,10 @@ int main(int argc, char **argv) { int (^XXX)(void) = ^{ return III+JJJJ; }; + // rdar 7671883 + __block char array[10] = {'a', 'b', 'c', 'd'}; + char (^ch)() = ^{ array[1] = 'X'; return array[5]; }; + ch(); + return 0; } - diff --git a/test/Sema/scope-check.c b/test/Sema/scope-check.c index 7d293f2747ed..6f8640255a9e 100644 --- a/test/Sema/scope-check.c +++ b/test/Sema/scope-check.c @@ -140,13 +140,13 @@ L2: ; L3: L4: - goto *P; // expected-error {{illegal indirect goto in protected scope, unknown effect on scopes}} + goto *P; // expected-warning {{illegal indirect goto in protected scope, unknown effect on scopes}} goto L3; // ok goto L4; // ok void *Ptrs[] = { &&L2, // Ok. - &&L3 // expected-error {{address taken of label in protected scope, jump to it would have unknown effect on scope}} + &&L3 // expected-warning {{address taken of label in protected scope, jump to it would have unknown effect on scope}} }; } diff --git a/test/SemaObjC/check-dup-objc-decls-1.m b/test/SemaObjC/check-dup-objc-decls-1.m index 1f80293588a6..8dde777f7437 100644 --- a/test/SemaObjC/check-dup-objc-decls-1.m +++ b/test/SemaObjC/check-dup-objc-decls-1.m @@ -37,3 +37,8 @@ void Gorf() // expected-error {{redefinition of 'Gorf' as different kind of symb @interface A(Cat)<P> @end // expected-note {{previous definition is here}} @interface A(Cat)<Q> @end // expected-warning {{duplicate definition of category 'Cat' on interface 'A'}} + +// rdar 7626768 +@class NSString; +NSString * TestBaz; // expected-note {{previous definition is here}} +NSString * const TestBaz; // expected-error {{redefinition of 'TestBaz' with a different type}} diff --git a/test/SemaObjC/unused.m b/test/SemaObjC/unused.m index e99418875ae2..a33a1bc02f9d 100644 --- a/test/SemaObjC/unused.m +++ b/test/SemaObjC/unused.m @@ -39,7 +39,15 @@ void test2() { // instance variables, which GCC does not. //===------------------------------------------------------------------------=== +#if __has_feature(attribute_objc_ivar_unused) +#define UNUSED_IVAR __attribute__((unused)) +#else +#error __attribute__((unused)) not supported on ivars +#endif + @interface TestUnusedIvar { - id x __attribute__((unused)); // no-warning + id y __attribute__((unused)); // no-warning + id x UNUSED_IVAR; // no-warning } @end + diff --git a/test/lit.cfg b/test/lit.cfg index beb8ae03b4f6..3565edc779b8 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -97,6 +97,18 @@ if config.test_exec_root is None: ### +import re +site_exp = {} +for line in open(os.path.join(config.llvm_obj_root, 'test', 'site.exp')): + m = re.match('set ([^ ]+) "([^"]*)"', line) + if m: + site_exp[m.group(1)] = m.group(2) + +targets = set(site_exp['TARGETS_TO_BUILD'].split()) +def llvm_supports_target(name): + return name in targets +config.conditions['TARGET'] = llvm_supports_target + # Discover the 'clang' and 'clangcc' to use. import os diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp index 6fc7b530307d..07bb7fbd83ef 100644 --- a/tools/CIndex/CIndex.cpp +++ b/tools/CIndex/CIndex.cpp @@ -104,7 +104,8 @@ public: { { llvm::raw_svector_ostream Out(CrashString); - Out << "ClangCIndex [createTranslationUnitFromSourceFile]: clang"; + Out << "ClangCIndex [" << getClangFullVersion() << "]" + << "[createTranslationUnitFromSourceFile]: clang"; for (llvm::SmallVectorImpl<const char*>::iterator I=Args.begin(), E=Args.end(); I!=E; ++I) Out << ' ' << *I; @@ -1002,7 +1003,8 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx, // FIXME: Until we have broader testing, just drop the entire AST if we // encountered an error. if (NumErrors != Diags->getNumErrors()) { - if (CXXIdx->getDisplayDiagnostics()) { + // Make sure to check that 'Unit' is non-NULL. + if (CXXIdx->getDisplayDiagnostics() && Unit.get()) { for (ASTUnit::diag_iterator D = Unit->diag_begin(), DEnd = Unit->diag_end(); D != DEnd; ++D) { @@ -1527,6 +1529,8 @@ CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) { ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU); + ASTUnit::ConcurrencyCheck Check(*CXXUnit); + SourceLocation SLoc = cxloc::translateSourceLocation(Loc); CXCursor Result = MakeCXCursorInvalid(CXCursor_NoDeclFound); if (SLoc.isValid()) { @@ -2052,6 +2056,8 @@ void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, if (!CXXUnit || !Tokens || !NumTokens) return; + ASTUnit::ConcurrencyCheck Check(*CXXUnit); + SourceRange R = cxloc::translateCXSourceRange(Range); if (R.isInvalid()) return; @@ -2175,6 +2181,8 @@ void clang_annotateTokens(CXTranslationUnit TU, if (!CXXUnit || !Tokens) return; + ASTUnit::ConcurrencyCheck Check(*CXXUnit); + // Annotate all of the source locations in the region of interest that map SourceRange RegionOfInterest; RegionOfInterest.setBegin( diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index 967afb763430..38c8811ab81e 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -431,10 +431,10 @@ static enum CXChildVisitResult PrintLinkage(CXCursor cursor, CXCursor p, switch (clang_getCursorLinkage(cursor)) { case CXLinkage_Invalid: break; - case CXLinkage_NoLinkage: linkage = "NoLinkage"; - case CXLinkage_Internal: linkage = "Internal"; - case CXLinkage_UniqueExternal: linkage = "UniqueExternal"; - case CXLinkage_External: linkage = "External"; + case CXLinkage_NoLinkage: linkage = "NoLinkage"; break; + case CXLinkage_Internal: linkage = "Internal"; break; + case CXLinkage_UniqueExternal: linkage = "UniqueExternal"; break; + case CXLinkage_External: linkage = "External"; break; } if (linkage) { |