Vendor import of clang trunk r304460:

https://llvm.org/svn/llvm-project/cfe/trunk@304460
This commit is contained in:
Dimitry Andric 2017-06-01 20:58:49 +00:00
parent 550ae89a71
commit 416ada0f75
84 changed files with 2272 additions and 1017 deletions

View File

@ -403,7 +403,7 @@ A *requires-declaration* specifies the requirements that an importing translatio
*feature*:
``!``:sub:`opt` *identifier*
The requirements clause allows specific modules or submodules to specify that they are only accessible with certain language dialects or on certain platforms. The feature list is a set of identifiers, defined below. If any of the features is not available in a given translation unit, that translation unit shall not import the module. The optional ``!`` indicates that a feature is incompatible with the module.
The requirements clause allows specific modules or submodules to specify that they are only accessible with certain language dialects or on certain platforms. The feature list is a set of identifiers, defined below. If any of the features is not available in a given translation unit, that translation unit shall not import the module. When building a module for use by a compilation, submodules requiring unavailable features are ignored. The optional ``!`` indicates that a feature is incompatible with the module.
The following features are defined:

View File

@ -123,6 +123,8 @@ which currently must be enabled through a linker option.
``-Wl,-plugin-opt,cache-dir=/path/to/cache``
- ld64 (support in clang 3.9 and Xcode 8):
``-Wl,-cache_path_lto,/path/to/cache``
- lld (as of LLVM r296702):
``-Wl,--thinlto-cache-dir=/path/to/cache``
Clang Bootstrap
---------------

View File

@ -106,6 +106,8 @@ Available checks are:
invalid pointers. These checks are made in terms of
``__builtin_object_size``, and consequently may be able to detect more
problems at higher optimization levels.
- ``-fsanitize=pointer-overflow``: Performing pointer arithmetic which
overflows.
- ``-fsanitize=return``: In C++, reaching the end of a
value-returning function without returning a value.
- ``-fsanitize=returns-nonnull-attribute``: Returning null pointer

View File

@ -154,6 +154,28 @@ public:
bool isRTTIKind() const { return isRTTIKind(getKind()); }
GlobalDecl getGlobalDecl() const {
assert(isUsedFunctionPointerKind() &&
"GlobalDecl can be created only from virtual function");
auto *DtorDecl = dyn_cast<CXXDestructorDecl>(getFunctionDecl());
switch (getKind()) {
case CK_FunctionPointer:
return GlobalDecl(getFunctionDecl());
case CK_CompleteDtorPointer:
return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Complete);
case CK_DeletingDtorPointer:
return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Deleting);
case CK_VCallOffset:
case CK_VBaseOffset:
case CK_OffsetToTop:
case CK_RTTI:
case CK_UnusedFunctionPointer:
llvm_unreachable("Only function pointers kinds");
}
llvm_unreachable("Should already return");
}
private:
static bool isFunctionPointerKind(Kind ComponentKind) {
return isUsedFunctionPointerKind(ComponentKind) ||

View File

@ -733,6 +733,7 @@ def Pedantic : DiagGroup<"pedantic">;
// Aliases.
def : DiagGroup<"", [Extra]>; // -W = -Wextra
def : DiagGroup<"endif-labels", [ExtraTokens]>; // -Wendif-labels=-Wextra-tokens
def : DiagGroup<"cpp", [PoundWarning]>; // -Wcpp = -W#warnings
def : DiagGroup<"comments", [Comment]>; // -Wcomments = -Wcomment
def : DiagGroup<"conversion-null",
[NullConversion]>; // -Wconversion-null = -Wnull-conversion

View File

@ -32,7 +32,7 @@ namespace clang {
DIAG_START_FRONTEND = DIAG_START_DRIVER + 200,
DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + 100,
DIAG_START_LEX = DIAG_START_SERIALIZATION + 120,
DIAG_START_PARSE = DIAG_START_LEX + 300,
DIAG_START_PARSE = DIAG_START_LEX + 400,
DIAG_START_AST = DIAG_START_PARSE + 500,
DIAG_START_COMMENT = DIAG_START_AST + 110,
DIAG_START_SEMA = DIAG_START_COMMENT + 100,

View File

@ -8979,10 +8979,10 @@ def err_coroutine_promise_new_requires_nothrow : Error<
def note_coroutine_promise_call_implicitly_required : Note<
"call to %0 implicitly required by coroutine function here">;
def err_await_suspend_invalid_return_type : Error<
"the return type of 'await_suspend' is required to be 'void' or 'bool' (have %0)"
"return type of 'await_suspend' is required to be 'void' or 'bool' (have %0)"
>;
def note_await_ready_no_bool_conversion : Note<
"the return type of 'await_ready' is required to be contextually convertible to 'bool'"
"return type of 'await_ready' is required to be contextually convertible to 'bool'"
>;
}

View File

@ -83,6 +83,10 @@ public:
/// are found.
const DirectoryEntry *Directory;
/// \brief The presumed file name for the module map defining this module.
/// Only non-empty when building from preprocessed source.
std::string PresumedModuleMapFile;
/// \brief The umbrella header or directory.
llvm::PointerUnion<const DirectoryEntry *, const FileEntry *> Umbrella;

View File

@ -73,6 +73,7 @@ SANITIZER("nullability-return", NullabilityReturn)
SANITIZER_GROUP("nullability", Nullability,
NullabilityArg | NullabilityAssign | NullabilityReturn)
SANITIZER("object-size", ObjectSize)
SANITIZER("pointer-overflow", PointerOverflow)
SANITIZER("return", Return)
SANITIZER("returns-nonnull-attribute", ReturnsNonnullAttribute)
SANITIZER("shift-base", ShiftBase)
@ -108,9 +109,9 @@ SANITIZER("safe-stack", SafeStack)
SANITIZER_GROUP("undefined", Undefined,
Alignment | Bool | ArrayBounds | Enum | FloatCastOverflow |
FloatDivideByZero | IntegerDivideByZero | NonnullAttribute |
Null | ObjectSize | Return | ReturnsNonnullAttribute |
Shift | SignedIntegerOverflow | Unreachable | VLABound |
Function | Vptr)
Null | ObjectSize | PointerOverflow | Return |
ReturnsNonnullAttribute | Shift | SignedIntegerOverflow |
Unreachable | VLABound | Function | Vptr)
// -fsanitize=undefined-trap is an alias for -fsanitize=undefined.
SANITIZER_GROUP("undefined-trap", UndefinedTrap, Undefined)

View File

@ -411,6 +411,7 @@ TYPE_TRAIT_1(__is_sealed, IsSealed, KEYMS)
// MSVC12.0 / VS2013 Type Traits
TYPE_TRAIT_1(__is_destructible, IsDestructible, KEYMS)
TYPE_TRAIT_1(__is_trivially_destructible, IsTriviallyDestructible, KEYCXX)
TYPE_TRAIT_1(__is_nothrow_destructible, IsNothrowDestructible, KEYMS)
TYPE_TRAIT_2(__is_nothrow_assignable, IsNothrowAssignable, KEYCXX)
TYPE_TRAIT_N(__is_constructible, IsConstructible, KEYCXX)
@ -439,7 +440,6 @@ TYPE_TRAIT_2(__is_convertible_to, IsConvertibleTo, KEYCXX)
TYPE_TRAIT_1(__is_empty, IsEmpty, KEYCXX)
TYPE_TRAIT_1(__is_enum, IsEnum, KEYCXX)
TYPE_TRAIT_1(__is_final, IsFinal, KEYCXX)
// Tentative name - there's no implementation of std::is_literal_type yet.
TYPE_TRAIT_1(__is_literal, IsLiteral, KEYCXX)
// Name for GCC 4.6 compatibility - people have already written libraries using
// this name unfortunately.

View File

@ -65,6 +65,7 @@ namespace clang {
UTT_IsStandardLayout,
UTT_IsTrivial,
UTT_IsTriviallyCopyable,
UTT_IsTriviallyDestructible,
UTT_IsUnion,
UTT_IsUnsigned,
UTT_IsVoid,

View File

@ -63,6 +63,12 @@ def _SLASH_C : CLFlag<"C">,
def _SLASH_c : CLFlag<"c">, HelpText<"Compile only">, Alias<c>;
def _SLASH_d1reportAllClassLayout : CLFlag<"d1reportAllClassLayout">,
HelpText<"Dump record layout information">, Alias<fdump_record_layouts>;
def _SLASH_diagnostics_caret : CLFlag<"diagnostics:caret">,
HelpText<"Enable caret and column diagnostics (on by default)">;
def _SLASH_diagnostics_column : CLFlag<"diagnostics:column">,
HelpText<"Disable caret diagnostics but keep column info">;
def _SLASH_diagnostics_classic : CLFlag<"diagnostics:classic">,
HelpText<"Disable column and caret diagnostics">;
def _SLASH_D : CLJoinedOrSeparate<"D">, HelpText<"Define macro">,
MetaVarName<"<macro[=value]>">, Alias<D>;
def _SLASH_E : CLFlag<"E">, HelpText<"Preprocess to stdout">, Alias<E>;
@ -324,6 +330,7 @@ def _SLASH_Zc_forScope : CLIgnoredFlag<"Zc:forScope">;
def _SLASH_Zc_inline : CLIgnoredFlag<"Zc:inline">;
def _SLASH_Zc_rvalueCast : CLIgnoredFlag<"Zc:rvalueCast">;
def _SLASH_Zc_wchar_t : CLIgnoredFlag<"Zc:wchar_t">;
def _SLASH_Zc_ternary : CLIgnoredFlag<"Zc:ternary">;
def _SLASH_Zm : CLIgnoredJoined<"Zm">;
def _SLASH_Zo : CLIgnoredFlag<"Zo">;
def _SLASH_Zo_ : CLIgnoredFlag<"Zo-">;

View File

@ -2084,7 +2084,7 @@ def no_cpp_precomp : Flag<["-"], "no-cpp-precomp">, Group<clang_ignored_f_Group>
def no_integrated_cpp : Flag<["-", "--"], "no-integrated-cpp">, Flags<[DriverOption]>;
def no_pedantic : Flag<["-", "--"], "no-pedantic">, Group<pedantic_Group>;
def no__dead__strip__inits__and__terms : Flag<["-"], "no_dead_strip_inits_and_terms">;
def nobuiltininc : Flag<["-"], "nobuiltininc">, Flags<[CC1Option]>,
def nobuiltininc : Flag<["-"], "nobuiltininc">, Flags<[CC1Option, CoreOption]>,
HelpText<"Disable builtin #include directories">;
def nocudainc : Flag<["-"], "nocudainc">;
def nocudalib : Flag<["-"], "nocudalib">;
@ -2096,7 +2096,7 @@ def nopie : Flag<["-"], "nopie">;
def noprebind : Flag<["-"], "noprebind">;
def noseglinkedit : Flag<["-"], "noseglinkedit">;
def nostartfiles : Flag<["-"], "nostartfiles">;
def nostdinc : Flag<["-"], "nostdinc">;
def nostdinc : Flag<["-"], "nostdinc">, Flags<[CoreOption]>;
def nostdlibinc : Flag<["-"], "nostdlibinc">;
def nostdincxx : Flag<["-"], "nostdinc++">, Flags<[CC1Option]>,
HelpText<"Disable standard #include directories for the C++ standard library">;

View File

@ -543,10 +543,13 @@ public:
/// \param Offset [inout] An offset within ID to start parsing. On exit,
/// filled by the end of the parsed contents (either EOF or the
/// location of an end-of-module-map pragma).
///
/// \param OriginalModuleMapFile The original path to the module map file,
/// used to resolve paths within the module (this is required when
/// building the module from preprocessed source).
/// \returns true if an error occurred, false otherwise.
bool loadModuleMapFile(const FileEntry *File, bool IsSystem,
FileID ID = FileID(), unsigned *Offset = nullptr);
FileID ID = FileID(), unsigned *Offset = nullptr,
StringRef OriginalModuleMapFile = StringRef());
/// \brief Collect the set of all known, top-level modules.
///

View File

@ -110,7 +110,24 @@ void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
}
}
void ODRHash::AddTemplateName(TemplateName Name) {}
void ODRHash::AddTemplateName(TemplateName Name) {
auto Kind = Name.getKind();
ID.AddInteger(Kind);
switch (Kind) {
case TemplateName::Template:
AddDecl(Name.getAsTemplateDecl());
break;
// TODO: Support these cases.
case TemplateName::OverloadedTemplate:
case TemplateName::QualifiedTemplate:
case TemplateName::DependentTemplate:
case TemplateName::SubstTemplateTemplateParm:
case TemplateName::SubstTemplateTemplateParmPack:
break;
}
}
void ODRHash::AddTemplateArgument(TemplateArgument TA) {}
void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) {}
@ -492,6 +509,15 @@ public:
AddQualType(T->getNamedType());
VisitTypeWithKeyword(T);
}
void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
ID.AddInteger(T->getNumArgs());
for (const auto &TA : T->template_arguments()) {
Hash.AddTemplateArgument(TA);
}
Hash.AddTemplateName(T->getTemplateName());
VisitType(T);
}
};
void ODRHash::AddType(const Type *T) {

View File

@ -3123,6 +3123,7 @@ public:
case CC_Swift:
case CC_X86Pascal:
case CC_IntelOclBicc:
case CC_OpenCLKernel:
return CCCR_OK;
default:
return CCCR_Warning;
@ -4834,6 +4835,7 @@ public:
case CC_PreserveMost:
case CC_PreserveAll:
case CC_X86RegCall:
case CC_OpenCLKernel:
return CCCR_OK;
default:
return CCCR_Warning;
@ -4907,6 +4909,7 @@ public:
case CC_X86_64SysV:
case CC_Swift:
case CC_X86RegCall:
case CC_OpenCLKernel:
return CCCR_OK;
default:
return CCCR_Warning;
@ -5860,6 +5863,7 @@ public:
case CC_AAPCS:
case CC_AAPCS_VFP:
case CC_Swift:
case CC_OpenCLKernel:
return CCCR_OK;
default:
return CCCR_Warning;
@ -6019,6 +6023,7 @@ public:
case CC_X86VectorCall:
return CCCR_Ignore;
case CC_C:
case CC_OpenCLKernel:
return CCCR_OK;
default:
return CCCR_Warning;
@ -6329,6 +6334,7 @@ public:
case CC_Swift:
case CC_PreserveMost:
case CC_PreserveAll:
case CC_OpenCLKernel:
return CCCR_OK;
default:
return CCCR_Warning;
@ -7380,6 +7386,7 @@ public:
switch (CC) {
case CC_C:
case CC_Swift:
case CC_OpenCLKernel:
return CCCR_OK;
default:
return CCCR_Warning;
@ -7663,6 +7670,15 @@ public:
ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
return None;
}
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
switch (CC) {
default:
return CCCR_Warning;
case CC_C:
case CC_OpenCLKernel:
return CCCR_OK;
}
}
};
class MipsTargetInfo : public TargetInfo {

View File

@ -149,7 +149,6 @@ namespace swiftcall {
return info->supportsSwift();
}
};
} // end namespace CodeGen
} // end namespace clang

View File

@ -707,6 +707,12 @@ CodeGenTypes::arrangeCall(const CGFunctionInfo &signature,
signature.getRequiredArgs());
}
namespace clang {
namespace CodeGen {
void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI);
}
}
/// Arrange the argument and result information for an abstract value
/// of a given function type. This is the method which all of the
/// above functions ultimately defer to.
@ -743,10 +749,14 @@ CodeGenTypes::arrangeLLVMFunctionInfo(CanQualType resultType,
assert(inserted && "Recursively being processed?");
// Compute ABI information.
if (info.getCC() != CC_Swift) {
getABIInfo().computeInfo(*FI);
} else {
if (CC == llvm::CallingConv::SPIR_KERNEL) {
// Force target independent argument handling for the host visible
// kernel functions.
computeSPIRKernelABIInfo(CGM, *FI);
} else if (info.getCC() == CC_Swift) {
swiftcall::computeABIInfo(CGM, *FI);
} else {
getABIInfo().computeInfo(*FI);
}
// Loop over all of the computed argument and return value info. If any of

View File

@ -448,6 +448,13 @@ void CodeGenFunction::PopCleanupBlocks(
auto *Inst = dyn_cast_or_null<llvm::Instruction>(*ReloadedValue);
if (!Inst)
continue;
// Don't spill static allocas, they dominate all cleanups. These are created
// by binding a reference to a local variable or temporary.
auto *AI = dyn_cast<llvm::AllocaInst>(Inst);
if (AI && AI->isStaticAlloca())
continue;
Address Tmp =
CreateDefaultAlignTempAlloca(Inst->getType(), "tmp.exprcleanup");

View File

@ -3002,9 +3002,10 @@ static llvm::Value *emitArraySubscriptGEP(CodeGenFunction &CGF,
llvm::Value *ptr,
ArrayRef<llvm::Value*> indices,
bool inbounds,
SourceLocation loc,
const llvm::Twine &name = "arrayidx") {
if (inbounds) {
return CGF.Builder.CreateInBoundsGEP(ptr, indices, name);
return CGF.EmitCheckedInBoundsGEP(ptr, indices, loc, name);
} else {
return CGF.Builder.CreateGEP(ptr, indices, name);
}
@ -3035,8 +3036,9 @@ static QualType getFixedSizeElementType(const ASTContext &ctx,
}
static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr,
ArrayRef<llvm::Value*> indices,
ArrayRef<llvm::Value *> indices,
QualType eltType, bool inbounds,
SourceLocation loc,
const llvm::Twine &name = "arrayidx") {
// All the indices except that last must be zero.
#ifndef NDEBUG
@ -3057,7 +3059,7 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr,
getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize);
llvm::Value *eltPtr =
emitArraySubscriptGEP(CGF, addr.getPointer(), indices, inbounds, name);
emitArraySubscriptGEP(CGF, addr.getPointer(), indices, inbounds, loc, name);
return Address(eltPtr, eltAlign);
}
@ -3110,7 +3112,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
Address Addr = EmitExtVectorElementLValue(LV);
QualType EltType = LV.getType()->castAs<VectorType>()->getElementType();
Addr = emitArraySubscriptGEP(*this, Addr, Idx, EltType, /*inbounds*/ true);
Addr = emitArraySubscriptGEP(*this, Addr, Idx, EltType, /*inbounds*/ true,
E->getExprLoc());
return MakeAddrLValue(Addr, EltType, LV.getBaseInfo());
}
@ -3138,7 +3141,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
}
Addr = emitArraySubscriptGEP(*this, Addr, Idx, vla->getElementType(),
!getLangOpts().isSignedOverflowDefined());
!getLangOpts().isSignedOverflowDefined(),
E->getExprLoc());
} else if (const ObjCObjectType *OIT = E->getType()->getAs<ObjCObjectType>()){
// Indexing over an interface, as in "NSString *P; P[4];"
@ -3163,8 +3167,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
// Do the GEP.
CharUnits EltAlign =
getArrayElementAlign(Addr.getAlignment(), Idx, InterfaceSize);
llvm::Value *EltPtr =
emitArraySubscriptGEP(*this, Addr.getPointer(), ScaledIdx, false);
llvm::Value *EltPtr = emitArraySubscriptGEP(
*this, Addr.getPointer(), ScaledIdx, false, E->getExprLoc());
Addr = Address(EltPtr, EltAlign);
// Cast back.
@ -3189,14 +3193,16 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
Addr = emitArraySubscriptGEP(*this, ArrayLV.getAddress(),
{CGM.getSize(CharUnits::Zero()), Idx},
E->getType(),
!getLangOpts().isSignedOverflowDefined());
!getLangOpts().isSignedOverflowDefined(),
E->getExprLoc());
BaseInfo = ArrayLV.getBaseInfo();
} else {
// The base must be a pointer; emit it with an estimate of its alignment.
Addr = EmitPointerWithAlignment(E->getBase(), &BaseInfo);
auto *Idx = EmitIdxAfterBase(/*Promote*/true);
Addr = emitArraySubscriptGEP(*this, Addr, Idx, E->getType(),
!getLangOpts().isSignedOverflowDefined());
!getLangOpts().isSignedOverflowDefined(),
E->getExprLoc());
}
LValue LV = MakeAddrLValue(Addr, E->getType(), BaseInfo);
@ -3368,7 +3374,8 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
else
Idx = Builder.CreateNSWMul(Idx, NumElements);
EltPtr = emitArraySubscriptGEP(*this, Base, Idx, VLA->getElementType(),
!getLangOpts().isSignedOverflowDefined());
!getLangOpts().isSignedOverflowDefined(),
E->getExprLoc());
} else if (const Expr *Array = isSimpleArrayDecayOperand(E->getBase())) {
// If this is A[i] where A is an array, the frontend will have decayed the
// base to be a ArrayToPointerDecay implicit cast. While correct, it is
@ -3387,13 +3394,15 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
// Propagate the alignment from the array itself to the result.
EltPtr = emitArraySubscriptGEP(
*this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx},
ResultExprTy, !getLangOpts().isSignedOverflowDefined());
ResultExprTy, !getLangOpts().isSignedOverflowDefined(),
E->getExprLoc());
BaseInfo = ArrayLV.getBaseInfo();
} else {
Address Base = emitOMPArraySectionBase(*this, E->getBase(), BaseInfo,
BaseTy, ResultExprTy, IsLowerBound);
EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy,
!getLangOpts().isSignedOverflowDefined());
!getLangOpts().isSignedOverflowDefined(),
E->getExprLoc());
}
return MakeAddrLValue(EltPtr, ResultExprTy, BaseInfo);
@ -3530,6 +3539,25 @@ static Address emitAddrOfFieldStorage(CodeGenFunction &CGF, Address base,
return CGF.Builder.CreateStructGEP(base, idx, offset, field->getName());
}
static bool hasAnyVptr(const QualType Type, const ASTContext &Context) {
const auto *RD = Type.getTypePtr()->getAsCXXRecordDecl();
if (!RD)
return false;
if (RD->isDynamicClass())
return true;
for (const auto &Base : RD->bases())
if (hasAnyVptr(Base.getType(), Context))
return true;
for (const FieldDecl *Field : RD->fields())
if (hasAnyVptr(Field->getType(), Context))
return true;
return false;
}
LValue CodeGenFunction::EmitLValueForField(LValue base,
const FieldDecl *field) {
LValueBaseInfo BaseInfo = base.getBaseInfo();
@ -3572,6 +3600,14 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
assert(!type->isReferenceType() && "union has reference member");
// TODO: handle path-aware TBAA for union.
TBAAPath = false;
const auto FieldType = field->getType();
if (CGM.getCodeGenOpts().StrictVTablePointers &&
hasAnyVptr(FieldType, getContext()))
// Because unions can easily skip invariant.barriers, we need to add
// a barrier every time CXXRecord field with vptr is referenced.
addr = Address(Builder.CreateInvariantGroupBarrier(addr.getPointer()),
addr.getAlignment());
} else {
// For structs, we GEP to the field that the record layout suggests.
addr = emitAddrOfFieldStorage(*this, addr, field);

View File

@ -30,6 +30,7 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Module.h"
@ -44,6 +45,43 @@ using llvm::Value;
//===----------------------------------------------------------------------===//
namespace {
/// Determine whether the given binary operation may overflow.
/// Sets \p Result to the value of the operation for BO_Add, BO_Sub, BO_Mul,
/// and signed BO_{Div,Rem}. For these opcodes, and for unsigned BO_{Div,Rem},
/// the returned overflow check is precise. The returned value is 'true' for
/// all other opcodes, to be conservative.
bool mayHaveIntegerOverflow(llvm::ConstantInt *LHS, llvm::ConstantInt *RHS,
BinaryOperator::Opcode Opcode, bool Signed,
llvm::APInt &Result) {
// Assume overflow is possible, unless we can prove otherwise.
bool Overflow = true;
const auto &LHSAP = LHS->getValue();
const auto &RHSAP = RHS->getValue();
if (Opcode == BO_Add) {
if (Signed)
Result = LHSAP.sadd_ov(RHSAP, Overflow);
else
Result = LHSAP.uadd_ov(RHSAP, Overflow);
} else if (Opcode == BO_Sub) {
if (Signed)
Result = LHSAP.ssub_ov(RHSAP, Overflow);
else
Result = LHSAP.usub_ov(RHSAP, Overflow);
} else if (Opcode == BO_Mul) {
if (Signed)
Result = LHSAP.smul_ov(RHSAP, Overflow);
else
Result = LHSAP.umul_ov(RHSAP, Overflow);
} else if (Opcode == BO_Div || Opcode == BO_Rem) {
if (Signed && !RHS->isZero())
Result = LHSAP.sdiv_ov(RHSAP, Overflow);
else
return false;
}
return Overflow;
}
struct BinOpInfo {
Value *LHS;
Value *RHS;
@ -55,37 +93,14 @@ struct BinOpInfo {
/// Check if the binop can result in integer overflow.
bool mayHaveIntegerOverflow() const {
// Without constant input, we can't rule out overflow.
const auto *LHSCI = dyn_cast<llvm::ConstantInt>(LHS);
const auto *RHSCI = dyn_cast<llvm::ConstantInt>(RHS);
auto *LHSCI = dyn_cast<llvm::ConstantInt>(LHS);
auto *RHSCI = dyn_cast<llvm::ConstantInt>(RHS);
if (!LHSCI || !RHSCI)
return true;
// Assume overflow is possible, unless we can prove otherwise.
bool Overflow = true;
const auto &LHSAP = LHSCI->getValue();
const auto &RHSAP = RHSCI->getValue();
if (Opcode == BO_Add) {
if (Ty->hasSignedIntegerRepresentation())
(void)LHSAP.sadd_ov(RHSAP, Overflow);
else
(void)LHSAP.uadd_ov(RHSAP, Overflow);
} else if (Opcode == BO_Sub) {
if (Ty->hasSignedIntegerRepresentation())
(void)LHSAP.ssub_ov(RHSAP, Overflow);
else
(void)LHSAP.usub_ov(RHSAP, Overflow);
} else if (Opcode == BO_Mul) {
if (Ty->hasSignedIntegerRepresentation())
(void)LHSAP.smul_ov(RHSAP, Overflow);
else
(void)LHSAP.umul_ov(RHSAP, Overflow);
} else if (Opcode == BO_Div || Opcode == BO_Rem) {
if (Ty->hasSignedIntegerRepresentation() && !RHSCI->isZero())
(void)LHSAP.sdiv_ov(RHSAP, Overflow);
else
return false;
}
return Overflow;
llvm::APInt Result;
return ::mayHaveIntegerOverflow(
LHSCI, RHSCI, Opcode, Ty->hasSignedIntegerRepresentation(), Result);
}
/// Check if the binop computes a division or a remainder.
@ -1925,7 +1940,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
if (CGF.getLangOpts().isSignedOverflowDefined())
value = Builder.CreateGEP(value, numElts, "vla.inc");
else
value = Builder.CreateInBoundsGEP(value, numElts, "vla.inc");
value = CGF.EmitCheckedInBoundsGEP(value, numElts, E->getExprLoc(),
"vla.inc");
// Arithmetic on function pointers (!) is just +-1.
} else if (type->isFunctionType()) {
@ -1935,7 +1951,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
if (CGF.getLangOpts().isSignedOverflowDefined())
value = Builder.CreateGEP(value, amt, "incdec.funcptr");
else
value = Builder.CreateInBoundsGEP(value, amt, "incdec.funcptr");
value = CGF.EmitCheckedInBoundsGEP(value, amt, E->getExprLoc(),
"incdec.funcptr");
value = Builder.CreateBitCast(value, input->getType());
// For everything else, we can just do a simple increment.
@ -1944,7 +1961,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
if (CGF.getLangOpts().isSignedOverflowDefined())
value = Builder.CreateGEP(value, amt, "incdec.ptr");
else
value = Builder.CreateInBoundsGEP(value, amt, "incdec.ptr");
value = CGF.EmitCheckedInBoundsGEP(value, amt, E->getExprLoc(),
"incdec.ptr");
}
// Vector increment/decrement.
@ -2025,7 +2043,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
if (CGF.getLangOpts().isSignedOverflowDefined())
value = Builder.CreateGEP(value, sizeValue, "incdec.objptr");
else
value = Builder.CreateInBoundsGEP(value, sizeValue, "incdec.objptr");
value = CGF.EmitCheckedInBoundsGEP(value, sizeValue, E->getExprLoc(),
"incdec.objptr");
value = Builder.CreateBitCast(value, input->getType());
}
@ -2692,7 +2711,8 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
pointer = CGF.Builder.CreateGEP(pointer, index, "add.ptr");
} else {
index = CGF.Builder.CreateNSWMul(index, numElements, "vla.index");
pointer = CGF.Builder.CreateInBoundsGEP(pointer, index, "add.ptr");
pointer = CGF.EmitCheckedInBoundsGEP(pointer, index, op.E->getExprLoc(),
"add.ptr");
}
return pointer;
}
@ -2709,7 +2729,8 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
if (CGF.getLangOpts().isSignedOverflowDefined())
return CGF.Builder.CreateGEP(pointer, index, "add.ptr");
return CGF.Builder.CreateInBoundsGEP(pointer, index, "add.ptr");
return CGF.EmitCheckedInBoundsGEP(pointer, index, op.E->getExprLoc(),
"add.ptr");
}
// Construct an fmuladd intrinsic to represent a fused mul-add of MulOp and
@ -3824,3 +3845,124 @@ LValue CodeGenFunction::EmitCompoundAssignmentLValue(
llvm_unreachable("Unhandled compound assignment operator");
}
Value *CodeGenFunction::EmitCheckedInBoundsGEP(Value *Ptr,
ArrayRef<Value *> IdxList,
SourceLocation Loc,
const Twine &Name) {
Value *GEPVal = Builder.CreateInBoundsGEP(Ptr, IdxList, Name);
// If the pointer overflow sanitizer isn't enabled, do nothing.
if (!SanOpts.has(SanitizerKind::PointerOverflow))
return GEPVal;
// If the GEP has already been reduced to a constant, leave it be.
if (isa<llvm::Constant>(GEPVal))
return GEPVal;
// Only check for overflows in the default address space.
if (GEPVal->getType()->getPointerAddressSpace())
return GEPVal;
auto *GEP = cast<llvm::GEPOperator>(GEPVal);
assert(GEP->isInBounds() && "Expected inbounds GEP");
SanitizerScope SanScope(this);
auto &VMContext = getLLVMContext();
const auto &DL = CGM.getDataLayout();
auto *IntPtrTy = DL.getIntPtrType(GEP->getPointerOperandType());
// Grab references to the signed add/mul overflow intrinsics for intptr_t.
auto *Zero = llvm::ConstantInt::getNullValue(IntPtrTy);
auto *SAddIntrinsic =
CGM.getIntrinsic(llvm::Intrinsic::sadd_with_overflow, IntPtrTy);
auto *SMulIntrinsic =
CGM.getIntrinsic(llvm::Intrinsic::smul_with_overflow, IntPtrTy);
// The total (signed) byte offset for the GEP.
llvm::Value *TotalOffset = nullptr;
// The offset overflow flag - true if the total offset overflows.
llvm::Value *OffsetOverflows = Builder.getFalse();
/// Return the result of the given binary operation.
auto eval = [&](BinaryOperator::Opcode Opcode, llvm::Value *LHS,
llvm::Value *RHS) -> llvm::Value * {
assert(Opcode == BO_Add || Opcode == BO_Mul && "Can't eval binop");
// If the operands are constants, return a constant result.
if (auto *LHSCI = dyn_cast<llvm::ConstantInt>(LHS)) {
if (auto *RHSCI = dyn_cast<llvm::ConstantInt>(RHS)) {
llvm::APInt N;
bool HasOverflow = mayHaveIntegerOverflow(LHSCI, RHSCI, Opcode,
/*Signed=*/true, N);
if (HasOverflow)
OffsetOverflows = Builder.getTrue();
return llvm::ConstantInt::get(VMContext, N);
}
}
// Otherwise, compute the result with checked arithmetic.
auto *ResultAndOverflow = Builder.CreateCall(
(Opcode == BO_Add) ? SAddIntrinsic : SMulIntrinsic, {LHS, RHS});
OffsetOverflows = Builder.CreateOr(
OffsetOverflows, Builder.CreateExtractValue(ResultAndOverflow, 1));
return Builder.CreateExtractValue(ResultAndOverflow, 0);
};
// Determine the total byte offset by looking at each GEP operand.
for (auto GTI = llvm::gep_type_begin(GEP), GTE = llvm::gep_type_end(GEP);
GTI != GTE; ++GTI) {
llvm::Value *LocalOffset;
auto *Index = GTI.getOperand();
// Compute the local offset contributed by this indexing step:
if (auto *STy = GTI.getStructTypeOrNull()) {
// For struct indexing, the local offset is the byte position of the
// specified field.
unsigned FieldNo = cast<llvm::ConstantInt>(Index)->getZExtValue();
LocalOffset = llvm::ConstantInt::get(
IntPtrTy, DL.getStructLayout(STy)->getElementOffset(FieldNo));
} else {
// Otherwise this is array-like indexing. The local offset is the index
// multiplied by the element size.
auto *ElementSize = llvm::ConstantInt::get(
IntPtrTy, DL.getTypeAllocSize(GTI.getIndexedType()));
auto *IndexS = Builder.CreateIntCast(Index, IntPtrTy, /*isSigned=*/true);
LocalOffset = eval(BO_Mul, ElementSize, IndexS);
}
// If this is the first offset, set it as the total offset. Otherwise, add
// the local offset into the running total.
if (!TotalOffset || TotalOffset == Zero)
TotalOffset = LocalOffset;
else
TotalOffset = eval(BO_Add, TotalOffset, LocalOffset);
}
// Common case: if the total offset is zero, don't emit a check.
if (TotalOffset == Zero)
return GEPVal;
// Now that we've computed the total offset, add it to the base pointer (with
// wrapping semantics).
auto *IntPtr = Builder.CreatePtrToInt(GEP->getPointerOperand(), IntPtrTy);
auto *ComputedGEP = Builder.CreateAdd(IntPtr, TotalOffset);
// The GEP is valid if:
// 1) The total offset doesn't overflow, and
// 2) The sign of the difference between the computed address and the base
// pointer matches the sign of the total offset.
llvm::Value *PosOrZeroValid = Builder.CreateICmpUGE(ComputedGEP, IntPtr);
llvm::Value *NegValid = Builder.CreateICmpULT(ComputedGEP, IntPtr);
auto *PosOrZeroOffset = Builder.CreateICmpSGE(TotalOffset, Zero);
llvm::Value *ValidGEP = Builder.CreateAnd(
Builder.CreateNot(OffsetOverflows),
Builder.CreateSelect(PosOrZeroOffset, PosOrZeroValid, NegValid));
llvm::Constant *StaticArgs[] = {EmitCheckSourceLocation(Loc)};
// Pass the computed GEP to the runtime to avoid emitting poisoned arguments.
llvm::Value *DynamicArgs[] = {IntPtr, ComputedGEP};
EmitCheck(std::make_pair(ValidGEP, SanitizerKind::PointerOverflow),
SanitizerHandler::PointerOverflow, StaticArgs, DynamicArgs);
return GEPVal;
}

View File

@ -90,7 +90,11 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
unsigned CVRQualifiers,
llvm::Value *Offset) {
// Compute (type*) ( (char *) BaseValue + Offset)
QualType IvarTy = Ivar->getType().withCVRQualifiers(CVRQualifiers);
QualType InterfaceTy{OID->getTypeForDecl(), 0};
QualType ObjectPtrTy =
CGF.CGM.getContext().getObjCObjectPointerType(InterfaceTy);
QualType IvarTy =
Ivar->getUsageType(ObjectPtrTy).withCVRQualifiers(CVRQualifiers);
llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy);
llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, CGF.Int8PtrTy);
V = CGF.Builder.CreateInBoundsGEP(V, Offset, "add.ptr");

View File

@ -901,6 +901,8 @@ void CodeGenModule::EmitDeferredVTables() {
for (const CXXRecordDecl *RD : DeferredVTables)
if (shouldEmitVTableAtEndOfTranslationUnit(*this, RD))
VTables.GenerateClassData(RD);
else if (shouldOpportunisticallyEmitVTables())
OpportunisticVTables.push_back(RD);
assert(savedSize == DeferredVTables.size() &&
"deferred extra vtables during vtable emission?");

View File

@ -120,6 +120,7 @@ enum TypeEvaluationKind {
SANITIZER_CHECK(NonnullArg, nonnull_arg, 0) \
SANITIZER_CHECK(NonnullReturn, nonnull_return, 0) \
SANITIZER_CHECK(OutOfBounds, out_of_bounds, 0) \
SANITIZER_CHECK(PointerOverflow, pointer_overflow, 0) \
SANITIZER_CHECK(ShiftOutOfBounds, shift_out_of_bounds, 0) \
SANITIZER_CHECK(SubOverflow, sub_overflow, 0) \
SANITIZER_CHECK(TypeMismatch, type_mismatch, 1) \
@ -3551,6 +3552,13 @@ public:
/// nonnull, if \p LHS is marked _Nonnull.
void EmitNullabilityCheck(LValue LHS, llvm::Value *RHS, SourceLocation Loc);
/// Same as IRBuilder::CreateInBoundsGEP, but additionally emits a check to
/// detect undefined behavior when the pointer overflow sanitizer is enabled.
llvm::Value *EmitCheckedInBoundsGEP(llvm::Value *Ptr,
ArrayRef<llvm::Value *> IdxList,
SourceLocation Loc,
const Twine &Name = "");
/// \brief Emit a description of a type in a format suitable for passing to
/// a runtime sanitizer handler.
llvm::Constant *EmitCheckTypeDescriptor(QualType T);

View File

@ -382,6 +382,7 @@ void InstrProfStats::reportDiagnostics(DiagnosticsEngine &Diags,
void CodeGenModule::Release() {
EmitDeferred();
EmitVTablesOpportunistically();
applyGlobalValReplacements();
applyReplacements();
checkAliases();
@ -472,10 +473,10 @@ void CodeGenModule::Release() {
// Width of wchar_t in bytes
uint64_t WCharWidth =
Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity();
assert(LangOpts.ShortWChar ||
llvm::TargetLibraryInfoImpl::getTargetWCharSize(Target.getTriple()) ==
Target.getWCharWidth() / 8 &&
"LLVM wchar_t size out of sync");
assert((LangOpts.ShortWChar ||
llvm::TargetLibraryInfoImpl::getTargetWCharSize(Target.getTriple()) ==
Target.getWCharWidth() / 8) &&
"LLVM wchar_t size out of sync");
// We need to record the widths of enums and wchar_t, so that we can generate
// the correct build attributes in the ARM backend. wchar_size is also used by
@ -1386,6 +1387,24 @@ void CodeGenModule::EmitDeferred() {
}
}
void CodeGenModule::EmitVTablesOpportunistically() {
// Try to emit external vtables as available_externally if they have emitted
// all inlined virtual functions. It runs after EmitDeferred() and therefore
// is not allowed to create new references to things that need to be emitted
// lazily. Note that it also uses fact that we eagerly emitting RTTI.
assert((OpportunisticVTables.empty() || shouldOpportunisticallyEmitVTables())
&& "Only emit opportunistic vtables with optimizations");
for (const CXXRecordDecl *RD : OpportunisticVTables) {
assert(getVTables().isVTableExternal(RD) &&
"This queue should only contain external vtables");
if (getCXXABI().canSpeculativelyEmitVTable(RD))
VTables.GenerateClassData(RD);
}
OpportunisticVTables.clear();
}
void CodeGenModule::EmitGlobalAnnotations() {
if (Annotations.empty())
return;
@ -1906,6 +1925,10 @@ bool CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
return !isTriviallyRecursive(F);
}
bool CodeGenModule::shouldOpportunisticallyEmitVTables() {
return CodeGenOpts.OptimizationLevel > 0;
}
void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
const auto *D = cast<ValueDecl>(GD.getDecl());

View File

@ -341,6 +341,9 @@ private:
/// A queue of (optional) vtables to consider emitting.
std::vector<const CXXRecordDecl*> DeferredVTables;
/// A queue of (optional) vtables that may be emitted opportunistically.
std::vector<const CXXRecordDecl *> OpportunisticVTables;
/// List of global values which are required to be present in the object file;
/// bitcast to i8*. This is used for forcing visibility of symbols which may
/// otherwise be optimized out.
@ -450,7 +453,7 @@ private:
bool isTriviallyRecursive(const FunctionDecl *F);
bool shouldEmitFunction(GlobalDecl GD);
bool shouldOpportunisticallyEmitVTables();
/// Map used to be sure we don't emit the same CompoundLiteral twice.
llvm::DenseMap<const CompoundLiteralExpr *, llvm::GlobalVariable *>
EmittedCompoundLiterals;
@ -1278,6 +1281,12 @@ private:
/// Emit any needed decls for which code generation was deferred.
void EmitDeferred();
/// Try to emit external vtables as available_externally if they have emitted
/// all inlined virtual functions. It runs after EmitDeferred() and therefore
/// is not allowed to create new references to things that need to be emitted
/// lazily.
void EmitVTablesOpportunistically();
/// Call replaceAllUsesWith on all pairs in Replacements.
void applyReplacements();

View File

@ -366,20 +366,30 @@ public:
void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override;
private:
bool hasAnyVirtualInlineFunction(const CXXRecordDecl *RD) const {
const auto &VtableLayout =
CGM.getItaniumVTableContext().getVTableLayout(RD);
bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const {
const auto &VtableLayout =
CGM.getItaniumVTableContext().getVTableLayout(RD);
for (const auto &VtableComponent : VtableLayout.vtable_components()) {
// Skip empty slot.
if (!VtableComponent.isUsedFunctionPointerKind())
continue;
for (const auto &VtableComponent : VtableLayout.vtable_components()) {
// Skip empty slot.
if (!VtableComponent.isUsedFunctionPointerKind())
continue;
const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
if (Method->getCanonicalDecl()->isInlined())
return true;
}
return false;
const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
if (!Method->getCanonicalDecl()->isInlined())
continue;
StringRef Name = CGM.getMangledName(VtableComponent.getGlobalDecl());
auto *Entry = CGM.GetGlobalValue(Name);
// This checks if virtual inline function has already been emitted.
// Note that it is possible that this inline function would be emitted
// after trying to emit vtable speculatively. Because of this we do
// an extra pass after emitting all deferred vtables to find and emit
// these vtables opportunistically.
if (!Entry || Entry->isDeclaration())
return true;
}
return false;
}
bool isVTableHidden(const CXXRecordDecl *RD) const {
@ -1687,11 +1697,11 @@ bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const {
if (CGM.getLangOpts().AppleKext)
return false;
// If we don't have any inline virtual functions, and if vtable is not hidden,
// then we are safe to emit available_externally copy of vtable.
// If we don't have any not emitted inline virtual function, and if vtable is
// not hidden, then we are safe to emit available_externally copy of vtable.
// FIXME we can still emit a copy of the vtable if we
// can emit definition of the inline functions.
return !hasAnyVirtualInlineFunction(RD) && !isVTableHidden(RD);
return !hasAnyUnusedVirtualInlineFunction(RD) && !isVTableHidden(RD);
}
static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF,
Address InitialPtr,
@ -2576,6 +2586,9 @@ ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
if (!GV) {
// Create a new global variable.
// Note for the future: If we would ever like to do deferred emission of
// RTTI, check if emitting vtables opportunistically need any adjustment.
GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy,
/*Constant=*/true,
llvm::GlobalValue::ExternalLinkage, nullptr,

View File

@ -3756,6 +3756,9 @@ llvm::Constant *MicrosoftCXXABI::getAddrOfRTTIDescriptor(QualType Type) {
if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName))
return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
// Note for the future: If we would ever like to do deferred emission of
// RTTI, check if emitting vtables opportunistically need any adjustment.
// Compute the fields for the TypeDescriptor.
SmallString<256> TypeInfoString;
{

View File

@ -398,7 +398,17 @@ TargetCodeGenInfo::getDependentLibraryOption(llvm::StringRef Lib,
}
unsigned TargetCodeGenInfo::getOpenCLKernelCallingConv() const {
return llvm::CallingConv::C;
// OpenCL kernels are called via an explicit runtime API with arguments
// set with clSetKernelArg(), not as normal sub-functions.
// Return SPIR_KERNEL by default as the kernel calling convention to
// ensure the fingerprint is fixed such way that each OpenCL argument
// gets one matching argument in the produced kernel function argument
// list to enable feasible implementation of clSetKernelArg() with
// aggregates etc. In case we would use the default C calling conv here,
// clSetKernelArg() might break depending on the target-specific
// conventions; different targets might split structs passed as values
// to multiple function arguments etc.
return llvm::CallingConv::SPIR_KERNEL;
}
llvm::Constant *TargetCodeGenInfo::getNullPointer(const CodeGen::CodeGenModule &CGM,
@ -8068,8 +8078,18 @@ public:
CodeGen::CodeGenModule &M) const override;
unsigned getOpenCLKernelCallingConv() const override;
};
} // End anonymous namespace.
namespace clang {
namespace CodeGen {
void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI) {
DefaultABIInfo SPIRABI(CGM.getTypes());
SPIRABI.computeInfo(FI);
}
}
}
/// Emit SPIR specific metadata: OpenCL and SPIR version.
void SPIRTargetCodeGenInfo::emitTargetMD(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const {

View File

@ -3985,9 +3985,30 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
<< value;
}
bool CaretDefault = true;
bool ColumnDefault = true;
if (Arg *DiagArg = Args.getLastArg(options::OPT__SLASH_diagnostics_classic,
options::OPT__SLASH_diagnostics_column,
options::OPT__SLASH_diagnostics_caret)) {
switch (DiagArg->getOption().getID()) {
case options::OPT__SLASH_diagnostics_caret:
CaretDefault = true;
ColumnDefault = true;
break;
case options::OPT__SLASH_diagnostics_column:
CaretDefault = false;
ColumnDefault = true;
break;
case options::OPT__SLASH_diagnostics_classic:
CaretDefault = false;
ColumnDefault = false;
break;
}
}
// -fcaret-diagnostics is default.
if (!Args.hasFlag(options::OPT_fcaret_diagnostics,
options::OPT_fno_caret_diagnostics, true))
options::OPT_fno_caret_diagnostics, CaretDefault))
CmdArgs.push_back("-fno-caret-diagnostics");
// -fdiagnostics-fixit-info is default, only pass non-default.
@ -4059,7 +4080,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fdiagnostics-absolute-paths");
if (!Args.hasFlag(options::OPT_fshow_column, options::OPT_fno_show_column,
true))
ColumnDefault))
CmdArgs.push_back("-fno-show-column");
if (!Args.hasFlag(options::OPT_fspell_checking,
@ -4781,14 +4802,36 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
CmdArgs.push_back("-fms-memptr-rep=virtual");
}
if (Args.getLastArg(options::OPT__SLASH_Gd))
CmdArgs.push_back("-fdefault-calling-conv=cdecl");
else if (Args.getLastArg(options::OPT__SLASH_Gr))
CmdArgs.push_back("-fdefault-calling-conv=fastcall");
else if (Args.getLastArg(options::OPT__SLASH_Gz))
CmdArgs.push_back("-fdefault-calling-conv=stdcall");
else if (Args.getLastArg(options::OPT__SLASH_Gv))
CmdArgs.push_back("-fdefault-calling-conv=vectorcall");
// Parse the default calling convention options.
if (Arg *CCArg =
Args.getLastArg(options::OPT__SLASH_Gd, options::OPT__SLASH_Gr,
options::OPT__SLASH_Gz, options::OPT__SLASH_Gv)) {
unsigned DCCOptId = CCArg->getOption().getID();
const char *DCCFlag = nullptr;
bool ArchSupported = true;
llvm::Triple::ArchType Arch = getToolChain().getArch();
switch (DCCOptId) {
case options::OPT__SLASH_Gd:
DCCFlag = "-fdefault-calling-conv=cdecl";
break;
case options::OPT__SLASH_Gr:
ArchSupported = Arch == llvm::Triple::x86;
DCCFlag = "-fdefault-calling-conv=fastcall";
break;
case options::OPT__SLASH_Gz:
ArchSupported = Arch == llvm::Triple::x86;
DCCFlag = "-fdefault-calling-conv=stdcall";
break;
case options::OPT__SLASH_Gv:
ArchSupported = Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64;
DCCFlag = "-fdefault-calling-conv=vectorcall";
break;
}
// MSVC doesn't warn if /Gr or /Gz is used on x64, so we don't either.
if (ArchSupported && DCCFlag)
CmdArgs.push_back(DCCFlag);
}
if (Arg *A = Args.getLastArg(options::OPT_vtordisp_mode_EQ))
A->render(Args, CmdArgs);

View File

@ -278,20 +278,20 @@ static void AddOpenMPLinkerScript(const ToolChain &TC, Compilation &C,
LksStream << "SECTIONS\n";
LksStream << "{\n";
LksStream << " .omp_offloading :\n";
LksStream << " ALIGN(0x10)\n";
LksStream << " {\n";
for (auto &BI : InputBinaryInfo) {
LksStream << " . = ALIGN(0x10);\n";
// Put each target binary into a separate section.
for (const auto &BI : InputBinaryInfo) {
LksStream << " .omp_offloading." << BI.first << " :\n";
LksStream << " ALIGN(0x10)\n";
LksStream << " {\n";
LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_start." << BI.first
<< " = .);\n";
LksStream << " " << BI.second << "\n";
LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_end." << BI.first
<< " = .);\n";
LksStream << " }\n";
}
LksStream << " }\n";
// Add commands to define host entries begin and end. We use 1-byte subalign
// so that the linker does not add any padding and the elements in this
// section form an array.

View File

@ -360,16 +360,21 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
switch (Tok->Tok.getKind()) {
case tok::l_brace:
if (Style.Language == FormatStyle::LK_JavaScript && PrevTok &&
PrevTok->is(tok::colon))
// A colon indicates this code is in a type, or a braced list following
// a label in an object literal ({a: {b: 1}}).
// The code below could be confused by semicolons between the individual
// members in a type member list, which would normally trigger BK_Block.
// In both cases, this must be parsed as an inline braced init.
Tok->BlockKind = BK_BracedInit;
else
if (Style.Language == FormatStyle::LK_JavaScript && PrevTok) {
if (PrevTok->is(tok::colon))
// A colon indicates this code is in a type, or a braced list
// following a label in an object literal ({a: {b: 1}}). The code
// below could be confused by semicolons between the individual
// members in a type member list, which would normally trigger
// BK_Block. In both cases, this must be parsed as an inline braced
// init.
Tok->BlockKind = BK_BracedInit;
else if (PrevTok->is(tok::r_paren))
// `) { }` can only occur in function or method declarations in JS.
Tok->BlockKind = BK_Block;
} else {
Tok->BlockKind = BK_Unknown;
}
LBraceStack.push_back(Tok);
break;
case tok::r_brace:
@ -391,6 +396,8 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
// BlockKind later if we parse a braced list (where all blocks
// inside are by default braced lists), or when we explicitly detect
// blocks (for example while parsing lambdas).
// FIXME: Some of these do not apply to JS, e.g. "} {" can never be a
// braced list in JS.
ProbablyBracedList =
(Style.Language == FormatStyle::LK_JavaScript &&
NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,

View File

@ -2214,8 +2214,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
llvm::Triple T(TargetOpts.Triple);
llvm::Triple::ArchType Arch = T.getArch();
bool emitError = (DefaultCC == LangOptions::DCC_FastCall ||
DefaultCC == LangOptions::DCC_StdCall) &&
Arch != llvm::Triple::x86;
DefaultCC == LangOptions::DCC_StdCall) &&
Arch != llvm::Triple::x86;
emitError |= DefaultCC == LangOptions::DCC_VectorCall &&
!(Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64);
if (emitError)

View File

@ -373,10 +373,11 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr,
return std::error_code();
}
static bool
loadModuleMapForModuleBuild(CompilerInstance &CI, StringRef Filename,
bool IsSystem, bool IsPreprocessed,
unsigned &Offset) {
static bool loadModuleMapForModuleBuild(CompilerInstance &CI,
StringRef Filename, bool IsSystem,
bool IsPreprocessed,
std::string &PresumedModuleMapFile,
unsigned &Offset) {
auto &SrcMgr = CI.getSourceManager();
HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
@ -388,16 +389,15 @@ loadModuleMapForModuleBuild(CompilerInstance &CI, StringRef Filename,
// line directives are not part of the module map syntax in general.
Offset = 0;
if (IsPreprocessed) {
std::string PresumedModuleMapFile;
SourceLocation EndOfLineMarker =
ReadOriginalFileName(CI, PresumedModuleMapFile, /*AddLineNote*/true);
if (EndOfLineMarker.isValid())
Offset = CI.getSourceManager().getDecomposedLoc(EndOfLineMarker).second;
// FIXME: Use PresumedModuleMapFile as the MODULE_MAP_FILE in the PCM.
}
// Load the module map file.
if (HS.loadModuleMapFile(ModuleMap, IsSystem, ModuleMapID, &Offset))
if (HS.loadModuleMapFile(ModuleMap, IsSystem, ModuleMapID, &Offset,
PresumedModuleMapFile))
return true;
if (SrcMgr.getBuffer(ModuleMapID)->getBufferSize() == Offset)
@ -664,15 +664,19 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
if (Input.getKind().getFormat() == InputKind::ModuleMap) {
CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleMap);
std::string PresumedModuleMapFile;
unsigned OffsetToContents;
if (loadModuleMapForModuleBuild(CI, Input.getFile(), Input.isSystem(),
Input.isPreprocessed(), OffsetToContents))
Input.isPreprocessed(),
PresumedModuleMapFile, OffsetToContents))
goto failure;
auto *CurrentModule = prepareToBuildModule(CI, Input.getFile());
if (!CurrentModule)
goto failure;
CurrentModule->PresumedModuleMapFile = PresumedModuleMapFile;
if (OffsetToContents)
// If the module contents are in the same file, skip to them.
CI.getPreprocessor().setSkipMainFilePreamble(OffsetToContents, true);

View File

@ -1326,14 +1326,27 @@ static const FileEntry *getPrivateModuleMap(const FileEntry *File,
}
bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem,
FileID ID, unsigned *Offset) {
FileID ID, unsigned *Offset,
StringRef OriginalModuleMapFile) {
// Find the directory for the module. For frameworks, that may require going
// up from the 'Modules' directory.
const DirectoryEntry *Dir = nullptr;
if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd)
Dir = FileMgr.getDirectory(".");
else {
Dir = File->getDir();
if (!OriginalModuleMapFile.empty()) {
// We're building a preprocessed module map. Find or invent the directory
// that it originally occupied.
Dir = FileMgr.getDirectory(
llvm::sys::path::parent_path(OriginalModuleMapFile));
if (!Dir) {
auto *FakeFile = FileMgr.getVirtualFile(OriginalModuleMapFile, 0, 0);
Dir = FakeFile->getDir();
}
} else {
Dir = File->getDir();
}
StringRef DirName(Dir->getName());
if (llvm::sys::path::filename(DirName) == "Modules") {
DirName = llvm::sys::path::parent_path(DirName);

View File

@ -391,8 +391,11 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise,
// [expr.await]p3 [...]
// - await-suspend is the expression e.await_suspend(h), which shall be
// a prvalue of type void or bool.
QualType RetType = AwaitSuspend->getType();
if (RetType != S.Context.BoolTy && RetType != S.Context.VoidTy) {
QualType RetType = AwaitSuspend->getCallReturnType(S.Context);
// non-class prvalues always have cv-unqualified types
QualType AdjRetType = RetType.getUnqualifiedType();
if (RetType->isReferenceType() ||
(AdjRetType != S.Context.BoolTy && AdjRetType != S.Context.VoidTy)) {
S.Diag(AwaitSuspend->getCalleeDecl()->getLocation(),
diag::err_await_suspend_invalid_return_type)
<< RetType;
@ -437,6 +440,7 @@ VarDecl *Sema::buildCoroutinePromise(SourceLocation Loc) {
if (VD->isInvalidDecl())
return nullptr;
ActOnUninitializedDecl(VD);
FD->addDecl(VD);
assert(!VD->isInvalidDecl());
return VD;
}

View File

@ -11116,6 +11116,17 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
<< Init->getSourceRange();
Diag(attr->getLocation(), diag::note_declared_required_constant_init_here)
<< attr->getRange();
if (getLangOpts().CPlusPlus11) {
APValue Value;
SmallVector<PartialDiagnosticAt, 8> Notes;
Init->EvaluateAsInitializer(Value, getASTContext(), var, Notes);
for (auto &it : Notes)
Diag(it.first, it.second);
} else {
Diag(CacheCulprit->getExprLoc(),
diag::note_invalid_subexpr_in_const_expr)
<< CacheCulprit->getSourceRange();
}
}
}
else if (!var->isConstexpr() && IsGlobal &&

View File

@ -1851,10 +1851,6 @@ Decl *Sema::ActOnStartCategoryImplementation(
// FIXME: PushOnScopeChains?
CurContext->addDecl(CDecl);
// If the interface is deprecated/unavailable, warn/error about it.
if (IDecl)
DiagnoseUseOfDecl(IDecl, ClassLoc);
// If the interface has the objc_runtime_visible attribute, we
// cannot implement a category for it.
if (IDecl && IDecl->hasAttr<ObjCRuntimeVisibleAttr>()) {

View File

@ -4080,24 +4080,23 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
return true;
// C++0x [meta.unary.prop] Table 49 requires the following traits to be
// applied to a complete type.
// C++1z [meta.unary.prop]:
// remove_all_extents_t<T> shall be a complete type or cv void.
case UTT_IsAggregate:
case UTT_IsTrivial:
case UTT_IsTriviallyCopyable:
case UTT_IsStandardLayout:
case UTT_IsPOD:
case UTT_IsLiteral:
ArgTy = QualType(ArgTy->getBaseElementTypeUnsafe(), 0);
LLVM_FALLTHROUGH;
// C++1z [meta.unary.prop]:
// T shall be a complete type, cv void, or an array of unknown bound.
case UTT_IsDestructible:
case UTT_IsNothrowDestructible:
// Fall-through
// These trait expressions are designed to help implement predicates in
// [meta.unary.prop] despite not being named the same. They are specified
// by both GCC and the Embarcadero C++ compiler, and require the complete
// type due to the overarching C++0x type predicates being implemented
// requiring the complete type.
case UTT_IsTriviallyDestructible:
// Per the GCC type traits documentation, the same constraints apply to these.
case UTT_HasNothrowAssign:
case UTT_HasNothrowMoveAssign:
case UTT_HasNothrowConstructor:
@ -4109,17 +4108,11 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
case UTT_HasTrivialCopy:
case UTT_HasTrivialDestructor:
case UTT_HasVirtualDestructor:
// Arrays of unknown bound are expressly allowed.
QualType ElTy = ArgTy;
if (ArgTy->isIncompleteArrayType())
ElTy = S.Context.getAsArrayType(ArgTy)->getElementType();
// The void type is expressly allowed.
if (ElTy->isVoidType())
if (ArgTy->isIncompleteArrayType() || ArgTy->isVoidType())
return true;
return !S.RequireCompleteType(
Loc, ElTy, diag::err_incomplete_type_used_in_type_trait_expr);
Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
}
}
@ -4356,6 +4349,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
!RD->hasNonTrivialCopyAssignment();
return false;
case UTT_IsDestructible:
case UTT_IsTriviallyDestructible:
case UTT_IsNothrowDestructible:
// C++14 [meta.unary.prop]:
// For reference types, is_destructible<T>::value is true.
@ -4373,6 +4367,11 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
if (T->isIncompleteType() || T->isFunctionType())
return false;
// A type that requires destruction (via a non-trivial destructor or ARC
// lifetime semantics) is not trivially-destructible.
if (UTT == UTT_IsTriviallyDestructible && T.isDestructedType())
return false;
// C++14 [meta.unary.prop]:
// For object types and given U equal to remove_all_extents_t<T>, if the
// expression std::declval<U&>().~U() is well-formed when treated as an

View File

@ -330,13 +330,13 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx,
} else if (FromType->isIntegralType(Ctx) && ToType->isRealFloatingType()) {
llvm::APSInt IntConstantValue;
const Expr *Initializer = IgnoreNarrowingConversion(Converted);
assert(Initializer && "Unknown conversion expression");
// If it's value-dependent, we can't tell whether it's narrowing.
if (Initializer->isValueDependent())
return NK_Dependent_Narrowing;
if (Initializer &&
Initializer->isIntegerConstantExpr(IntConstantValue, Ctx)) {
if (Initializer->isIntegerConstantExpr(IntConstantValue, Ctx)) {
// Convert the integer to the floating type.
llvm::APFloat Result(Ctx.getFloatTypeSemantics(ToType));
Result.convertFromAPInt(IntConstantValue, IntConstantValue.isSigned(),

View File

@ -3175,11 +3175,7 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D,
for (const AttributeList *Attr = D.getDeclSpec().getAttributes().getList();
Attr; Attr = Attr->getNext()) {
if (Attr->getKind() == AttributeList::AT_OpenCLKernel) {
llvm::Triple::ArchType arch = S.Context.getTargetInfo().getTriple().getArch();
if (arch == llvm::Triple::spir || arch == llvm::Triple::spir64 ||
arch == llvm::Triple::amdgcn || arch == llvm::Triple::r600) {
CC = CC_OpenCLKernel;
}
CC = CC_OpenCLKernel;
break;
}
}

View File

@ -1422,8 +1422,8 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record,
getClangFullRepositoryVersion());
}
if (WritingModule) {
if (WritingModule) {
// Module name
auto Abbrev = std::make_shared<BitCodeAbbrev>();
Abbrev->Add(BitCodeAbbrevOp(MODULE_NAME));
@ -1466,9 +1466,10 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
Record.clear();
auto &Map = PP.getHeaderSearchInfo().getModuleMap();
// Primary module map file.
AddPath(Map.getModuleMapFileForUniquing(WritingModule)->getName(), Record);
AddPath(WritingModule->PresumedModuleMapFile.empty()
? Map.getModuleMapFileForUniquing(WritingModule)->getName()
: StringRef(WritingModule->PresumedModuleMapFile),
Record);
// Additional module map files.
if (auto *AdditionalModMaps =

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,171 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -w -emit-llvm -o - %s -fsanitize=pointer-overflow | FileCheck %s
// CHECK-LABEL: define void @unary_arith
void unary_arith(char *p) {
// CHECK: [[BASE:%.*]] = ptrtoint i8* {{.*}} to i64, !nosanitize
// CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], 1, !nosanitize
// CHECK-NEXT: [[POSVALID:%.*]] = icmp uge i64 [[COMPGEP]], [[BASE]], !nosanitize
// CHECK-NEXT: [[NEGVALID:%.*]] = icmp ult i64 [[COMPGEP]], [[BASE]], !nosanitize
// CHECK-NEXT: [[DIFFVALID:%.*]] = select i1 true, i1 [[POSVALID]], i1 [[NEGVALID]], !nosanitize
// CHECK-NEXT: [[VALID:%.*]] = and i1 true, [[DIFFVALID]], !nosanitize
// CHECK-NEXT: br i1 [[VALID]]{{.*}}, !nosanitize
// CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}, i64 [[BASE]], i64 [[COMPGEP]]){{.*}}, !nosanitize
++p;
// CHECK: ptrtoint i8* {{.*}} to i64, !nosanitize
// CHECK-NEXT: add i64 {{.*}}, -1, !nosanitize
// CHECK: select i1 false{{.*}}, !nosanitize
// CHECK-NEXT: and i1 true{{.*}}, !nosanitize
// CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}
--p;
// CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}
p++;
// CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}
p--;
}
// CHECK-LABEL: define void @binary_arith
void binary_arith(char *p, int i) {
// CHECK: [[SMUL:%.*]] = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 1, i64 %{{.*}}), !nosanitize
// CHECK-NEXT: [[SMULOFLOW:%.*]] = extractvalue { i64, i1 } [[SMUL]], 1, !nosanitize
// CHECK-NEXT: [[OFFSETOFLOW:%.*]] = or i1 false, [[SMULOFLOW]], !nosanitize
// CHECK-NEXT: [[SMULVAL:%.*]] = extractvalue { i64, i1 } [[SMUL]], 0, !nosanitize
// CHECK-NEXT: [[BASE:%.*]] = ptrtoint i8* {{.*}} to i64, !nosanitize
// CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], [[SMULVAL]], !nosanitize
// CHECK-NEXT: [[POSVALID:%.*]] = icmp uge i64 [[COMPGEP]], [[BASE]], !nosanitize
// CHECK-NEXT: [[NEGVALID:%.*]] = icmp ult i64 [[COMPGEP]], [[BASE]], !nosanitize
// CHECK-NEXT: [[POSOFFSET:%.*]] = icmp sge i64 [[SMULVAL]], 0, !nosanitize
// CHECK-NEXT: [[OFFSETVALID:%.*]] = xor i1 [[OFFSETOFLOW]], true, !nosanitize
// CHECK-NEXT: [[DIFFVALID:%.*]] = select i1 [[POSOFFSET]], i1 [[POSVALID]], i1 [[NEGVALID]], !nosanitize
// CHECK-NEXT: [[VALID:%.*]] = and i1 [[OFFSETVALID]], [[DIFFVALID]], !nosanitize
// CHECK-NEXT: br i1 [[VALID]]{{.*}}, !nosanitize
// CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}, i64 [[BASE]], i64 [[COMPGEP]]){{.*}}, !nosanitize
p + i;
// CHECK: [[OFFSET:%.*]] = sub i64 0, {{.*}}
// CHECK-NEXT: getelementptr inbounds {{.*}} [[OFFSET]]
// CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}
p - i;
}
// CHECK-LABEL: define void @fixed_len_array
void fixed_len_array(int k) {
// CHECK: getelementptr inbounds [10 x [10 x i32]], [10 x [10 x i32]]* [[ARR:%.*]], i64 0, i64 [[IDXPROM:%.*]]
// CHECK-NEXT: [[SMUL:%.*]] = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 40, i64 [[IDXPROM]]), !nosanitize
// CHECK-NEXT: [[SMULOFLOW:%.*]] = extractvalue { i64, i1 } [[SMUL]], 1, !nosanitize
// CHECK-NEXT: [[OFFSETOFLOW:%.*]] = or i1 false, [[SMULOFLOW]], !nosanitize
// CHECK-NEXT: [[SMULVAL:%.*]] = extractvalue { i64, i1 } [[SMUL]], 0, !nosanitize
// CHECK-NEXT: [[BASE:%.*]] = ptrtoint [10 x [10 x i32]]* [[ARR]] to i64, !nosanitize
// CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], [[SMULVAL]], !nosanitize
// CHECK-NEXT: [[POSVALID:%.*]] = icmp uge i64 [[COMPGEP]], [[BASE]], !nosanitize
// CHECK-NEXT: [[NEGVALID:%.*]] = icmp ult i64 [[COMPGEP]], [[BASE]], !nosanitize
// CHECK-NEXT: [[POSOFFSET:%.*]] = icmp sge i64 [[SMULVAL]], 0, !nosanitize
// CHECK-NEXT: [[OFFSETVALID:%.*]] = xor i1 [[OFFSETOFLOW]], true, !nosanitize
// CHECK-NEXT: [[DIFFVALID:%.*]] = select i1 [[POSOFFSET]], i1 [[POSVALID]], i1 [[NEGVALID]], !nosanitize
// CHECK-NEXT: [[VALID:%.*]] = and i1 [[OFFSETVALID]], [[DIFFVALID]], !nosanitize
// CHECK-NEXT: br i1 [[VALID]]{{.*}}, !nosanitize
// CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}, i64 [[BASE]], i64 [[COMPGEP]]){{.*}}, !nosanitize
// CHECK: getelementptr inbounds [10 x i32], [10 x i32]* {{.*}}, i64 0, i64 [[IDXPROM1:%.*]]
// CHECK-NEXT: @llvm.smul.with.overflow.i64(i64 4, i64 [[IDXPROM1]]), !nosanitize
// CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}
int arr[10][10];
arr[k][k];
}
// CHECK-LABEL: define void @variable_len_array
void variable_len_array(int n, int k) {
// CHECK: getelementptr inbounds i32, i32* {{.*}}, i64 [[IDXPROM:%.*]]
// CHECK-NEXT: @llvm.smul.with.overflow.i64(i64 4, i64 [[IDXPROM]]), !nosanitize
// CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}
// CHECK: getelementptr inbounds i32, i32* {{.*}}, i64 [[IDXPROM1:%.*]]
// CHECK-NEXT: @llvm.smul.with.overflow.i64(i64 4, i64 [[IDXPROM1]]), !nosanitize
// CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}
int arr[n][n];
arr[k][k];
}
// CHECK-LABEL: define void @pointer_array
void pointer_array(int **arr, int k) {
// CHECK: @llvm.smul.with.overflow.i64(i64 8, i64 {{.*}}), !nosanitize
// CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}
// CHECK: @llvm.smul.with.overflow.i64(i64 4, i64 {{.*}}), !nosanitize
// CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}
arr[k][k];
}
struct S1 {
int pad1;
union {
char leaf;
struct S1 *link;
} u;
struct S1 *arr;
};
// TODO: Currently, structure GEPs are not checked, so there are several
// potentially unsafe GEPs here which we don't instrument.
//
// CHECK-LABEL: define void @struct_index
void struct_index(struct S1 *p) {
// CHECK: getelementptr inbounds %struct.S1, %struct.S1* [[P:%.*]], i64 10
// CHECK-NEXT: [[BASE:%.*]] = ptrtoint %struct.S1* [[P]] to i64, !nosanitize
// CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], 240, !nosanitize
// CHECK: @__ubsan_handle_pointer_overflow{{.*}} i64 [[BASE]], i64 [[COMPGEP]]) {{.*}}, !nosanitize
// CHECK-NOT: @__ubsan_handle_pointer_overflow
p->arr[10].u.link->u.leaf;
}
typedef void (*funcptr_t)(void);
// CHECK-LABEL: define void @function_pointer_arith
void function_pointer_arith(funcptr_t *p, int k) {
// CHECK: add i64 {{.*}}, 8, !nosanitize
// CHECK: @__ubsan_handle_pointer_overflow{{.*}}
++p;
// CHECK: @llvm.smul.with.overflow.i64(i64 8, i64 {{.*}}), !nosanitize
// CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}
p + k;
}
// CHECK-LABEL: define void @variable_len_array_arith
void variable_len_array_arith(int n, int k) {
int vla[n];
int (*p)[n] = &vla;
// CHECK: getelementptr inbounds i32, i32* {{.*}}, i64 [[INC:%.*]]
// CHECK: @llvm.smul.with.overflow.i64(i64 4, i64 [[INC]]), !nosanitize
// CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}
++p;
// CHECK: getelementptr inbounds i32, i32* {{.*}}, i64 [[IDXPROM:%.*]]
// CHECK: @llvm.smul.with.overflow.i64(i64 4, i64 [[IDXPROM]]), !nosanitize
// CHECK: call void @__ubsan_handle_pointer_overflow{{.*}}
p + k;
}
// CHECK-LABEL: define void @objc_id
void objc_id(id *p) {
// CHECK: add i64 {{.*}}, 8, !nosanitize
// CHECK: @__ubsan_handle_pointer_overflow{{.*}}
p++;
}
// CHECK-LABEL: define void @dont_emit_checks_for_no_op_GEPs
// CHECK-NOT: __ubsan_handle_pointer_overflow
void dont_emit_checks_for_no_op_GEPs(char *p) {
&p[0];
int arr[10][10];
&arr[0][0];
}

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 -Wno-unused-value -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -Wno-unused-value -triple i686-linux-gnu -emit-llvm -o - %s | FileCheck %s
// rdar: //8540501
extern "C" int printf(...);
extern "C" void abort();
@ -139,6 +139,34 @@ extern "C" int cleanup_exit_lvalue(bool cond) {
// CHECK: %[[v:[^ ]*]] = load i32*, i32** %[[tmp]]
// CHECK-NEXT: store i32* %[[v]], i32** %r
// Bind the reference to a byval argument. It is not an instruction or Constant,
// so it's a bit of a corner case.
struct ByVal { int x[3]; };
extern "C" int cleanup_exit_lvalue_byval(bool cond, ByVal arg) {
ByVal &r = (A(1), ({ if (cond) return 0; (void)ByVal(); }), arg);
return r.x[0];
}
// CHECK-LABEL: define{{.*}} i32 @cleanup_exit_lvalue_byval({{.*}}, %struct.ByVal* byval align 4 %arg)
// CHECK: call {{.*}} @_ZN1AC1Ei
// CHECK: call {{.*}} @_ZN1AD1Ev
// CHECK: switch
// CHECK: store %struct.ByVal* %arg, %struct.ByVal** %r
// Bind the reference to a local variable. We don't need to spill it. Binding a
// reference to it doesn't generate any instructions.
extern "C" int cleanup_exit_lvalue_local(bool cond) {
int local = 42;
int &r = (A(1), ({ if (cond) return 0; (void)0; }), local);
return r;
}
// CHECK-LABEL: define{{.*}} i32 @cleanup_exit_lvalue_local({{.*}})
// CHECK: %local = alloca i32
// CHECK: store i32 42, i32* %local
// CHECK: call {{.*}} @_ZN1AC1Ei
// CHECK-NOT: store i32* %local
// CHECK: call {{.*}} @_ZN1AD1Ev
// CHECK: switch
// CHECK: store i32* %local, i32** %r, align 4
// We handle ExprWithCleanups for complex evaluation type separately, and it had
// the same bug.

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fstrict-vtable-pointers -disable-llvm-passes -O2 -emit-llvm -o %t.ll
// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fstrict-vtable-pointers -std=c++11 -disable-llvm-passes -O2 -emit-llvm -o %t.ll
// RUN: FileCheck --check-prefix=CHECK-CTORS %s < %t.ll
// RUN: FileCheck --check-prefix=CHECK-NEW %s < %t.ll
// RUN: FileCheck --check-prefix=CHECK-DTORS %s < %t.ll
@ -180,6 +180,119 @@ struct DynamicFromStatic;
// CHECK-CTORS-NOT: @llvm.invariant.group.barrier(
// CHECK-CTORS-LABEL: {{^}}}
struct A {
virtual void foo();
};
struct B : A {
virtual void foo();
};
union U {
A a;
B b;
};
void changeToB(U *u);
void changeToA(U *u);
void g2(A *a) {
a->foo();
}
// We have to guard access to union fields with invariant.group, because
// it is very easy to skip the barrier with unions. In this example the inlined
// g2 will produce loads with the same !invariant.group metadata, and
// u->a and u->b would use the same pointer.
// CHECK-NEW-LABEL: define void @_Z14UnionsBarriersP1U
void UnionsBarriers(U *u) {
// CHECK-NEW: call void @_Z9changeToBP1U(
changeToB(u);
// CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
// CHECK-NEW: call void @_Z2g2P1A(%struct.A*
g2(&u->b);
// CHECK-NEW: call void @_Z9changeToAP1U(%union.U*
changeToA(u);
// CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
// call void @_Z2g2P1A(%struct.A* %a)
g2(&u->a);
// CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
}
struct HoldingVirtuals {
A a;
};
struct Empty {};
struct AnotherEmpty {
Empty e;
};
union NoVptrs {
int a;
AnotherEmpty empty;
};
void take(AnotherEmpty &);
// CHECK-NEW-LABEL: noBarriers
void noBarriers(NoVptrs &noVptrs) {
// CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
// CHECK-NEW: 42
noVptrs.a += 42;
// CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
// CHECK-NEW: call void @_Z4takeR12AnotherEmpty(
take(noVptrs.empty);
}
union U2 {
HoldingVirtuals h;
int z;
};
void take(HoldingVirtuals &);
// CHECK-NEW-LABEL: define void @_Z15UnionsBarriers2R2U2
void UnionsBarriers2(U2 &u) {
// CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
// CHECK-NEW: 42
u.z += 42;
// CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
// CHECK-NEW: call void @_Z4takeR15HoldingVirtuals(
take(u.h);
}
struct VirtualInBase : HoldingVirtuals, Empty {
};
struct VirtualInVBase : virtual Empty, virtual HoldingVirtuals {
};
// It has vtable by virtual inheritance.
struct VirtualInheritance : virtual Empty {
};
union U3 {
VirtualInBase v1;
VirtualInBase v2;
VirtualInheritance v3;
int z;
};
void take(VirtualInBase &);
void take(VirtualInVBase &);
void take(VirtualInheritance &);
void UnionsBarrier3(U3 &u) {
// CHECK-NEW-NOT: call i8* @llvm.invariant.group.barrier(i8*
// CHECK-NEW: 42
u.z += 42;
// CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
// CHECK-NEW: call void @_Z4takeR13VirtualInBase(
take(u.v1);
// CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
// CHECK-NEW: call void @_Z4takeR13VirtualInBase(
take(u.v2);
// CHECK-NEW: call i8* @llvm.invariant.group.barrier(i8*
// CHECK-NEW: call void @_Z4takeR18VirtualInheritance(
take(u.v3);
}
/** DTORS **/
// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN10StaticBaseD2Ev(

View File

@ -12,6 +12,7 @@
// RUN: FileCheck --check-prefix=CHECK-TEST14 %s < %t.opt
// RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt
// RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt
// RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt
#include <typeinfo>
@ -274,8 +275,8 @@ struct C {
virtual D& operator=(const D&);
};
// Cannot emit B's vtable available_externally, because we cannot create
// a reference to the inline virtual B::operator= function.
// Cannot emit D's vtable available_externally, because we cannot create
// a reference to the inline virtual D::operator= function.
// CHECK-TEST11: @_ZTVN6Test111DE = external unnamed_addr constant
struct D : C {
virtual void key();
@ -391,3 +392,30 @@ void test() {
}
}
namespace Test17 {
// This test checks if we emit vtables opportunistically.
// CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally
// CHECK-TEST17-DAG: @_ZTVN6Test171BE = external
struct A {
virtual void key();
virtual void bar() {}
};
// We won't gonna use deleting destructor for this type, which will disallow
// emitting vtable as available_externally
struct B {
virtual void key();
virtual ~B() {}
};
void testcaseA() {
A a;
a.bar(); // this forces to emit definition of bar
}
void testcaseB() {
B b; // This only forces emitting of complete object destructor
}
} // namespace Test17

View File

@ -145,12 +145,14 @@ void use_F() {
// F<int> is an explicit template instantiation declaration without a
// key function, so its vtable should have external linkage.
// CHECK-DAG: @_ZTV1FIiE = external unnamed_addr constant
// CHECK-OPT-DAG: @_ZTV1FIiE = external unnamed_addr constant
// CHECK-OPT-DAG: @_ZTV1FIiE = available_externally unnamed_addr constant
// E<int> is an explicit template instantiation declaration. It has a
// key function is not instantiated, so we know that vtable definition
// will be generated in TU where key function will be defined
// so we can mark it as available_externally (only with optimizations)
// so we can mark it as external (without optimizations) and
// available_externally (with optimizations) because all of the inline
// virtual functions have been emitted.
// CHECK-DAG: @_ZTV1EIiE = external unnamed_addr constant
// CHECK-OPT-DAG: @_ZTV1EIiE = available_externally unnamed_addr constant

View File

@ -0,0 +1,38 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines-ts -std=c++14 -emit-llvm %s -o - | FileCheck %s
#include "Inputs/coroutine.h"
using namespace std::experimental;
struct coro {
struct promise_type {
coro get_return_object();
suspend_never initial_suspend();
suspend_never final_suspend();
void return_void();
static void unhandled_exception();
};
};
struct A {
~A();
bool await_ready();
int await_resume() { return 8; }
template <typename F> void await_suspend(F);
};
extern "C" void consume(int);
// Verifies that domination is properly built during cleanup.
// Without CGCleanup.cpp fix verifier was reporting:
// Instruction does not dominate all uses!
// %tmp.exprcleanup = alloca i32*, align 8
// store i32* %x, i32** %tmp.exprcleanup, align 8
// CHECK-LABEL: f(
extern "C" coro f(int) {
int x = 42;
x = co_await A{};
consume(x);
}

View File

@ -68,3 +68,31 @@ void blockTest(NSMutableArray<void (^)(void)> *array, NSString *name) {
// CHECK: call i8* @objc_retainBlock
// CHECK: ret void
}
// CHECK-LABEL: define internal void @"\01-[Derived setDest:]
// CHECK: %[[SELFADDR:.*]] = alloca %[[SELFTY:.*]]*
// CHECK: %[[AADDR:.*]] = alloca %[[IVARTY:.*]]*
// CHECK: %[[V2:.*]] = load %[[IVARTY]]*, %[[IVARTY]]** %[[AADDR]]
// CHECK: %[[V3:.*]] = load %[[SELFTY]]*, %[[SELFTY]]** %[[SELFADDR]]
// CHECK: %[[IVAR:.*]] = load i64, i64* @"OBJC_IVAR_$_Base._destination"
// CHECK: %[[V4:.*]] = bitcast %[[SELFTY]]* %[[V3]] to i8*
// CHECK: %[[ADDPTR:.*]] = getelementptr inbounds i8, i8* %[[V4]], i64 %[[IVAR]]
// CHECK: %[[V5:.*]] = bitcast i8* %[[ADDPTR]] to %[[IVARTY]]**
// CHECK: %[[V6:.*]] = bitcast %[[IVARTY]]** %[[V5]] to i8**
// CHECK: %[[V7:.*]] = bitcast %[[IVARTY]]* %[[V2]] to i8*
// CHECK: call void @objc_storeStrong(i8** %[[V6]], i8* %[[V7]])
@interface Base<DestType> : NSObject {
DestType _destination;
}
@end
@interface Derived : Base<NSObject *>
- (void)setDest:(NSObject *)a;
@end
@implementation Derived
- (void)setDest:(NSObject *)a {
_destination = a;
}
@end

View File

@ -4,7 +4,7 @@ typedef unsigned char uchar4 __attribute((ext_vector_type(4)));
typedef unsigned int int4 __attribute((ext_vector_type(4)));
typedef float float4 __attribute((ext_vector_type(4)));
// CHECK-LABEL: define void @ker()
// CHECK-LABEL: define spir_kernel void @ker()
void kernel ker() {
bool t = true;
int4 vec4 = (int4)t;

View File

@ -3,13 +3,13 @@
typedef unsigned int uint4 __attribute__((ext_vector_type(4)));
kernel __attribute__((vec_type_hint(int))) __attribute__((reqd_work_group_size(1,2,4))) void kernel1(int a) {}
// CHECK: define void @kernel1(i32 {{[^%]*}}%a) {{[^{]+}} !vec_type_hint ![[MD1:[0-9]+]] !reqd_work_group_size ![[MD2:[0-9]+]]
// CHECK: define spir_kernel void @kernel1(i32 {{[^%]*}}%a) {{[^{]+}} !vec_type_hint ![[MD1:[0-9]+]] !reqd_work_group_size ![[MD2:[0-9]+]]
kernel __attribute__((vec_type_hint(uint4))) __attribute__((work_group_size_hint(8,16,32))) void kernel2(int a) {}
// CHECK: define void @kernel2(i32 {{[^%]*}}%a) {{[^{]+}} !vec_type_hint ![[MD3:[0-9]+]] !work_group_size_hint ![[MD4:[0-9]+]]
// CHECK: define spir_kernel void @kernel2(i32 {{[^%]*}}%a) {{[^{]+}} !vec_type_hint ![[MD3:[0-9]+]] !work_group_size_hint ![[MD4:[0-9]+]]
kernel __attribute__((intel_reqd_sub_group_size(8))) void kernel3(int a) {}
// CHECK: define void @kernel3(i32 {{[^%]*}}%a) {{[^{]+}} !intel_reqd_sub_group_size ![[MD5:[0-9]+]]
// CHECK: define spir_kernel void @kernel3(i32 {{[^%]*}}%a) {{[^{]+}} !intel_reqd_sub_group_size ![[MD5:[0-9]+]]
// CHECK: [[MD1]] = !{i32 undef, i32 1}
// CHECK: [[MD2]] = !{i32 1, i32 2, i32 4}

View File

@ -6,5 +6,5 @@ void normal_function() {
__kernel void kernel_function() {
}
// CHECK: define void @kernel_function() {{[^{]+}} !kernel_arg_addr_space ![[MD:[0-9]+]] !kernel_arg_access_qual ![[MD]] !kernel_arg_type ![[MD]] !kernel_arg_base_type ![[MD]] !kernel_arg_type_qual ![[MD]] {
// CHECK: define spir_kernel void @kernel_function() {{[^{]+}} !kernel_arg_addr_space ![[MD:[0-9]+]] !kernel_arg_access_qual ![[MD]] !kernel_arg_type ![[MD]] !kernel_arg_base_type ![[MD]] !kernel_arg_type_qual ![[MD]] {
// CHECK: ![[MD]] = !{}

View File

@ -0,0 +1,65 @@
// RUN: %clang_cc1 %s -cl-std=CL1.2 -emit-llvm -triple x86_64-unknown-unknown -o - | FileCheck %s
// RUN: %clang_cc1 %s -cl-std=CL1.2 -emit-llvm -triple amdgcn-unknown-unknown -o - | FileCheck -check-prefixes=AMDGCN %s
// Test that the kernels always use the SPIR calling convention
// to have unambiguous mapping of arguments to feasibly implement
// clSetKernelArg().
typedef struct int_single {
int a;
} int_single;
typedef struct int_pair {
long a;
long b;
} int_pair;
typedef struct test_struct {
int elementA;
int elementB;
long elementC;
char elementD;
long elementE;
float elementF;
short elementG;
double elementH;
} test_struct;
kernel void test_single(int_single input, global int* output) {
// CHECK: spir_kernel
// AMDGCN: define amdgpu_kernel void @test_single
// CHECK: struct.int_single* byval nocapture
// CHECK: i32* nocapture %output
output[0] = input.a;
}
kernel void test_pair(int_pair input, global int* output) {
// CHECK: spir_kernel
// AMDGCN: define amdgpu_kernel void @test_pair
// CHECK: struct.int_pair* byval nocapture
// CHECK: i32* nocapture %output
output[0] = (int)input.a;
output[1] = (int)input.b;
}
kernel void test_kernel(test_struct input, global int* output) {
// CHECK: spir_kernel
// AMDGCN: define amdgpu_kernel void @test_kernel
// CHECK: struct.test_struct* byval nocapture
// CHECK: i32* nocapture %output
output[0] = input.elementA;
output[1] = input.elementB;
output[2] = (int)input.elementC;
output[3] = (int)input.elementD;
output[4] = (int)input.elementE;
output[5] = (int)input.elementF;
output[6] = (int)input.elementG;
output[7] = (int)input.elementH;
};
void test_function(int_pair input, global int* output) {
// CHECK-NOT: spir_kernel
// AMDGCN-NOT: define amdgpu_kernel void @test_function
// CHECK: i64 %input.coerce0, i64 %input.coerce1, i32* nocapture %output
output[0] = (int)input.a;
output[1] = (int)input.b;
}

View File

@ -28,7 +28,7 @@ void test5(read_only pipe int4 p) {
typedef read_only pipe int MyPipe;
kernel void test6(MyPipe p) {
// CHECK: define void @test6(%opencl.pipe_t* %p)
// CHECK: define spir_kernel void @test6(%opencl.pipe_t* %p)
}
struct Person {

View File

@ -7,7 +7,7 @@ void device_function() {
__kernel void kernel_function() {
device_function();
}
// CHECK-LABEL: define void @kernel_function()
// CHECK-LABEL: define spir_kernel void @kernel_function()
// CHECK: call void @device_function()
// CHECK: !{{[0-9]+}} = !{void ()* @kernel_function, !"kernel", i32 1}

View File

@ -6,6 +6,6 @@ void device_function() {
__kernel void kernel_function() {
}
// CHECK-LABEL: define void @kernel_function()
// CHECK-LABEL: define spir_kernel void @kernel_function()
// CHECK: !{{[0-9]+}} = !{void ()* @kernel_function, !"kernel", i32 1}

View File

@ -120,11 +120,11 @@
// RUN: %clang -target armv7a-linux-gnueabi -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V7A %s
// RUN: %clang -target arm-linux-gnueabi -march=armv7-a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V7A %s
// CHECK-V7A: "-cc1"{{.*}} "-triple" "armv7-{{.*}} "-target-cpu" "cortex-a8"
// CHECK-V7A: "-cc1"{{.*}} "-triple" "armv7-{{.*}} "-target-cpu" "generic"
// RUN: %clang -target armv7a-linux-gnueabi -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V7A-THUMB %s
// RUN: %clang -target arm-linux-gnueabi -march=armv7-a -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V7A-THUMB %s
// CHECK-V7A-THUMB: "-cc1"{{.*}} "-triple" "thumbv7-{{.*}} "-target-cpu" "cortex-a8"
// CHECK-V7A-THUMB: "-cc1"{{.*}} "-triple" "thumbv7-{{.*}} "-target-cpu" "generic"
// RUN: %clang -target armv7r-linux-gnueabi -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V7R %s
// RUN: %clang -target arm-linux-gnueabi -march=armv7-r -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V7R %s
@ -144,7 +144,7 @@
// RUN: %clang -target armv8a -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A %s
// RUN: %clang -target arm -march=armv8a -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A %s
// RUN: %clang -target arm -mlittle-endian -march=armv8-a -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A %s
// CHECK-V8A: "-cc1"{{.*}} "-triple" "armv8-{{.*}}" "-target-cpu" "cortex-a53"
// CHECK-V8A: "-cc1"{{.*}} "-triple" "armv8-{{.*}}" "-target-cpu" "generic"
// RUN: %clang -target armv8r-linux-gnueabi -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8R %s
// RUN: %clang -target arm -march=armv8r -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8R %s
@ -189,7 +189,7 @@
// RUN: %clang -target armv8a -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V8A %s
// RUN: %clang -target arm -march=armebv8a -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V8A %s
// RUN: %clang -target arm -march=armebv8-a -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V8A %s
// CHECK-BE-V8A: "-cc1"{{.*}} "-triple" "armebv8-{{.*}}" "-target-cpu" "cortex-a53"
// CHECK-BE-V8A: "-cc1"{{.*}} "-triple" "armebv8-{{.*}}" "-target-cpu" "generic"
// RUN: %clang -target armv8 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A-THUMB %s
// RUN: %clang -target arm -march=armv8 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A-THUMB %s
@ -199,7 +199,7 @@
// RUN: %clang -target arm -march=armv8 -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A-THUMB %s
// RUN: %clang -target armv8a -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A-THUMB %s
// RUN: %clang -target arm -march=armv8a -mlittle-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A-THUMB %s
// CHECK-V8A-THUMB: "-cc1"{{.*}} "-triple" "thumbv8-{{.*}}" "-target-cpu" "cortex-a53"
// CHECK-V8A-THUMB: "-cc1"{{.*}} "-triple" "thumbv8-{{.*}}" "-target-cpu" "generic"
// RUN: %clang -target armebv8 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V8A-THUMB %s
// RUN: %clang -target armeb -march=armebv8 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V8A-THUMB %s
@ -209,7 +209,7 @@
// RUN: %clang -target arm -march=armebv8 -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V8A-THUMB %s
// RUN: %clang -target armv8a -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V8A-THUMB %s
// RUN: %clang -target arm -march=armebv8a -mbig-endian -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-V8A-THUMB %s
// CHECK-BE-V8A-THUMB: "-cc1"{{.*}} "-triple" "thumbebv8-{{.*}}" "-target-cpu" "cortex-a53"
// CHECK-BE-V8A-THUMB: "-cc1"{{.*}} "-triple" "thumbebv8-{{.*}}" "-target-cpu" "generic"
// RUN: %clang -target arm -march=armv8.1a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V81A %s
// RUN: %clang -target armv8.1a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V81A %s

33
test/Driver/cl-cc-flags.c Normal file
View File

@ -0,0 +1,33 @@
// Note: %s must be preceded by --, otherwise it may be interpreted as a
// command-line option, e.g. on Mac where %s is commonly under /Users.
// RUN: %clang_cl --target=i686-windows-msvc /Gd -### -- %s 2>&1 | FileCheck --check-prefix=CDECL %s
// CDECL: -fdefault-calling-conv=cdecl
// RUN: %clang_cl --target=i686-windows-msvc /Gr -### -- %s 2>&1 | FileCheck --check-prefix=FASTCALL %s
// FASTCALL: -fdefault-calling-conv=fastcall
// RUN: %clang_cl --target=i686-windows-msvc /Gz -### -- %s 2>&1 | FileCheck --check-prefix=STDCALL %s
// STDCALL: -fdefault-calling-conv=stdcall
// RUN: %clang_cl --target=i686-windows-msvc /Gv -### -- %s 2>&1 | FileCheck --check-prefix=VECTORCALL %s
// VECTORCALL: -fdefault-calling-conv=vectorcall
// Last one should win:
// RUN: %clang_cl --target=i686-windows-msvc /Gd /Gv -### -- %s 2>&1 | FileCheck --check-prefix=LASTWINS_VECTOR %s
// LASTWINS_VECTOR: -fdefault-calling-conv=vectorcall
// RUN: %clang_cl --target=i686-windows-msvc /Gv /Gd -### -- %s 2>&1 | FileCheck --check-prefix=LASTWINS_CDECL %s
// LASTWINS_CDECL: -fdefault-calling-conv=cdecl
// No fastcall or stdcall on x86_64:
// RUN: %clang_cl -Wno-msvc-not-found --target=x86_64-windows-msvc /Gr -### -- %s 2>&1 | FileCheck --check-prefix=UNSUPPORTED %s
// RUN: %clang_cl -Wno-msvc-not-found --target=x86_64-windows-msvc /Gz -### -- %s 2>&1 | FileCheck --check-prefix=UNSUPPORTED %s
// RUN: %clang_cl -Wno-msvc-not-found --target=thumbv7-windows-msvc /Gv -### -- %s 2>&1 | FileCheck --check-prefix=UNSUPPORTED %s
// UNSUPPORTED-NOT: error:
// UNSUPPORTED-NOT: warning:
// UNSUPPORTED-NOT: -fdefault-calling-conv=

View File

@ -0,0 +1,28 @@
// Note: %s must be preceded by --, otherwise it may be interpreted as a
// command-line option, e.g. on Mac where %s is commonly under /Users.
// RUN: %clang_cl /diagnostics:classic -### -- %s 2>&1 | FileCheck %s --check-prefix=CLASSIC
// CLASSIC: -fno-caret-diagnostics
// CLASSIC: -fno-show-column
// RUN: %clang_cl /diagnostics:column -### -- %s 2>&1 | FileCheck %s --check-prefix=COLUMN
// COLUMN: -fno-caret-diagnostics
// COLUMN-NOT: -fno-show-column
// RUN: %clang_cl /diagnostics:caret -### -- %s 2>&1 | FileCheck %s --check-prefix=CARET
// CARET-NOT: -fno-caret-diagnostics
// CARET-NOT: -fno-show-column
// RUN: not %clang_cl -fms-compatibility-version=19 /diagnostics:classic /Zs -c -- %s 2>&1 | FileCheck %s --check-prefix=OUTPUT_CLASSIC
// OUTPUT_CLASSIC: cl-diagnostics.c({{[0-9]+}}): error: "asdf"
// OUTPUT_CLASSIC-NOT: #error
// RUN: not %clang_cl -fms-compatibility-version=19 /diagnostics:caret /Zs -c -- %s 2>&1 | FileCheck %s --check-prefix=OUTPUT_CARET
// OUTPUT_CARET: cl-diagnostics.c({{[0-9]+,[0-9]+}}): error: "asdf"
// OUTPUT_CARET-NEXT: #error "asdf"
// OUTPUT_CARET-NEXT: ^
#error "asdf"

14
test/Driver/cl-include.c Normal file
View File

@ -0,0 +1,14 @@
// Note: %s must be preceded by --, otherwise it may be interpreted as a
// command-line option, e.g. on Mac where %s is commonly under /Users.
// RUN: %clang_cl -### -- %s 2>&1 | FileCheck %s --check-prefix=BUILTIN
// BUILTIN: "-internal-isystem" "{{.*lib.*clang.*include}}"
// RUN: %clang_cl -nobuiltininc -### -- %s 2>&1 | FileCheck %s --check-prefix=NOBUILTIN
// NOBUILTIN-NOT: "-internal-isystem" "{{.*lib.*clang.*include}}"
// RUN: env INCLUDE=/my/system/inc %clang_cl -### -- %s 2>&1 | FileCheck %s --check-prefix=STDINC
// STDINC: "-internal-isystem" "/my/system/inc"
// RUN: env INCLUDE=/my/system/inc %clang_cl -nostdinc -### -- %s 2>&1 | FileCheck %s --check-prefix=NOSTDINC
// NOSTDINC-NOT: "-internal-isystem" "/my/system/inc"

View File

@ -53,6 +53,11 @@
// RUN: %clang_cl /c -### /Zc:inline- -- %s 2>&1 | FileCheck -check-prefix=INLINE-OFF %s
// INLINE-OFF: argument unused during compilation
// RUN: %clang_cl /c -### /Zc:ternary -- %s 2>&1 | FileCheck -check-prefix=TERNARY-ON %s
// TERNARY-ON-NOT: argument unused during compilation
// RUN: %clang_cl /c -### /Zc:ternary- -- %s 2>&1 | FileCheck -check-prefix=TERNARY-OFF %s
// TERNARY-OFF: argument unused during compilation
// These never warn, but don't have an effect yet.

View File

@ -3,18 +3,18 @@
// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize-undefined-trap-on-error %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP
// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP
// RUN: %clang -target x86_64-linux-gnu -fsanitize-undefined-trap-on-error -fsanitize=undefined-trap %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP
// CHECK-UNDEFINED-TRAP: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute|function),?){18}"}}
// CHECK-UNDEFINED-TRAP: "-fsanitize-trap=alignment,array-bounds,bool,enum,float-cast-overflow,float-divide-by-zero,function,integer-divide-by-zero,nonnull-attribute,null,object-size,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound"
// CHECK-UNDEFINED-TRAP2: "-fsanitize-trap=alignment,array-bounds,bool,enum,float-cast-overflow,float-divide-by-zero,function,integer-divide-by-zero,nonnull-attribute,null,object-size,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound"
// CHECK-UNDEFINED-TRAP: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute|function),?){19}"}}
// CHECK-UNDEFINED-TRAP: "-fsanitize-trap=alignment,array-bounds,bool,enum,float-cast-overflow,float-divide-by-zero,function,integer-divide-by-zero,nonnull-attribute,null,object-size,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound"
// CHECK-UNDEFINED-TRAP2: "-fsanitize-trap=alignment,array-bounds,bool,enum,float-cast-overflow,float-divide-by-zero,function,integer-divide-by-zero,nonnull-attribute,null,object-size,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound"
// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED
// CHECK-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|vptr|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){19}"}}
// CHECK-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|vptr|object-size|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){20}"}}
// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-DARWIN
// CHECK-UNDEFINED-DARWIN: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){17}"}}
// CHECK-UNDEFINED-DARWIN: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){18}"}}
// RUN: %clang -target i386-unknown-openbsd -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-OPENBSD
// CHECK-UNDEFINED-OPENBSD: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){17}"}}
// CHECK-UNDEFINED-OPENBSD: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){18}"}}
// RUN: %clang -target i386-pc-win32 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-WIN --check-prefix=CHECK-UNDEFINED-WIN32
// RUN: %clang -target i386-pc-win32 -fsanitize=undefined -x c++ %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-WIN --check-prefix=CHECK-UNDEFINED-WIN32 --check-prefix=CHECK-UNDEFINED-WIN-CXX
@ -23,7 +23,7 @@
// CHECK-UNDEFINED-WIN32: "--dependent-lib={{[^"]*}}ubsan_standalone-i386.lib"
// CHECK-UNDEFINED-WIN64: "--dependent-lib={{[^"]*}}ubsan_standalone-x86_64.lib"
// CHECK-UNDEFINED-WIN-CXX: "--dependent-lib={{[^"]*}}ubsan_standalone_cxx{{[^"]*}}.lib"
// CHECK-UNDEFINED-WIN-SAME: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){17}"}}
// CHECK-UNDEFINED-WIN-SAME: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){18}"}}
// RUN: %clang -target i386-pc-win32 -fsanitize-coverage=bb %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-COVERAGE-WIN32
// CHECK-COVERAGE-WIN32: "--dependent-lib={{[^"]*}}ubsan_standalone-i386.lib"
@ -43,7 +43,7 @@
// CHECK-FNO-SANITIZE-ALL: "-fsanitize=thread"
// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread,undefined -fno-sanitize=thread -fno-sanitize=float-cast-overflow,vptr,bool,enum %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-PARTIAL-UNDEFINED
// CHECK-PARTIAL-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|array-bounds|returns-nonnull-attribute|nonnull-attribute),?){15}"}}
// CHECK-PARTIAL-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|object-size|pointer-overflow|array-bounds|returns-nonnull-attribute|nonnull-attribute),?){16}"}}
// RUN: %clang -target x86_64-linux-gnu -fsanitize=shift -fno-sanitize=shift-base %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FSANITIZE-SHIFT-PARTIAL
// CHECK-FSANITIZE-SHIFT-PARTIAL: "-fsanitize=shift-exponent"
@ -217,7 +217,7 @@
// RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fno-sanitize-recover=undefined -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-RECOVER-UBSAN
// RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fno-sanitize-recover=all -fsanitize-recover=thread -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-RECOVER-UBSAN
// RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fsanitize-recover=all -fno-sanitize-recover=undefined -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-RECOVER-UBSAN
// CHECK-RECOVER-UBSAN: "-fsanitize-recover={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|vla-bound|alignment|null|vptr|object-size|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){17}"}}
// CHECK-RECOVER-UBSAN: "-fsanitize-recover={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|vla-bound|alignment|null|vptr|object-size|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|returns-nonnull-attribute|nonnull-attribute),?){18}"}}
// CHECK-NO-RECOVER-UBSAN-NOT: sanitize-recover
// RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fno-sanitize-recover=all -fsanitize-recover=object-size,shift-base -### 2>&1 | FileCheck %s --check-prefix=CHECK-PARTIAL-RECOVER

View File

@ -19,7 +19,7 @@
// RUN: -march=armv7a -Wl,-plugin-opt=foo -O0 \
// RUN: | FileCheck %s --check-prefix=CHECK-ARM-V7A
// CHECK-ARM-V7A: "-plugin" "{{.*}}/LLVMgold.so"
// CHECK-ARM-V7A: "-plugin-opt=mcpu=cortex-a8"
// CHECK-ARM-V7A: "-plugin-opt=mcpu=generic"
// CHECK-ARM-V7A: "-plugin-opt=O0"
// CHECK-ARM-V7A: "-plugin-opt=foo"
//

View File

@ -46,7 +46,7 @@
// RUN: | FileCheck --check-prefix=CHECK-ARM %s
// CHECK-ARM: {{.*}}clang{{.*}}" "-cc1"
// CHECK-ARM: "-fuse-init-array"
// CHECK-ARM: "-target-cpu" "cortex-a8"
// CHECK-ARM: "-target-cpu" "generic"
// CHECK-ARM: "-target-abi" "aapcs-linux"
// CHECK-ARM: "-mfloat-abi" "hard"
// CHECK-ARM: "-resource-dir" "foo"

View File

@ -210,14 +210,16 @@
// CHK-LKS-ST: INPUT([[T2BIN:.+\.out-openmp-x86_64-pc-linux-gnu]])
// CHK-LKS: SECTIONS
// CHK-LKS: {
// CHK-LKS: .omp_offloading :
// CHK-LKS: .omp_offloading.powerpc64le-ibm-linux-gnu :
// CHK-LKS: ALIGN(0x10)
// CHK-LKS: {
// CHK-LKS: . = ALIGN(0x10);
// CHK-LKS: PROVIDE_HIDDEN(.omp_offloading.img_start.powerpc64le-ibm-linux-gnu = .);
// CHK-LKS: [[T1BIN]]
// CHK-LKS: PROVIDE_HIDDEN(.omp_offloading.img_end.powerpc64le-ibm-linux-gnu = .);
// CHK-LKS: . = ALIGN(0x10);
// CHK-LKS: }
// CHK-LKS: .omp_offloading.x86_64-pc-linux-gnu :
// CHK-LKS: ALIGN(0x10)
// CHK-LKS: {
// CHK-LKS: PROVIDE_HIDDEN(.omp_offloading.img_start.x86_64-pc-linux-gnu = .);
// CHK-LKS: [[T2BIN]]
// CHK-LKS: PROVIDE_HIDDEN(.omp_offloading.img_end.x86_64-pc-linux-gnu = .);

View File

@ -4,6 +4,7 @@
// This should not emit anything.
// RUN: %clang_cc1 %s -w 2>&1 | not grep diagnostic
// RUN: %clang_cc1 %s -Wno-#warnings 2>&1 | not grep diagnostic
// RUN: %clang_cc1 %s -Wno-cpp 2>&1 | not grep diagnostic
// -Werror can map all warnings to error.
// RUN: not %clang_cc1 %s -Werror 2>&1 | grep "error: foo"

View File

@ -866,6 +866,40 @@ S9 s9;
#endif
}
namespace TemplateSpecializationType {
#if defined(FIRST)
template <class T1> struct U1 {};
struct S1 {
U1<int> u;
};
#elif defined(SECOND)
template <class T1, class T2> struct U1 {};
struct S1 {
U1<int, int> u;
};
#else
S1 s1;
// expected-error@first.h:* {{'TemplateSpecializationType::S1::u' from module 'FirstModule' is not present in definition of 'TemplateSpecializationType::S1' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'u' does not match}}
#endif
#if defined(FIRST)
template <class T1> struct U2 {};
struct S2 {
U2<int> u;
};
#elif defined(SECOND)
template <class T1> struct V1 {};
struct S2 {
V1<int> u;
};
#else
S2 s2;
// expected-error@first.h:* {{'TemplateSpecializationType::S2::u' from module 'FirstModule' is not present in definition of 'TemplateSpecializationType::S2' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'u' does not match}}
#endif
}
// Interesting cases that should not cause errors. struct S should not error
// while struct T should error at the access specifier mismatch at the end.
namespace AllDecls {

View File

@ -14,8 +14,6 @@
// RUN: FileCheck %s --input-file %t/rewrite.ii --check-prefix=CHECK --check-prefix=REWRITE
// Check that we can build a module from the preprocessed output.
// FIXME: For now, we need the headers to exist.
// RUN: touch %t/file.h %t/file2.h
// RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodule-file=%t/fwd.pcm -x c++-module-map-cpp-output %t/no-rewrite.ii -emit-module -o %t/no-rewrite.pcm
// RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodule-file=%t/fwd.pcm -x c++-module-map-cpp-output %t/rewrite.ii -emit-module -o %t/rewrite.pcm
@ -27,6 +25,8 @@
// Check the module we built works.
// RUN: %clang_cc1 -fmodules -fmodule-file=%t/no-rewrite.pcm %s -I%t -verify -fno-modules-error-recovery
// RUN: %clang_cc1 -fmodules -fmodule-file=%t/rewrite.pcm %s -I%t -verify -fno-modules-error-recovery -DREWRITE
// RUN: %clang_cc1 -fmodules -fmodule-file=%t/no-rewrite.pcm %s -I%t -verify -fno-modules-error-recovery -DINCLUDE -I%S/Inputs/preprocess
// RUN: %clang_cc1 -fmodules -fmodule-file=%t/rewrite.pcm %s -I%t -verify -fno-modules-error-recovery -DREWRITE -DINCLUDE -I%S/Inputs/preprocess
// == module map
@ -102,7 +102,11 @@ __FILE *a; // expected-error {{declaration of '__FILE' must be imported}}
// expected-note@no-rewrite.ii:1 {{here}}
#endif
#ifdef INCLUDE
#include "file.h"
#else
#pragma clang module import file
#endif
FILE *b;
int x = file2;
int x = file2; // ok, found in file2.h, even under -DINCLUDE

View File

@ -8,8 +8,6 @@
// RUN: FileCheck %s --input-file %t/rewrite.ii --check-prefix=CHECK --check-prefix=REWRITE
// Check that we can build a module from the preprocessed output.
// FIXME: For now, the files need to exist.
// RUN: touch %t/a.h %t/b.h %t/c.h
// RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility -fmodule-name=nested -x c++-module-map-cpp-output %t/no-rewrite.ii -emit-module -o %t/no-rewrite.pcm
// RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility -fmodule-name=nested -x c++-module-map-cpp-output %t/rewrite.ii -emit-module -o %t/rewrite.pcm

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 -x c++-module-map %s -fmodule-name=a -verify
// RUN: %clang_cc1 -x c++-module-map %s -fmodule-name=a -verify -std=c++98
module a {
module b {
requires cplusplus11

View File

@ -7,9 +7,9 @@
#define ATTR __attribute__((require_constant_initialization)) // expected-note 0+ {{expanded from macro}}
int ReturnInt();
int ReturnInt(); // expected-note 0+ {{declared here}}
struct PODType {
struct PODType { // expected-note 0+ {{declared here}}
int value;
int value2;
};
@ -20,20 +20,20 @@ struct PODType {
struct LitType {
constexpr LitType() : value(0) {}
constexpr LitType(int x) : value(x) {}
LitType(void *) : value(-1) {}
LitType(void *) : value(-1) {} // expected-note 0+ {{declared here}}
int value;
};
#endif
struct NonLit {
struct NonLit { // expected-note 0+ {{declared here}}
#if __cplusplus >= 201402L
constexpr NonLit() : value(0) {}
constexpr NonLit(int x) : value(x) {}
#else
NonLit() : value(0) {}
NonLit() : value(0) {} // expected-note 0+ {{declared here}}
NonLit(int x) : value(x) {}
#endif
NonLit(void *) : value(-1) {}
NonLit(void *) : value(-1) {} // expected-note 0+ {{declared here}}
~NonLit() {}
int value;
};
@ -43,7 +43,7 @@ struct StoresNonLit {
constexpr StoresNonLit() : obj() {}
constexpr StoresNonLit(int x) : obj(x) {}
#else
StoresNonLit() : obj() {}
StoresNonLit() : obj() {} // expected-note 0+ {{declared here}}
StoresNonLit(int x) : obj(x) {}
#endif
StoresNonLit(void *p) : obj(p) {}
@ -82,6 +82,12 @@ void test_basic_start_static_2_1() {
const int non_global = 42;
ATTR static const int &local_init = non_global; // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
#if __cplusplus >= 201103L
// expected-note@-3 {{reference to 'non_global' is not a constant expression}}
// expected-note@-5 {{declared here}}
#else
// expected-note@-6 {{subexpression not valid in a constant expression}}
#endif
ATTR static const int &global_init = glvalue_int;
ATTR static const int &temp_init = 42;
}
@ -89,8 +95,18 @@ void test_basic_start_static_2_1() {
ATTR const int &temp_ref = 42;
ATTR const int &temp_ref2 = ReturnInt(); // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
#if __cplusplus >= 201103L
// expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}}
#else
// expected-note@-5 {{subexpression not valid in a constant expression}}
#endif
ATTR const NonLit &nl_temp_ref = 42; // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
#if __cplusplus >= 201103L
// expected-note@-3 {{non-literal type 'const NonLit' cannot be used in a constant expression}}
#else
// expected-note@-5 {{subexpression not valid in a constant expression}}
#endif
#if __cplusplus >= 201103L
ATTR const LitType &lit_temp_ref = 42;
@ -99,6 +115,11 @@ ATTR const int &subobj_ref = LitType{}.value;
ATTR const int &nl_subobj_ref = NonLit().value; // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
#if __cplusplus >= 201103L
// expected-note-re@-3 {{non-literal type '{{.*}}' cannot be used in a constant expression}}
#else
// expected-note@-5 {{subexpression not valid in a constant expression}}
#endif
struct TT1 {
ATTR static const int &no_init;
@ -116,6 +137,8 @@ const int &TT1::subobj_init = PODType().value;
#if __cplusplus >= 201103L
thread_local const int &TT1::tl_glvalue_init = glvalue_int;
thread_local const int &TT1::tl_temp_init = 42; // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{reference to temporary is not a constant expression}}
// expected-note@-2 {{temporary created here}}
#endif
// [basic.start.static]p2.2
@ -129,17 +152,25 @@ void test_basic_start_static_2_2() {
#else
ATTR static PODType pod; // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
// expected-note@-2 {{non-constexpr constructor 'PODType' cannot be used in a constant expression}}
#endif
ATTR static PODType pot2 = {ReturnInt()}; // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
#if __cplusplus >= 201103L
// expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}}
#else
// expected-note@-5 {{subexpression not valid in a constant expression}}
#endif
#if __cplusplus >= 201103L
constexpr LitType l;
ATTR static LitType static_lit = l;
ATTR static LitType static_lit2 = (void *)0; // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
// expected-note@-2 {{non-constexpr constructor 'LitType' cannot be used in a constant expression}}
ATTR static LitType static_lit3 = ReturnInt(); // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
// expected-note@-2 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}}
ATTR thread_local LitType tls = 42;
#endif
}
@ -157,15 +188,23 @@ struct TT2 {
ATTR static const NonLit non_lit_copy_init; // expected-note {{required by 'require_constant_initialization' attribute here}}
#endif
};
PODType TT2::pod_noinit;
PODType TT2::pod_noinit; // expected-note 0+ {{declared here}}
#if __cplusplus >= 201103L
// expected-error@-2 {{variable does not have a constant initializer}}
// expected-note@-3 {{non-constexpr constructor 'PODType' cannot be used in a constant expression}}
#endif
PODType TT2::pod_copy_init(TT2::pod_noinit); // expected-error {{variable does not have a constant initializer}}
#if __cplusplus >= 201103L
// expected-note@-2 {{read of non-constexpr variable 'pod_noinit' is not allowed in a constant expression}}
// expected-note@-3 {{in call to 'PODType(pod_noinit)'}}
#else
// expected-note@-5 {{subexpression not valid in a constant expression}}
#endif
#if __cplusplus >= 201402L
const NonLit TT2::non_lit(42);
const NonLit TT2::non_lit_list_init = {42};
const NonLit TT2::non_lit_copy_init = 42; // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{subexpression not valid in a constant expression}}
#endif
#if __cplusplus >= 201103L
@ -183,19 +222,25 @@ ATTR StoresNonLit snl;
#else
ATTR NonLit nl_ctor; // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
// expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}}
ATTR NonLit nl_ctor2{}; // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
// expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}}
ATTR NonLit nl_ctor3 = {}; // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
// expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}}
ATTR thread_local NonLit nl_ctor_tl = {}; // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
// expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}}
ATTR StoresNonLit snl; // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
// expected-note@-2 {{non-constexpr constructor 'StoresNonLit' cannot be used in a constant expression}}
#endif
// Non-literal types cannot appear in the initializer of a non-literal type.
ATTR int nl_in_init = NonLit{42}.value; // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
// expected-note@-2 {{non-literal type 'NonLit' cannot be used in a constant expression}}
ATTR int lit_in_init = LitType{42}.value;
#endif
@ -218,6 +263,11 @@ ATTR PODType pod_missing_init = {42 /* should have second arg */};
ATTR PODType pod_full_init = {1, 2};
ATTR PODType pod_non_constexpr_init = {1, ReturnInt()}; // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
#if __cplusplus >= 201103L
// expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}}
#else
// expected-note@-5 {{subexpression not valid in a constant expression}}
#endif
#if __cplusplus >= 201103L
ATTR int val_init{};
@ -233,15 +283,17 @@ typedef const char *StrType;
// initializer
struct NotC {
constexpr NotC(void *) {}
NotC(int) {}
NotC(int) {} // expected-note 0+ {{declared here}}
};
template <class T>
struct TestCtor {
constexpr TestCtor(int x) : value(x) {}
// expected-note@-1 {{non-constexpr constructor 'NotC' cannot be used in a constant expression}}
T value;
};
ATTR TestCtor<NotC> t(42); // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
// expected-note@-2 {{in call to 'TestCtor(42)'}}
#endif
// Test various array types
@ -261,9 +313,11 @@ struct TestCtor {
ATTR LitType non_const_lit(nullptr); // expected-error {{variable does not have a constant initializer}}
// expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
// expected-note@-2 {{non-constexpr constructor 'LitType' cannot be used in a constant expression}}
ATTR NonLit non_const(nullptr); // expected-error {{variable does not have a constant initializer}}
// expected-warning@-1 {{declaration requires a global destructor}}
// expected-note@-2 {{required by 'require_constant_initialization' attribute here}}
// expected-note@-3 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}}
LitType const_init_lit(nullptr); // expected-warning {{declaration requires a global constructor}}
NonLit const_init{42}; // expected-warning {{declaration requires a global destructor}}
constexpr TestCtor<NotC> inval_constexpr(42); // expected-error {{must be initialized by a constant expression}}

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++14 -fcoroutines-ts -fsyntax-only -Wignored-qualifiers -Wno-error=return-type -verify -fblocks -Wno-unreachable-code -Wno-unused-value
// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++14 -fcoroutines-ts -fsyntax-only -Wignored-qualifiers -Wno-error=return-type -verify -fblocks -Wall -Wextra -Wno-error=unreachable-code
#include "Inputs/std-coroutine.h"
using std::experimental::suspend_always;

View File

@ -0,0 +1,44 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++14 -fcoroutines-ts -fsyntax-only -Wall -Wextra -Wuninitialized -fblocks
#include "Inputs/std-coroutine.h"
using namespace std::experimental;
struct A {
bool await_ready() { return true; }
int await_resume() { return 42; }
template <typename F>
void await_suspend(F) {}
};
struct coro_t {
struct promise_type {
coro_t get_return_object() { return {}; }
suspend_never initial_suspend() { return {}; }
suspend_never final_suspend() { return {}; }
A yield_value(int) { return {}; }
void return_void() {}
static void unhandled_exception() {}
};
};
coro_t f(int n) {
if (n == 0)
co_return;
co_yield 42;
int x = co_await A{};
}
template <class Await>
coro_t g(int n) {
if (n == 0)
co_return;
co_yield 42;
int x = co_await Await{};
}
int main() {
f(0);
g<A>(0);
}

View File

@ -840,12 +840,12 @@ coro<bad_promise_no_return_func> no_return_value_or_return_void() {
struct bad_await_suspend_return {
bool await_ready();
// expected-error@+1 {{the return type of 'await_suspend' is required to be 'void' or 'bool' (have 'char')}}
// expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'char')}}
char await_suspend(std::experimental::coroutine_handle<>);
void await_resume();
};
struct bad_await_ready_return {
// expected-note@+1 {{the return type of 'await_ready' is required to be contextually convertible to 'bool'}}
// expected-note@+1 {{return type of 'await_ready' is required to be contextually convertible to 'bool'}}
void await_ready();
bool await_suspend(std::experimental::coroutine_handle<>);
void await_resume();
@ -858,6 +858,14 @@ struct await_ready_explicit_bool {
void await_suspend(std::experimental::coroutine_handle<>);
void await_resume();
};
template <class SuspendTy>
struct await_suspend_type_test {
bool await_ready();
// expected-error@+2 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'bool &')}}
// expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'bool &&')}}
SuspendTy await_suspend(std::experimental::coroutine_handle<>);
void await_resume();
};
void test_bad_suspend() {
{
// FIXME: The actual error emitted here is terrible, and no number of notes can save it.
@ -873,4 +881,14 @@ void test_bad_suspend() {
await_ready_explicit_bool c;
co_await c; // OK
}
{
await_suspend_type_test<bool &&> a;
await_suspend_type_test<bool &> b;
await_suspend_type_test<const void> c;
await_suspend_type_test<const volatile bool> d;
co_await a; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}}
co_await b; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}}
co_await c; // OK
co_await d; // OK
}
}

View File

@ -252,6 +252,11 @@ void is_pod()
{ int arr[F(__is_pod(void))]; }
{ int arr[F(__is_pod(cvoid))]; }
// { int arr[F(__is_pod(NonPODUnion))]; }
{ int arr[T(__is_pod(ACompleteType))]; }
{ int arr[F(__is_pod(AnIncompleteType))]; } // expected-error {{incomplete type}}
{ int arr[F(__is_pod(AnIncompleteType[]))]; } // expected-error {{incomplete type}}
{ int arr[F(__is_pod(AnIncompleteType[1]))]; } // expected-error {{incomplete type}}
}
typedef Empty EmptyAr[10];
@ -287,6 +292,11 @@ void is_empty()
{ int arr[F(__is_empty(IntArNB))]; }
{ int arr[F(__is_empty(HasAnonymousUnion))]; }
// { int arr[F(__is_empty(DerivesVirt))]; }
{ int arr[T(__is_empty(ACompleteType))]; }
{ int arr[F(__is_empty(AnIncompleteType))]; } // expected-error {{incomplete type}}
{ int arr[F(__is_empty(AnIncompleteType[]))]; }
{ int arr[F(__is_empty(AnIncompleteType[1]))]; }
}
typedef Derives ClassType;
@ -511,6 +521,8 @@ void is_aggregate()
constexpr bool TrueAfterCpp14 = __cplusplus > 201402L;
__is_aggregate(AnIncompleteType); // expected-error {{incomplete type}}
__is_aggregate(AnIncompleteType[]); // expected-error {{incomplete type}}
__is_aggregate(AnIncompleteType[1]); // expected-error {{incomplete type}}
__is_aggregate(AnIncompleteTypeAr); // expected-error {{incomplete type}}
__is_aggregate(AnIncompleteTypeArNB); // expected-error {{incomplete type}}
__is_aggregate(AnIncompleteTypeArMB); // expected-error {{incomplete type}}
@ -1220,6 +1232,13 @@ void is_trivial2()
int t32[F(__is_trivial(SuperNonTrivialStruct))];
int t33[F(__is_trivial(NonTCStruct))];
int t34[F(__is_trivial(ExtDefaulted))];
int t40[T(__is_trivial(ACompleteType))];
int t41[F(__is_trivial(AnIncompleteType))]; // expected-error {{incomplete type}}
int t42[F(__is_trivial(AnIncompleteType[]))]; // expected-error {{incomplete type}}
int t43[F(__is_trivial(AnIncompleteType[1]))]; // expected-error {{incomplete type}}
int t44[F(__is_trivial(void))];
int t45[F(__is_trivial(const volatile void))];
}
void is_trivially_copyable2()
@ -1257,6 +1276,13 @@ void is_trivially_copyable2()
int t34[T(__is_trivially_copyable(const int))];
int t35[T(__is_trivially_copyable(volatile int))];
int t40[T(__is_trivially_copyable(ACompleteType))];
int t41[F(__is_trivially_copyable(AnIncompleteType))]; // expected-error {{incomplete type}}
int t42[F(__is_trivially_copyable(AnIncompleteType[]))]; // expected-error {{incomplete type}}
int t43[F(__is_trivially_copyable(AnIncompleteType[1]))]; // expected-error {{incomplete type}}
int t44[F(__is_trivially_copyable(void))];
int t45[F(__is_trivially_copyable(const volatile void))];
}
struct CStruct {
@ -1320,6 +1346,13 @@ void is_standard_layout()
int t15[F(__is_standard_layout(CppStructNonStandardByBaseAr))];
int t16[F(__is_standard_layout(CppStructNonStandardBySameBase))];
int t17[F(__is_standard_layout(CppStructNonStandardBy2ndVirtBase))];
int t40[T(__is_standard_layout(ACompleteType))];
int t41[F(__is_standard_layout(AnIncompleteType))]; // expected-error {{incomplete type}}
int t42[F(__is_standard_layout(AnIncompleteType[]))]; // expected-error {{incomplete type}}
int t43[F(__is_standard_layout(AnIncompleteType[1]))]; // expected-error {{incomplete type}}
int t44[F(__is_standard_layout(void))];
int t45[F(__is_standard_layout(const volatile void))];
}
void is_signed()
@ -2133,6 +2166,13 @@ void trivial_checks()
TrivialMoveButNotCopy)))]; }
{ int arr[T((__is_assignable(TrivialMoveButNotCopy &,
TrivialMoveButNotCopy &&)))]; }
{ int arr[T(__is_assignable(ACompleteType, ACompleteType))]; }
{ int arr[F(__is_assignable(AnIncompleteType, AnIncompleteType))]; } // expected-error {{incomplete type}}
{ int arr[F(__is_assignable(AnIncompleteType[], AnIncompleteType[]))]; }
{ int arr[F(__is_assignable(AnIncompleteType[1], AnIncompleteType[1]))]; } // expected-error {{incomplete type}}
{ int arr[F(__is_assignable(void, void))]; }
{ int arr[F(__is_assignable(const volatile void, const volatile void))]; }
}
void constructible_checks() {
@ -2164,6 +2204,19 @@ void constructible_checks() {
// PR25513
{ int arr[F(__is_constructible(int(int)))]; }
{ int arr[T(__is_constructible(ACompleteType))]; }
{ int arr[T(__is_nothrow_constructible(ACompleteType))]; }
{ int arr[F(__is_constructible(AnIncompleteType))]; } // expected-error {{incomplete type}}
{ int arr[F(__is_nothrow_constructible(AnIncompleteType))]; } // expected-error {{incomplete type}}
{ int arr[F(__is_constructible(AnIncompleteType[]))]; }
{ int arr[F(__is_nothrow_constructible(AnIncompleteType[]))]; }
{ int arr[F(__is_constructible(AnIncompleteType[1]))]; } // expected-error {{incomplete type}}
{ int arr[F(__is_nothrow_constructible(AnIncompleteType[1]))]; } // expected-error {{incomplete type}}
{ int arr[F(__is_constructible(void))]; }
{ int arr[F(__is_nothrow_constructible(void))]; }
{ int arr[F(__is_constructible(const volatile void))]; }
{ int arr[F(__is_nothrow_constructible(const volatile void))]; }
}
// Instantiation of __is_trivially_constructible
@ -2192,6 +2245,13 @@ void is_trivially_constructible_test() {
{ int arr[F((is_trivially_constructible<NonTrivialDefault>::value))]; }
{ int arr[F((is_trivially_constructible<ThreeArgCtor, int*, char*, int&>::value))]; }
{ int arr[F((is_trivially_constructible<Abstract>::value))]; } // PR19178
{ int arr[T(__is_trivially_constructible(ACompleteType))]; }
{ int arr[F(__is_trivially_constructible(AnIncompleteType))]; } // expected-error {{incomplete type}}
{ int arr[F(__is_trivially_constructible(AnIncompleteType[]))]; }
{ int arr[F(__is_trivially_constructible(AnIncompleteType[1]))]; } // expected-error {{incomplete type}}
{ int arr[F(__is_trivially_constructible(void))]; }
{ int arr[F(__is_trivially_constructible(const volatile void))]; }
}
void array_rank() {
@ -2218,6 +2278,13 @@ void is_destructible_test() {
{ int arr[F(__is_destructible(AllDeleted))]; }
{ int arr[T(__is_destructible(ThrowingDtor))]; }
{ int arr[T(__is_destructible(NoThrowDtor))]; }
{ int arr[T(__is_destructible(ACompleteType))]; }
{ int arr[F(__is_destructible(AnIncompleteType))]; } // expected-error {{incomplete type}}
{ int arr[F(__is_destructible(AnIncompleteType[]))]; }
{ int arr[F(__is_destructible(AnIncompleteType[1]))]; } // expected-error {{incomplete type}}
{ int arr[F(__is_destructible(void))]; }
{ int arr[F(__is_destructible(const volatile void))]; }
}
void is_nothrow_destructible_test() {
@ -2234,4 +2301,33 @@ void is_nothrow_destructible_test() {
{ int arr[F(__is_nothrow_destructible(ThrowingDtor))]; }
{ int arr[T(__is_nothrow_destructible(NoExceptDtor))]; }
{ int arr[T(__is_nothrow_destructible(NoThrowDtor))]; }
{ int arr[T(__is_nothrow_destructible(ACompleteType))]; }
{ int arr[F(__is_nothrow_destructible(AnIncompleteType))]; } // expected-error {{incomplete type}}
{ int arr[F(__is_nothrow_destructible(AnIncompleteType[]))]; }
{ int arr[F(__is_nothrow_destructible(AnIncompleteType[1]))]; } // expected-error {{incomplete type}}
{ int arr[F(__is_nothrow_destructible(void))]; }
{ int arr[F(__is_nothrow_destructible(const volatile void))]; }
}
void is_trivially_destructible_test() {
{ int arr[T(__is_trivially_destructible(int))]; }
{ int arr[T(__is_trivially_destructible(int[2]))]; }
{ int arr[F(__is_trivially_destructible(int[]))]; }
{ int arr[F(__is_trivially_destructible(void))]; }
{ int arr[T(__is_trivially_destructible(int &))]; }
{ int arr[F(__is_trivially_destructible(HasDest))]; }
{ int arr[F(__is_trivially_destructible(AllPrivate))]; }
{ int arr[F(__is_trivially_destructible(SuperNonTrivialStruct))]; }
{ int arr[T(__is_trivially_destructible(AllDefaulted))]; }
{ int arr[F(__is_trivially_destructible(AllDeleted))]; }
{ int arr[F(__is_trivially_destructible(ThrowingDtor))]; }
{ int arr[F(__is_trivially_destructible(NoThrowDtor))]; }
{ int arr[T(__is_trivially_destructible(ACompleteType))]; }
{ int arr[F(__is_trivially_destructible(AnIncompleteType))]; } // expected-error {{incomplete type}}
{ int arr[F(__is_trivially_destructible(AnIncompleteType[]))]; }
{ int arr[F(__is_trivially_destructible(AnIncompleteType[1]))]; } // expected-error {{incomplete type}}
{ int arr[F(__is_trivially_destructible(void))]; }
{ int arr[F(__is_trivially_destructible(const volatile void))]; }
}

View File

@ -83,7 +83,7 @@ int t5() {
}
__attribute ((deprecated)) // expected-note 2 {{'DEPRECATED' has been explicitly marked deprecated here}}
__attribute ((deprecated)) // expected-note {{'DEPRECATED' has been explicitly marked deprecated here}}
@interface DEPRECATED {
@public int ivar;
DEPRECATED *ivar2; // no warning.
@ -98,9 +98,17 @@ __attribute ((deprecated)) // expected-note 2 {{'DEPRECATED' has been explicitly
@end
@interface DEPRECATED (Category2) // no warning.
- (id)meth;
@end
@implementation DEPRECATED (Category2) // expected-warning {{'DEPRECATED' is deprecated}}
__attribute__((deprecated))
void depr_function();
@implementation DEPRECATED (Category2) // no warning
- (id)meth {
depr_function(); // no warning.
return 0;
}
@end
@interface NS : DEPRECATED // expected-warning {{'DEPRECATED' is deprecated}}

View File

@ -2,7 +2,7 @@
// rdar://9092208
__attribute__((unavailable("not available")))
@interface MyClass { // expected-note 8 {{'MyClass' has been explicitly marked unavailable here}}
@interface MyClass { // expected-note 7 {{'MyClass' has been explicitly marked unavailable here}}
@public
void *_test;
MyClass *ivar; // no error.
@ -28,7 +28,7 @@ __attribute__((unavailable("not available")))
@interface MyClass (Cat2) // no error.
@end
@implementation MyClass (Cat2) // expected-error {{unavailable}}
@implementation MyClass (Cat2) // no error.
@end
int main() {

View File

@ -28,15 +28,14 @@
- (void) G {} // No warning, implementing its own deprecated method
@end
__attribute__((deprecated)) // expected-note 2 {{'CL' has been explicitly marked deprecated here}}
__attribute__((deprecated)) // expected-note {{'CL' has been explicitly marked deprecated here}}
@interface CL // expected-note 2 {{class declared here}}
@end
@implementation CL // expected-warning {{Implementing deprecated class}}
@end
@implementation CL ( SomeCategory ) // expected-warning {{'CL' is deprecated}} \
// expected-warning {{Implementing deprecated category}}
@implementation CL (SomeCategory) // expected-warning {{Implementing deprecated category}}
@end
@interface CL_SUB : CL // expected-warning {{'CL' is deprecated}}

View File

@ -474,9 +474,8 @@ TEST_F(FormatTestJS, FormatsFreestandingFunctions) {
"(function f() {\n"
" var x = 1;\n"
"}());\n");
// Known issue: this should wrap after {}, but calculateBraceTypes
// misclassifies the first braces as a BK_BracedInit.
verifyFormat("function aFunction(){} {\n"
verifyFormat("function aFunction() {}\n"
"{\n"
" let x = 1;\n"
" console.log(x);\n"
"}\n");
@ -1233,6 +1232,10 @@ TEST_F(FormatTestJS, ClassDeclarations) {
verifyFormat("class C {\n x: string = 12;\n}");
verifyFormat("class C {\n x(): string => 12;\n}");
verifyFormat("class C {\n ['x' + 2]: string = 12;\n}");
verifyFormat("class C {\n"
" foo() {}\n"
" [bar]() {}\n"
"}\n");
verifyFormat("class C {\n private x: string = 12;\n}");
verifyFormat("class C {\n private static x: string = 12;\n}");
verifyFormat("class C {\n static x(): string {\n return 'asd';\n }\n}");

View File

@ -718,9 +718,9 @@ namespace {
};
// Unique the enums, but maintain the original declaration ordering.
std::vector<std::string>
uniqueEnumsInOrder(const std::vector<std::string> &enums) {
std::vector<std::string> uniques;
std::vector<StringRef>
uniqueEnumsInOrder(const std::vector<StringRef> &enums) {
std::vector<StringRef> uniques;
SmallDenseSet<StringRef, 8> unique_set;
for (const auto &i : enums) {
if (unique_set.insert(i).second)
@ -731,7 +731,8 @@ namespace {
class EnumArgument : public Argument {
std::string type;
std::vector<std::string> values, enums, uniques;
std::vector<StringRef> values, enums, uniques;
public:
EnumArgument(const Record &Arg, StringRef Attr)
: Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
@ -850,7 +851,7 @@ namespace {
class VariadicEnumArgument: public VariadicArgument {
std::string type, QualifiedTypeName;
std::vector<std::string> values, enums, uniques;
std::vector<StringRef> values, enums, uniques;
protected:
void writeValueImpl(raw_ostream &OS) const override {
@ -1591,8 +1592,9 @@ struct AttributeSubjectMatchRule {
}
std::string getEnumValueName() const {
std::string Result =
"SubjectMatchRule_" + MetaSubject->getValueAsString("Name");
SmallString<128> Result;
Result += "SubjectMatchRule_";
Result += MetaSubject->getValueAsString("Name");
if (isSubRule()) {
Result += "_";
if (isNegatedSubRule())
@ -1601,7 +1603,7 @@ struct AttributeSubjectMatchRule {
}
if (isAbstractRule())
Result += "_abstract";
return Result;
return Result.str();
}
std::string getEnumValue() const { return "attr::" + getEnumValueName(); }
@ -2603,7 +2605,7 @@ void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
// append a unique suffix to distinguish this set of target checks from other
// TargetSpecificAttr records.
static void GenerateTargetSpecificAttrChecks(const Record *R,
std::vector<std::string> &Arches,
std::vector<StringRef> &Arches,
std::string &Test,
std::string *FnName) {
// It is assumed that there will be an llvm::Triple object
@ -2613,8 +2615,9 @@ static void GenerateTargetSpecificAttrChecks(const Record *R,
Test += "(";
for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) {
std::string Part = *I;
Test += "T.getArch() == llvm::Triple::" + Part;
StringRef Part = *I;
Test += "T.getArch() == llvm::Triple::";
Test += Part;
if (I + 1 != E)
Test += " || ";
if (FnName)
@ -2627,11 +2630,12 @@ static void GenerateTargetSpecificAttrChecks(const Record *R,
// We know that there was at least one arch test, so we need to and in the
// OS tests.
Test += " && (";
std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
std::vector<StringRef> OSes = R->getValueAsListOfStrings("OSes");
for (auto I = OSes.begin(), E = OSes.end(); I != E; ++I) {
std::string Part = *I;
StringRef Part = *I;
Test += "T.getOS() == llvm::Triple::" + Part;
Test += "T.getOS() == llvm::Triple::";
Test += Part;
if (I + 1 != E)
Test += " || ";
if (FnName)
@ -2643,10 +2647,11 @@ static void GenerateTargetSpecificAttrChecks(const Record *R,
// If one or more CXX ABIs are specified, check those as well.
if (!R->isValueUnset("CXXABIs")) {
Test += " && (";
std::vector<std::string> CXXABIs = R->getValueAsListOfStrings("CXXABIs");
std::vector<StringRef> CXXABIs = R->getValueAsListOfStrings("CXXABIs");
for (auto I = CXXABIs.begin(), E = CXXABIs.end(); I != E; ++I) {
std::string Part = *I;
Test += "Target.getCXXABI().getKind() == TargetCXXABI::" + Part;
StringRef Part = *I;
Test += "Target.getCXXABI().getKind() == TargetCXXABI::";
Test += Part;
if (I + 1 != E)
Test += " || ";
if (FnName)
@ -2684,7 +2689,7 @@ static void GenerateHasAttrSpellingStringSwitch(
std::string Test;
if (Attr->isSubClassOf("TargetSpecificAttr")) {
const Record *R = Attr->getValueAsDef("Target");
std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
std::vector<StringRef> Arches = R->getValueAsListOfStrings("Arches");
GenerateTargetSpecificAttrChecks(R, Arches, Test, nullptr);
// If this is the C++11 variety, also add in the LangOpts test.
@ -3323,7 +3328,7 @@ static std::string GenerateTargetRequirements(const Record &Attr,
// Get the list of architectures to be tested for.
const Record *R = Attr.getValueAsDef("Target");
std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
std::vector<StringRef> Arches = R->getValueAsListOfStrings("Arches");
if (Arches.empty()) {
PrintError(Attr.getLoc(), "Empty list of target architectures for a "
"target-specific attr");
@ -3340,9 +3345,10 @@ static std::string GenerateTargetRequirements(const Record &Attr,
std::string APK = Attr.getValueAsString("ParseKind");
for (const auto &I : Dupes) {
if (I.first == APK) {
std::vector<std::string> DA = I.second->getValueAsDef("Target")
->getValueAsListOfStrings("Arches");
std::move(DA.begin(), DA.end(), std::back_inserter(Arches));
std::vector<StringRef> DA =
I.second->getValueAsDef("Target")->getValueAsListOfStrings(
"Arches");
Arches.insert(Arches.end(), DA.begin(), DA.end());
}
}
}

View File

@ -1277,8 +1277,8 @@ void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS) {
bool IsSynonym = GroupInfo.DiagsInGroup.empty() &&
GroupInfo.SubGroups.size() == 1;
writeHeader((IsRemarkGroup ? "-R" : "-W") +
G->getValueAsString("GroupName"),
writeHeader(((IsRemarkGroup ? "-R" : "-W") +
G->getValueAsString("GroupName")).str(),
OS);
if (!IsSynonym) {

View File

@ -83,7 +83,7 @@ Documentation extractDocumentation(RecordKeeper &Records) {
}
// Pretend no-X and Xno-Y options are aliases of X and XY.
auto Name = R->getValueAsString("Name");
std::string Name = R->getValueAsString("Name");
if (Name.size() >= 4) {
if (Name.substr(0, 3) == "no-" && OptionsByName[Name.substr(3)]) {
Aliases[OptionsByName[Name.substr(3)]].push_back(R);
@ -229,7 +229,7 @@ std::string getRSTStringWithTextFallback(const Record *R, StringRef Primary,
}
void emitOptionWithArgs(StringRef Prefix, const Record *Option,
ArrayRef<std::string> Args, raw_ostream &OS) {
ArrayRef<StringRef> Args, raw_ostream &OS) {
OS << Prefix << escapeRST(Option->getValueAsString("Name"));
std::pair<StringRef, StringRef> Separators =
@ -261,14 +261,15 @@ void emitOptionName(StringRef Prefix, const Record *Option, raw_ostream &OS) {
}
}
emitOptionWithArgs(Prefix, Option, Args, OS);
emitOptionWithArgs(Prefix, Option, std::vector<StringRef>(Args.begin(), Args.end()), OS);
auto AliasArgs = Option->getValueAsListOfStrings("AliasArgs");
if (!AliasArgs.empty()) {
Record *Alias = Option->getValueAsDef("Alias");
OS << " (equivalent to ";
emitOptionWithArgs(Alias->getValueAsListOfStrings("Prefixes").front(),
Alias, Option->getValueAsListOfStrings("AliasArgs"), OS);
emitOptionWithArgs(
Alias->getValueAsListOfStrings("Prefixes").front(), Alias,
AliasArgs, OS);
OS << ")";
}
}
@ -310,7 +311,7 @@ void emitOption(const DocumentedOption &Option, const Record *DocInfo,
forEachOptionName(Option, DocInfo, [&](const Record *Option) {
for (auto &Prefix : Option->getValueAsListOfStrings("Prefixes"))
SphinxOptionIDs.push_back(
getSphinxOptionID(Prefix + Option->getValueAsString("Name")));
getSphinxOptionID((Prefix + Option->getValueAsString("Name")).str()));
});
assert(!SphinxOptionIDs.empty() && "no flags for option");
static std::map<std::string, int> NextSuffix;

View File

@ -51,7 +51,8 @@ static std::string getParentPackageFullName(const Record *R) {
static std::string getPackageFullName(const Record *R) {
std::string name = getParentPackageFullName(R);
if (!name.empty()) name += ".";
return name + R->getValueAsString("PackageName");
name += R->getValueAsString("PackageName");
return name;
}
static std::string getCheckerFullName(const Record *R) {