Vendor import of clang release_70 branch r348686:

https://llvm.org/svn/llvm-project/cfe/branches/release_70@348686
This commit is contained in:
Dimitry Andric 2018-12-08 14:31:58 +00:00
parent 6ae2bfad8a
commit 52c5eb8567
15 changed files with 329 additions and 116 deletions

View File

@ -1216,7 +1216,6 @@ public:
value_type SingleElement;
public:
iterator() = default;
explicit iterator(pointer Pos, value_type Single = nullptr)
: IteratorBase(Pos), SingleElement(Single) {}

View File

@ -1953,6 +1953,39 @@ def Target : InheritableAttr {
return parse(getFeaturesStr());
}
StringRef getArchitecture() const {
StringRef Features = getFeaturesStr();
if (Features == "default") return {};
SmallVector<StringRef, 1> AttrFeatures;
Features.split(AttrFeatures, ",");
for (auto &Feature : AttrFeatures) {
Feature = Feature.trim();
if (Feature.startswith("arch="))
return Feature.drop_front(sizeof("arch=") - 1);
}
return "";
}
// Gets the list of features as simple string-refs with no +/- or 'no-'.
// Only adds the items to 'Out' that are additions.
void getAddedFeatures(llvm::SmallVectorImpl<StringRef> &Out) const {
StringRef Features = getFeaturesStr();
if (Features == "default") return;
SmallVector<StringRef, 1> AttrFeatures;
Features.split(AttrFeatures, ",");
for (auto &Feature : AttrFeatures) {
Feature = Feature.trim();
if (!Feature.startswith("no-") && !Feature.startswith("arch=") &&
!Feature.startswith("fpmath=") && !Feature.startswith("tune="))
Out.push_back(Feature);
}
}
template<class Compare>
ParsedTargetAttr parse(Compare cmp) const {
ParsedTargetAttr Attrs = parse();

View File

@ -9734,6 +9734,10 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
return true;
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
// Multiversioned functions always have to be emitted, because they are used
// by the resolver.
if (FD->isMultiVersion())
return true;
// Forward declarations aren't required.
if (!FD->doesThisDeclarationHaveABody())
return FD->doesDeclarationForceExternallyVisibleDefinition();

View File

@ -725,7 +725,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
// If we're paying attention to global visibility, apply
// -finline-visibility-hidden if this is an inline method.
if (useInlineVisibilityHidden(D))
LV.mergeVisibility(HiddenVisibility, true);
LV.mergeVisibility(HiddenVisibility, /*visibilityExplicit=*/false);
}
}
@ -915,7 +915,7 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D,
// Note that we do this before merging information about
// the class visibility.
if (!LV.isVisibilityExplicit() && useInlineVisibilityHidden(D))
LV.mergeVisibility(HiddenVisibility, true);
LV.mergeVisibility(HiddenVisibility, /*visibilityExplicit=*/false);
}
// If this class member has an explicit visibility attribute, the only
@ -1262,7 +1262,27 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
!isTemplateInstantiation(FD->getTemplateSpecializationKind()))
return LinkageInfo::none();
// If a function is hidden by -fvisibility-inlines-hidden option and
// is not explicitly attributed as a hidden function,
// we should not make static local variables in the function hidden.
LV = getLVForDecl(FD, computation);
if (isa<VarDecl>(D) && useInlineVisibilityHidden(FD) &&
!LV.isVisibilityExplicit()) {
assert(cast<VarDecl>(D)->isStaticLocal());
// If this was an implicitly hidden inline method, check again for
// explicit visibility on the parent class, and use that for static locals
// if present.
if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
LV = getLVForDecl(MD->getParent(), computation);
if (!LV.isVisibilityExplicit()) {
Visibility globalVisibility =
computation.isValueVisibility()
? Context.getLangOpts().getValueVisibilityMode()
: Context.getLangOpts().getTypeVisibilityMode();
return LinkageInfo(VisibleNoLinkage, globalVisibility,
/*visibilityExplicit=*/false);
}
}
}
if (!isExternallyVisible(LV.getLinkage()))
return LinkageInfo::none();

View File

@ -2359,91 +2359,53 @@ void CodeGenFunction::EmitSanitizerStatReport(llvm::SanitizerStatKind SSK) {
CGM.getSanStats().create(IRB, SSK);
}
llvm::Value *CodeGenFunction::FormResolverCondition(
const TargetMultiVersionResolverOption &RO) {
llvm::Value *TrueCondition = nullptr;
if (!RO.ParsedAttribute.Architecture.empty())
TrueCondition = EmitX86CpuIs(RO.ParsedAttribute.Architecture);
llvm::Value *
CodeGenFunction::FormResolverCondition(const MultiVersionResolverOption &RO) {
llvm::Value *Condition = nullptr;
if (!RO.ParsedAttribute.Features.empty()) {
SmallVector<StringRef, 8> FeatureList;
llvm::for_each(RO.ParsedAttribute.Features,
[&FeatureList](const std::string &Feature) {
FeatureList.push_back(StringRef{Feature}.substr(1));
});
llvm::Value *FeatureCmp = EmitX86CpuSupports(FeatureList);
TrueCondition = TrueCondition ? Builder.CreateAnd(TrueCondition, FeatureCmp)
: FeatureCmp;
if (!RO.Conditions.Architecture.empty())
Condition = EmitX86CpuIs(RO.Conditions.Architecture);
if (!RO.Conditions.Features.empty()) {
llvm::Value *FeatureCond = EmitX86CpuSupports(RO.Conditions.Features);
Condition =
Condition ? Builder.CreateAnd(Condition, FeatureCond) : FeatureCond;
}
return TrueCondition;
return Condition;
}
void CodeGenFunction::EmitTargetMultiVersionResolver(
llvm::Function *Resolver,
ArrayRef<TargetMultiVersionResolverOption> Options) {
void CodeGenFunction::EmitMultiVersionResolver(
llvm::Function *Resolver, ArrayRef<MultiVersionResolverOption> Options) {
assert((getContext().getTargetInfo().getTriple().getArch() ==
llvm::Triple::x86 ||
getContext().getTargetInfo().getTriple().getArch() ==
llvm::Triple::x86_64) &&
"Only implemented for x86 targets");
// Main function's basic block.
llvm::BasicBlock *CurBlock = createBasicBlock("entry", Resolver);
Builder.SetInsertPoint(CurBlock);
EmitX86CpuInit();
llvm::Function *DefaultFunc = nullptr;
for (const TargetMultiVersionResolverOption &RO : Options) {
Builder.SetInsertPoint(CurBlock);
llvm::Value *TrueCondition = FormResolverCondition(RO);
if (!TrueCondition) {
DefaultFunc = RO.Function;
} else {
llvm::BasicBlock *RetBlock = createBasicBlock("ro_ret", Resolver);
llvm::IRBuilder<> RetBuilder(RetBlock);
RetBuilder.CreateRet(RO.Function);
CurBlock = createBasicBlock("ro_else", Resolver);
Builder.CreateCondBr(TrueCondition, RetBlock, CurBlock);
}
}
assert(DefaultFunc && "No default version?");
// Emit return from the 'else-ist' block.
Builder.SetInsertPoint(CurBlock);
Builder.CreateRet(DefaultFunc);
}
void CodeGenFunction::EmitCPUDispatchMultiVersionResolver(
llvm::Function *Resolver,
ArrayRef<CPUDispatchMultiVersionResolverOption> Options) {
assert((getContext().getTargetInfo().getTriple().getArch() ==
llvm::Triple::x86 ||
getContext().getTargetInfo().getTriple().getArch() ==
llvm::Triple::x86_64) &&
"Only implemented for x86 targets");
// Main function's basic block.
llvm::BasicBlock *CurBlock = createBasicBlock("resolver_entry", Resolver);
Builder.SetInsertPoint(CurBlock);
EmitX86CpuInit();
for (const CPUDispatchMultiVersionResolverOption &RO : Options) {
for (const MultiVersionResolverOption &RO : Options) {
Builder.SetInsertPoint(CurBlock);
llvm::Value *Condition = FormResolverCondition(RO);
// "generic" case should catch-all.
if (RO.FeatureMask == 0) {
// The 'default' or 'generic' case.
if (!Condition) {
assert(&RO == Options.end() - 1 &&
"Default or Generic case must be last");
Builder.CreateRet(RO.Function);
return;
}
llvm::BasicBlock *RetBlock = createBasicBlock("resolver_return", Resolver);
llvm::IRBuilder<> RetBuilder(RetBlock);
RetBuilder.CreateRet(RO.Function);
CurBlock = createBasicBlock("resolver_else", Resolver);
llvm::Value *TrueCondition = EmitX86CpuSupports(RO.FeatureMask);
Builder.CreateCondBr(TrueCondition, RetBlock, CurBlock);
Builder.CreateCondBr(Condition, RetBlock, CurBlock);
}
// If no generic/default, emit an unreachable.
Builder.SetInsertPoint(CurBlock);
llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
TrapCall->setDoesNotReturn();

View File

@ -4247,30 +4247,26 @@ public:
void EmitSanitizerStatReport(llvm::SanitizerStatKind SSK);
struct TargetMultiVersionResolverOption {
struct MultiVersionResolverOption {
llvm::Function *Function;
TargetAttr::ParsedTargetAttr ParsedAttribute;
unsigned Priority;
TargetMultiVersionResolverOption(
const TargetInfo &TargInfo, llvm::Function *F,
const clang::TargetAttr::ParsedTargetAttr &PT)
: Function(F), ParsedAttribute(PT), Priority(0u) {
for (StringRef Feat : PT.Features)
Priority = std::max(Priority,
TargInfo.multiVersionSortPriority(Feat.substr(1)));
struct Conds {
StringRef Architecture;
llvm::SmallVector<StringRef, 8> Features;
if (!PT.Architecture.empty())
Priority = std::max(Priority,
TargInfo.multiVersionSortPriority(PT.Architecture));
}
Conds(StringRef Arch, ArrayRef<StringRef> Feats)
: Architecture(Arch), Features(Feats.begin(), Feats.end()) {}
} Conditions;
bool operator>(const TargetMultiVersionResolverOption &Other) const {
return Priority > Other.Priority;
}
MultiVersionResolverOption(llvm::Function *F, StringRef Arch,
ArrayRef<StringRef> Feats)
: Function(F), Conditions(Arch, Feats) {}
};
void EmitTargetMultiVersionResolver(
llvm::Function *Resolver,
ArrayRef<TargetMultiVersionResolverOption> Options);
// Emits the body of a multiversion function's resolver. Assumes that the
// options are already sorted in the proper order, with the 'default' option
// last (if it exists).
void EmitMultiVersionResolver(llvm::Function *Resolver,
ArrayRef<MultiVersionResolverOption> Options);
struct CPUDispatchMultiVersionResolverOption {
llvm::Function *Function;
@ -4306,8 +4302,7 @@ private:
llvm::Value *EmitX86CpuSupports(ArrayRef<StringRef> FeatureStrs);
llvm::Value *EmitX86CpuSupports(uint32_t Mask);
llvm::Value *EmitX86CpuInit();
llvm::Value *
FormResolverCondition(const TargetMultiVersionResolverOption &RO);
llvm::Value *FormResolverCondition(const MultiVersionResolverOption &RO);
};
inline DominatingLLVMValue::saved_type

View File

@ -2399,9 +2399,22 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old,
llvm::Function *NewFn);
static unsigned
TargetMVPriority(const TargetInfo &TI,
const CodeGenFunction::MultiVersionResolverOption &RO) {
unsigned Priority = 0;
for (StringRef Feat : RO.Conditions.Features)
Priority = std::max(Priority, TI.multiVersionSortPriority(Feat));
if (!RO.Conditions.Architecture.empty())
Priority = std::max(
Priority, TI.multiVersionSortPriority(RO.Conditions.Architecture));
return Priority;
}
void CodeGenModule::emitMultiVersionFunctions() {
for (GlobalDecl GD : MultiVersionFuncs) {
SmallVector<CodeGenFunction::TargetMultiVersionResolverOption, 10> Options;
SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options;
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
getContext().forEachMultiversionedFunctionVersion(
FD, [this, &GD, &Options](const FunctionDecl *CurFD) {
@ -2422,8 +2435,13 @@ void CodeGenModule::emitMultiVersionFunctions() {
}
assert(Func && "This should have just been created");
}
Options.emplace_back(getTarget(), cast<llvm::Function>(Func),
CurFD->getAttr<TargetAttr>()->parse());
const auto *TA = CurFD->getAttr<TargetAttr>();
llvm::SmallVector<StringRef, 8> Feats;
TA->getAddedFeatures(Feats);
Options.emplace_back(cast<llvm::Function>(Func),
TA->getArchitecture(), Feats);
});
llvm::Function *ResolverFunc = cast<llvm::Function>(
@ -2431,11 +2449,16 @@ void CodeGenModule::emitMultiVersionFunctions() {
if (supportsCOMDAT())
ResolverFunc->setComdat(
getModule().getOrInsertComdat(ResolverFunc->getName()));
const TargetInfo &TI = getTarget();
std::stable_sort(
Options.begin(), Options.end(),
std::greater<CodeGenFunction::TargetMultiVersionResolverOption>());
[&TI](const CodeGenFunction::MultiVersionResolverOption &LHS,
const CodeGenFunction::MultiVersionResolverOption &RHS) {
return TargetMVPriority(TI, LHS) > TargetMVPriority(TI, RHS);
});
CodeGenFunction CGF(*this);
CGF.EmitTargetMultiVersionResolver(ResolverFunc, Options);
CGF.EmitMultiVersionResolver(ResolverFunc, Options);
}
}
@ -2444,7 +2467,13 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
assert(FD && "Not a FunctionDecl?");
const auto *DD = FD->getAttr<CPUDispatchAttr>();
assert(DD && "Not a cpu_dispatch Function?");
llvm::Type *DeclTy = getTypes().ConvertTypeForMem(FD->getType());
QualType CanonTy = Context.getCanonicalType(FD->getType());
llvm::Type *DeclTy = getTypes().ConvertFunctionType(CanonTy, FD);
if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
const CGFunctionInfo &FInfo = getTypes().arrangeCXXMethodDeclaration(CXXFD);
DeclTy = getTypes().GetFunctionType(FInfo);
}
StringRef ResolverName = getMangledName(GD);
llvm::Type *ResolverType = llvm::FunctionType::get(
@ -2455,15 +2484,14 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
GetOrCreateLLVMFunction(ResolverName, ResolverType, GlobalDecl{},
/*ForVTable=*/false));
SmallVector<CodeGenFunction::CPUDispatchMultiVersionResolverOption, 10>
Options;
SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options;
const TargetInfo &Target = getTarget();
for (const IdentifierInfo *II : DD->cpus()) {
// Get the name of the target function so we can look it up/create it.
std::string MangledName = getMangledNameImpl(*this, GD, FD, true) +
getCPUSpecificMangling(*this, II->getName());
llvm::Constant *Func = GetOrCreateLLVMFunction(
MangledName, DeclTy, GD, /*ForVTable=*/false, /*DontDefer=*/false,
MangledName, DeclTy, GD, /*ForVTable=*/false, /*DontDefer=*/true,
/*IsThunk=*/false, llvm::AttributeList(), ForDefinition);
llvm::SmallVector<StringRef, 32> Features;
Target.getCPUSpecificCPUDispatchFeatures(II->getName(), Features);
@ -2473,15 +2501,34 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
Features.begin(), Features.end(), [&Target](StringRef Feat) {
return !Target.validateCpuSupports(Feat);
}), Features.end());
Options.emplace_back(cast<llvm::Function>(Func),
CodeGenFunction::GetX86CpuSupportsMask(Features));
Options.emplace_back(cast<llvm::Function>(Func), StringRef{}, Features);
}
llvm::sort(
Options.begin(), Options.end(),
std::greater<CodeGenFunction::CPUDispatchMultiVersionResolverOption>());
[](const CodeGenFunction::MultiVersionResolverOption &LHS,
const CodeGenFunction::MultiVersionResolverOption &RHS) {
return CodeGenFunction::GetX86CpuSupportsMask(LHS.Conditions.Features) >
CodeGenFunction::GetX86CpuSupportsMask(RHS.Conditions.Features);
});
// If the list contains multiple 'default' versions, such as when it contains
// 'pentium' and 'generic', don't emit the call to the generic one (since we
// always run on at least a 'pentium'). We do this by deleting the 'least
// advanced' (read, lowest mangling letter).
while (Options.size() > 1 &&
CodeGenFunction::GetX86CpuSupportsMask(
(Options.end() - 2)->Conditions.Features) == 0) {
StringRef LHSName = (Options.end() - 2)->Function->getName();
StringRef RHSName = (Options.end() - 1)->Function->getName();
if (LHSName.compare(RHSName) < 0)
Options.erase(Options.end() - 2);
else
Options.erase(Options.end() - 1);
}
CodeGenFunction CGF(*this);
CGF.EmitCPUDispatchMultiVersionResolver(ResolverFunc, Options);
CGF.EmitMultiVersionResolver(ResolverFunc, Options);
}
/// If an ifunc for the specified mangled name is not in the module, create and

View File

@ -138,7 +138,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_pie))
CmdArgs.push_back("-pie");
if (Args.hasArg(options::OPT_nopie))
if (Args.hasArg(options::OPT_nopie) || Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-nopie");
if (Output.isFilename()) {

View File

@ -475,9 +475,6 @@ static Optional<NonLoc> tryRearrange(ProgramStateRef State,
SingleTy = ResultTy;
if (LSym->getType() != SingleTy)
return None;
// Substracting unsigned integers is a nightmare.
if (!SingleTy->isSignedIntegerOrEnumerationType())
return None;
} else {
// Don't rearrange other operations.
return None;
@ -485,6 +482,10 @@ static Optional<NonLoc> tryRearrange(ProgramStateRef State,
assert(!SingleTy.isNull() && "We should have figured out the type by now!");
// Rearrange signed symbolic expressions only
if (!SingleTy->isSignedIntegerOrEnumerationType())
return None;
SymbolRef RSym = Rhs.getAsSymbol();
if (!RSym || RSym->getType() != SingleTy)
return None;

View File

@ -934,3 +934,17 @@ int mixed_integer_types(int x, int y) {
short a = x - 1U;
return a - y;
}
unsigned gu();
unsigned fu() {
unsigned x = gu();
// Assert that no overflows occur in this test file.
// Assuming that concrete integers are also within that range.
assert(x <= ((unsigned)UINT_MAX / 4));
return x;
}
void unsigned_concrete_int_no_crash() {
unsigned x = fu() + 1U, y = fu() + 1U;
clang_analyzer_dump(x == y); // expected-warning {{((conj_$2{unsigned int}) + 1U) == ((conj_$7{unsigned int}) + 1U)}}
}

View File

@ -96,6 +96,15 @@ void HasGeneric(void);
// CHECK: ret void ()* @HasGeneric.A
// CHECK-NOT: call void @llvm.trap
__attribute__((cpu_dispatch(atom, generic, pentium)))
int GenericAndPentium(int i, double d);
// CHECK: define i32 (i32, double)* @GenericAndPentium.resolver()
// CHECK: call void @__cpu_indicator_init
// CHECK: ret i32 (i32, double)* @GenericAndPentium.O
// CHECK: ret i32 (i32, double)* @GenericAndPentium.B
// CHECK-NOT: ret i32 (i32, double)* @GenericAndPentium.A
// CHECK-NOT: call void @llvm.trap
// CHECK: attributes #[[S]] = {{.*}}"target-features"="+avx,+cmov,+f16c,+mmx,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave"
// CHECK: attributes #[[K]] = {{.*}}"target-features"="+adx,+avx,+avx2,+avx512cd,+avx512er,+avx512f,+avx512pf,+bmi,+cmov,+f16c,+fma,+lzcnt,+mmx,+movbe,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave"
// CHECK: attributes #[[O]] = {{.*}}"target-features"="+cmov,+mmx,+movbe,+sse,+sse2,+sse3,+ssse3,+x87"

View File

@ -0,0 +1,18 @@
// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,LINUX
struct S {
__attribute__((cpu_specific(atom)))
void Func(){}
__attribute__((cpu_dispatch(ivybridge,atom)))
void Func(){}
};
void foo() {
S s;
s.Func();
}
// LINUX: define linkonce_odr void @_ZN1S4FuncEv.O
// LINUX: define void (%struct.S*)* @_ZN1S4FuncEv.resolver
// LINUX: ret void (%struct.S*)* @_ZN1S4FuncEv.S
// LINUX: ret void (%struct.S*)* @_ZN1S4FuncEv.O

View File

@ -72,6 +72,15 @@ int templ_use() {
// CHECK: @_ZN5templIiE3fooEi.ifunc = ifunc i32 (%struct.templ*, i32), i32 (%struct.templ*, i32)* ()* @_ZN5templIiE3fooEi.resolver
// CHECK: @_ZN5templIdE3fooEi.ifunc = ifunc i32 (%struct.templ.0*, i32), i32 (%struct.templ.0*, i32)* ()* @_ZN5templIdE3fooEi.resolver
// CHECK: define linkonce_odr i32 @_ZN1S3fooEi.sse4.2(%struct.S* %this, i32)
// CHECK: ret i32 0
// CHECK: define linkonce_odr i32 @_ZN1S3fooEi.arch_ivybridge(%struct.S* %this, i32)
// CHECK: ret i32 1
// CHECK: define linkonce_odr i32 @_ZN1S3fooEi(%struct.S* %this, i32)
// CHECK: ret i32 2
// CHECK: define i32 @_Z3barv()
// CHECK: %s = alloca %struct.S, align 1
// CHECK: %s2 = alloca %struct.S, align 1
@ -123,23 +132,14 @@ int templ_use() {
// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.sse4.2
// CHECK: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi
// CHECK: define linkonce_odr i32 @_ZN1S3fooEi.sse4.2(%struct.S* %this, i32)
// CHECK: ret i32 0
// CHECK: declare i32 @_ZN1S3fooEi.arch_sandybridge(%struct.S*, i32)
// CHECK: define linkonce_odr i32 @_ZN1S3fooEi.arch_ivybridge(%struct.S* %this, i32)
// CHECK: ret i32 1
// CHECK: define linkonce_odr i32 @_ZN1S3fooEi(%struct.S* %this, i32)
// CHECK: ret i32 2
// CHECK: define linkonce_odr i32 @_ZN5templIiE3fooEi.sse4.2
// CHECK: declare i32 @_ZN5templIiE3fooEi.arch_sandybridge
// CHECK: define linkonce_odr i32 @_ZN5templIiE3fooEi.arch_ivybridge
// CHECK: define linkonce_odr i32 @_ZN5templIiE3fooEi
// CHECK: define linkonce_odr i32 @_ZN5templIdE3fooEi.sse4.2
// CHECK: declare i32 @_ZN5templIdE3fooEi.arch_sandybridge
// CHECK: define linkonce_odr i32 @_ZN5templIdE3fooEi.arch_ivybridge
// CHECK: define linkonce_odr i32 @_ZN5templIdE3fooEi
//
// CHECK: declare i32 @_ZN1S3fooEi.arch_sandybridge(%struct.S*, i32)
// CHECK: declare i32 @_ZN5templIiE3fooEi.arch_sandybridge
// CHECK: declare i32 @_ZN5templIdE3fooEi.arch_sandybridge

View File

@ -0,0 +1,111 @@
// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s
// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck -check-prefixes=CHECK-NO-VIH %s
// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility hidden -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s --check-prefix=CHECK-VIS-HIDDEN
// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility protected -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s --check-prefix=CHECK-VIS-PROTECTED
// When a function is hidden due to -fvisibility-inlines-hidden option, static local variables of the function should not be hidden by the option.
// CHECK-DAG: @_ZZ4funcvE3var = internal global i32 0
// CHECK-DAG: @_ZZ11hidden_funcvE3var = internal global i32 0
// CHECK-DAG: @_ZZ12default_funcvE3var = internal global i32 0
// CHECK-DAG: @_ZZ11inline_funcvE3var = linkonce_odr global i32 0, comdat
// CHECK-DAG: @_ZZ18inline_hidden_funcvE3var = linkonce_odr hidden global i32 0, comdat
// CHECK-DAG: @_ZZ19inline_default_funcvE3var = linkonce_odr global i32 0, comdat
// CHECK-DAG: @_ZZN13ExportedClass10inl_methodEvE3var = linkonce_odr global i32 0, comdat, align 4
// CHECK-DAG: define i32 @_Z4funcv()
// CHECK-DAG: define hidden i32 @_Z11hidden_funcv()
// CHECK-DAG: define i32 @_Z12default_funcv()
// CHECK-DAG: define linkonce_odr hidden i32 @_Z11inline_funcv()
// CHECK-DAG: define linkonce_odr hidden i32 @_Z18inline_hidden_funcv()
// CHECK-DAG: define linkonce_odr i32 @_Z19inline_default_funcv()
// CHECK-DAG: define linkonce_odr hidden i32 @_ZN13ExportedClass10inl_methodEv({{.*}})
// CHECK-DAG: define i32 @_ZN13ExportedClass10ext_methodEv({{.*}})
// CHECK-NO-VIH-DAG: @_ZZ4funcvE3var = internal global i32 0
// CHECK-NO-VIH-DAG: @_ZZ11hidden_funcvE3var = internal global i32 0
// CHECK-NO-VIH-DAG: @_ZZ12default_funcvE3var = internal global i32 0
// CHECK-NO-VIH-DAG: @_ZZ11inline_funcvE3var = linkonce_odr global i32 0, comdat
// CHECK-NO-VIH-DAG: @_ZZ18inline_hidden_funcvE3var = linkonce_odr hidden global i32 0, comdat
// CHECK-NO-VIH-DAG: @_ZZ19inline_default_funcvE3var = linkonce_odr global i32 0, comdat
// CHECK-NO-VIH-DAG: @_ZZN13ExportedClass10inl_methodEvE3var = linkonce_odr global i32 0, comdat, align 4
// CHECK-NO-VIH-DAG: define i32 @_Z4funcv()
// CHECK-NO-VIH-DAG: define hidden i32 @_Z11hidden_funcv()
// CHECK-NO-VIH-DAG: define i32 @_Z12default_funcv()
// CHECK-NO-VIH-DAG: define linkonce_odr i32 @_Z11inline_funcv()
// CHECK-NO-VIH-DAG: define linkonce_odr hidden i32 @_Z18inline_hidden_funcv()
// CHECK-NO-VIH-DAG: define linkonce_odr i32 @_Z19inline_default_funcv()
// CHECK-NO-VIH-DAG: define linkonce_odr i32 @_ZN13ExportedClass10inl_methodEv({{.*}})
// CHECK-NO-VIH-DAG: define i32 @_ZN13ExportedClass10ext_methodEv({{.*}})
// CHECK-VIS-HIDDEN-DAG: @_ZZ4funcvE3var = internal global i32 0
// CHECK-VIS-HIDDEN-DAG: @_ZZ11hidden_funcvE3var = internal global i32 0
// CHECK-VIS-HIDDEN-DAG: @_ZZ12default_funcvE3var = internal global i32 0
// CHECK-VIS-HIDDEN-DAG: @_ZZ11inline_funcvE3var = linkonce_odr hidden global i32 0, comdat
// CHECK-VIS-HIDDEN-DAG: @_ZZ18inline_hidden_funcvE3var = linkonce_odr hidden global i32 0, comdat
// CHECK-VIS-HIDDEN-DAG: @_ZZ19inline_default_funcvE3var = linkonce_odr global i32 0, comdat
// CHECK-VIS-HIDDEN-DAG: @_ZZN13ExportedClass10inl_methodEvE3var = linkonce_odr global i32 0, comdat, align 4
// CHECK-VIS-HIDDEN-DAG: define hidden i32 @_Z4funcv()
// CHECK-VIS-HIDDEN-DAG: define hidden i32 @_Z11hidden_funcv()
// CHECK-VIS-HIDDEN-DAG: define i32 @_Z12default_funcv()
// CHECK-VIS-HIDDEN-DAG: define linkonce_odr hidden i32 @_Z11inline_funcv()
// CHECK-VIS-HIDDEN-DAG: define linkonce_odr hidden i32 @_Z18inline_hidden_funcv()
// CHECK-VIS-HIDDEN-DAG: define linkonce_odr i32 @_Z19inline_default_funcv()
// CHECK-VIS-HIDDEN-DAG: define linkonce_odr hidden i32 @_ZN13ExportedClass10inl_methodEv({{.*}})
// CHECK-VIS-HIDDEN-DAG: define i32 @_ZN13ExportedClass10ext_methodEv({{.*}})
// CHECK-VIS-PROTECTED-DAG: @_ZZ4funcvE3var = internal global i32 0
// CHECK-VIS-PROTECTED-DAG: @_ZZ11hidden_funcvE3var = internal global i32 0
// CHECK-VIS-PROTECTED-DAG: @_ZZ12default_funcvE3var = internal global i32 0
// CHECK-VIS-PROTECTED-DAG: @_ZZ11inline_funcvE3var = linkonce_odr protected global i32 0, comdat
// CHECK-VIS-PROTECTED-DAG: @_ZZ18inline_hidden_funcvE3var = linkonce_odr hidden global i32 0, comdat
// CHECK-VIS-PROTECTED-DAG: @_ZZ19inline_default_funcvE3var = linkonce_odr global i32 0, comdat
// CHECK-VIS-PROTECTED-DAG: @_ZZN13ExportedClass10inl_methodEvE3var = linkonce_odr global i32 0, comdat, align 4
// CHECK-VIS-PROTECTED-DAG: define protected i32 @_Z4funcv()
// CHECK-VIS-PROTECTED-DAG: define hidden i32 @_Z11hidden_funcv()
// CHECK-VIS-PROTECTED-DAG: define i32 @_Z12default_funcv()
// CHECK-VIS-PROTECTED-DAG: define linkonce_odr hidden i32 @_Z11inline_funcv()
// CHECK-VIS-PROTECTED-DAG: define linkonce_odr hidden i32 @_Z18inline_hidden_funcv()
// CHECK-VIS-PROTECTED-DAG: define linkonce_odr i32 @_Z19inline_default_funcv()
// CHECK-VIS-PROTECTED-DAG: define linkonce_odr hidden i32 @_ZN13ExportedClass10inl_methodEv({{.*}})
// CHECK-VIS-PROTECTED-DAG: define i32 @_ZN13ExportedClass10ext_methodEv({{.*}})
int func(void) {
static int var = 0;
return var++;
}
inline int inline_func(void) {
static int var = 0;
return var++;
}
int __attribute__((visibility("hidden"))) hidden_func(void) {
static int var = 0;
return var++;
}
inline int __attribute__((visibility("hidden"))) inline_hidden_func(void) {
static int var = 0;
return var++;
}
int __attribute__((visibility("default"))) default_func(void) {
static int var = 0;
return var++;
}
inline int __attribute__((visibility("default"))) inline_default_func(void) {
static int var = 0;
return var++;
}
struct __attribute__((visibility("default"))) ExportedClass {
int inl_method() {
static int var = 0;
return var++;
}
int ext_method();
};
int ExportedClass::ext_method() { return inl_method(); }
void bar(void) {
func();
inline_func();
hidden_func();
inline_hidden_func();
default_func();
inline_default_func();
}

View File

@ -12,7 +12,7 @@
// RUN: %clang -no-canonical-prefixes -target i686-pc-openbsd -pg -pthread %s -### 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-PG %s
// CHECK-PG: clang{{.*}}" "-cc1" "-triple" "i686-pc-openbsd"
// CHECK-PG: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-o" "a.out" "{{.*}}gcrt0.o" "{{.*}}crtbegin.o" "{{.*}}.o" "-lgcc" "-lpthread_p" "-lc_p" "-lgcc" "{{.*}}crtend.o"
// CHECK-PG: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-Bdynamic" "-dynamic-linker" "{{.*}}ld.so" "-nopie" "-o" "a.out" "{{.*}}gcrt0.o" "{{.*}}crtbegin.o" "{{.*}}.o" "-lgcc" "-lpthread_p" "-lc_p" "-lgcc" "{{.*}}crtend.o"
// Check CPU type for MIPS64
// RUN: %clang -target mips64-unknown-openbsd -### -c %s 2>&1 \