aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2010-03-06 09:23:02 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2010-03-06 09:23:02 +0000
commitdd5132ce2569a1ef901c92772eb8581aa1705f25 (patch)
tree7e0a88c3c6cb70271946aaa95a231b3da55d9f91
parent79ade4e028932fcb9dab15e2fb2305ca15ab0f14 (diff)
downloadsrc-dd5132ce2569a1ef901c92772eb8581aa1705f25.tar.gz
src-dd5132ce2569a1ef901c92772eb8581aa1705f25.zip
Update clang to r97873.
Notes
Notes: svn path=/vendor/clang/dist/; revision=204793
-rw-r--r--docs/Makefile18
-rw-r--r--docs/tools/Makefile6
-rw-r--r--include/clang/AST/ASTContext.h3
-rw-r--r--include/clang/AST/DeclBase.h2
-rw-r--r--include/clang/Basic/Builtins.def5
-rw-r--r--include/clang/Basic/BuiltinsARM.def20
-rw-r--r--include/clang/Basic/BuiltinsX86.def4
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td9
-rw-r--r--include/clang/Basic/TargetBuiltins.h18
-rw-r--r--include/clang/Basic/TokenKinds.def4
-rw-r--r--include/clang/Checker/PathSensitive/Environment.h12
-rw-r--r--include/clang/Checker/PathSensitive/GRState.h13
-rw-r--r--include/clang/Checker/PathSensitive/SymbolManager.h15
-rw-r--r--include/clang/Driver/HostInfo.h2
-rw-r--r--include/clang/Driver/Options.td5
-rw-r--r--include/clang/Frontend/ASTUnit.h30
-rw-r--r--lib/AST/ASTContext.cpp8
-rw-r--r--lib/AST/DeclBase.cpp10
-rw-r--r--lib/Basic/Targets.cpp35
-rw-r--r--lib/Basic/Version.cpp6
-rw-r--r--lib/Checker/Environment.cpp8
-rw-r--r--lib/Checker/GRExprEngine.cpp7
-rw-r--r--lib/Checker/GRState.cpp14
-rw-r--r--lib/Checker/SymbolManager.cpp10
-rw-r--r--lib/CodeGen/CGBlocks.cpp17
-rw-r--r--lib/CodeGen/CGBlocks.h4
-rw-r--r--lib/CodeGen/CGBuiltin.cpp48
-rw-r--r--lib/CodeGen/CGCXX.cpp6
-rw-r--r--lib/CodeGen/CGExpr.cpp10
-rw-r--r--lib/CodeGen/CGExprConstant.cpp4
-rw-r--r--lib/CodeGen/CGExprScalar.cpp2
-rw-r--r--lib/CodeGen/CGStmt.cpp11
-rw-r--r--lib/CodeGen/CodeGenFunction.h1
-rw-r--r--lib/CodeGen/CodeGenModule.cpp60
-rw-r--r--lib/CodeGen/CodeGenModule.h10
-rw-r--r--lib/CodeGen/Mangle.cpp66
-rw-r--r--lib/CodeGen/Mangle.h17
-rw-r--r--lib/CodeGen/TargetInfo.cpp81
-rw-r--r--lib/CodeGen/TargetInfo.h17
-rw-r--r--lib/Driver/Driver.cpp4
-rw-r--r--lib/Driver/HostInfo.cpp46
-rw-r--r--lib/Driver/ToolChains.cpp60
-rw-r--r--lib/Driver/ToolChains.h20
-rw-r--r--lib/Frontend/ASTUnit.cpp3
-rw-r--r--lib/Frontend/CacheTokens.cpp4
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp11
-rw-r--r--lib/Frontend/RewriteObjC.cpp26
-rw-r--r--lib/Headers/smmintrin.h130
-rw-r--r--lib/Lex/PPMacroExpansion.cpp1
-rw-r--r--lib/Sema/Sema.h8
-rw-r--r--lib/Sema/SemaDeclCXX.cpp31
-rw-r--r--lib/Sema/SemaExpr.cpp134
-rw-r--r--lib/Sema/SemaExprCXX.cpp2
-rw-r--r--lib/Sema/SemaInit.cpp3
-rw-r--r--lib/Sema/SemaOverload.cpp41
-rw-r--r--lib/Sema/SemaType.cpp3
-rw-r--r--lib/Sema/TreeTransform.h2
-rw-r--r--test/Analysis/inline3.c15
-rw-r--r--test/CXX/class.derived/class.member.lookup/p8.cpp63
-rw-r--r--test/CXX/except/except.handle/p16.cpp40
-rw-r--r--test/CodeGen/asm-2.c10
-rw-r--r--test/CodeGen/asm-inout.c18
-rw-r--r--test/CodeGen/asm.c33
-rw-r--r--test/CodeGen/attr-weakref.c62
-rw-r--r--test/CodeGen/attr-weakref2.c54
-rw-r--r--test/CodeGen/attributes.c6
-rw-r--r--test/CodeGen/blockstret.c106
-rw-r--r--test/CodeGen/builtins-arm.c6
-rw-r--r--test/CodeGen/builtins-x86.c4
-rw-r--r--test/CodeGen/builtins.c1
-rw-r--r--test/CodeGenCXX/mangle-local-class-names.cpp57
-rw-r--r--test/CodeGenObjC/id-isa-codegen.m18
-rw-r--r--test/Index/linkage.c13
-rw-r--r--test/Rewriter/rewrite-byref-vars.mm3
-rw-r--r--test/Rewriter/rewrite-nested-ivar.mm6
-rw-r--r--test/Rewriter/rewrite-protocol-qualified.mm13
-rw-r--r--test/Rewriter/rewrite-static-block.mm11
-rw-r--r--test/Sema/block-byref-args.c6
-rw-r--r--test/Sema/scope-check.c4
-rw-r--r--test/SemaObjC/check-dup-objc-decls-1.m5
-rw-r--r--test/SemaObjC/unused.m10
-rw-r--r--test/lit.cfg12
-rw-r--r--tools/CIndex/CIndex.cpp12
-rw-r--r--tools/c-index-test/c-index-test.c8
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) {