21 changes: 15 additions & 6 deletions clang/lib/AST/ByteCode/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2869,6 +2869,11 @@ bool Compiler<Emitter>::VisitPredefinedExpr(const PredefinedExpr *E) {
if (DiscardResult)
return true;

if (!Initializing) {
unsigned StringIndex = P.createGlobalString(E->getFunctionName(), E);
return this->emitGetPtrGlobal(StringIndex, E);
}

return this->delegate(E->getFunctionName());
}

Expand Down Expand Up @@ -6006,6 +6011,9 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {

return this->emitGetPtrParam(It->second.Offset, E);
}

if (D->getType()->isReferenceType())
return false; // FIXME: Do we need to emit InvalidDeclRef?
}

// In case we need to re-visit a declaration.
Expand Down Expand Up @@ -6042,9 +6050,7 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
const auto typeShouldBeVisited = [&](QualType T) -> bool {
if (T.isConstant(Ctx.getASTContext()))
return true;
if (const auto *RT = T->getAs<ReferenceType>())
return RT->getPointeeType().isConstQualified();
return false;
return T->isReferenceType();
};

// DecompositionDecls are just proxies for us.
Expand All @@ -6060,9 +6066,12 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
// other words, we're evaluating the initializer, just to know if we can
// evaluate the initializer.
if (VD->isLocalVarDecl() && typeShouldBeVisited(VD->getType()) &&
VD->getInit() && !VD->getInit()->isValueDependent() &&
VD->evaluateValue())
return revisit(VD);
VD->getInit() && !VD->getInit()->isValueDependent()) {

if (VD->evaluateValue())
return revisit(VD);
return this->emitInvalidDeclRef(cast<DeclRefExpr>(E), E);
}
}
} else {
if (const auto *VD = dyn_cast<VarDecl>(D);
Expand Down
73 changes: 71 additions & 2 deletions clang/lib/AST/ByteCode/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ static T getParam(const InterpFrame *Frame, unsigned Index) {
return Frame->getParam<T>(Offset);
}

// static APSInt getAPSIntParam(InterpStack &Stk, size_t Offset = 0) {
static APSInt getAPSIntParam(const InterpFrame *Frame, unsigned Index) {
APSInt R;
unsigned Offset = Frame->getFunction()->getParamOffset(Index);
Expand Down Expand Up @@ -1162,6 +1161,71 @@ static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC,
return false;
}

/// __builtin_assume_aligned(Ptr, Alignment[, ExtraOffset])
static bool interp__builtin_assume_aligned(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func,
const CallExpr *Call) {
assert(Call->getNumArgs() == 2 || Call->getNumArgs() == 3);

// Might be called with function pointers in C.
std::optional<PrimType> PtrT = S.Ctx.classify(Call->getArg(0));
if (PtrT != PT_Ptr)
return false;

unsigned ArgSize = callArgSize(S, Call);
const Pointer &Ptr = S.Stk.peek<Pointer>(ArgSize);
std::optional<APSInt> ExtraOffset;
APSInt Alignment;
if (Call->getNumArgs() == 2) {
Alignment = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(1)));
} else {
PrimType AlignmentT = *S.Ctx.classify(Call->getArg(1));
PrimType ExtraOffsetT = *S.Ctx.classify(Call->getArg(2));
Alignment = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(1)),
align(primSize(AlignmentT)) +
align(primSize(ExtraOffsetT)));
ExtraOffset = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(2)));
}

CharUnits Align = CharUnits::fromQuantity(Alignment.getZExtValue());

// If there is a base object, then it must have the correct alignment.
if (Ptr.isBlockPointer()) {
CharUnits BaseAlignment;
if (const auto *VD = Ptr.getDeclDesc()->asValueDecl())
BaseAlignment = S.getASTContext().getDeclAlign(VD);
else if (const auto *E = Ptr.getDeclDesc()->asExpr())
BaseAlignment = GetAlignOfExpr(S.getASTContext(), E, UETT_AlignOf);

if (BaseAlignment < Align) {
S.CCEDiag(Call->getArg(0),
diag::note_constexpr_baa_insufficient_alignment)
<< 0 << BaseAlignment.getQuantity() << Align.getQuantity();
return false;
}
}

APValue AV = Ptr.toAPValue(S.getASTContext());
CharUnits AVOffset = AV.getLValueOffset();
if (ExtraOffset)
AVOffset -= CharUnits::fromQuantity(ExtraOffset->getZExtValue());
if (AVOffset.alignTo(Align) != AVOffset) {
if (Ptr.isBlockPointer())
S.CCEDiag(Call->getArg(0),
diag::note_constexpr_baa_insufficient_alignment)
<< 1 << AVOffset.getQuantity() << Align.getQuantity();
else
S.CCEDiag(Call->getArg(0),
diag::note_constexpr_baa_value_insufficient_alignment)
<< AVOffset.getQuantity() << Align.getQuantity();
return false;
}

S.Stk.push<Pointer>(Ptr);
return true;
}

static bool interp__builtin_ia32_bextr(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func,
Expand Down Expand Up @@ -1287,7 +1351,7 @@ static bool interp__builtin_ia32_addcarry_subborrow(InterpState &S,
const InterpFrame *Frame,
const Function *Func,
const CallExpr *Call) {
if (!Call->getArg(0)->getType()->isIntegerType() ||
if (Call->getNumArgs() != 4 || !Call->getArg(0)->getType()->isIntegerType() ||
!Call->getArg(1)->getType()->isIntegerType() ||
!Call->getArg(2)->getType()->isIntegerType())
return false;
Expand Down Expand Up @@ -1905,6 +1969,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
return false;
break;

case Builtin::BI__builtin_assume_aligned:
if (!interp__builtin_assume_aligned(S, OpPC, Frame, F, Call))
return false;
break;

case clang::X86::BI__builtin_ia32_bextr_u32:
case clang::X86::BI__builtin_ia32_bextr_u64:
case clang::X86::BI__builtin_ia32_bextri_u32:
Expand Down
5 changes: 0 additions & 5 deletions clang/lib/AST/ByteCode/Pointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,11 +253,6 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
}
}

// FIXME(perf): We compute the lvalue path above, but we can't supply it
// for dummy pointers (that causes crashes later in CheckConstantExpression).
if (isDummy())
Path.clear();

// We assemble the LValuePath starting from the innermost pointer to the
// outermost one. SO in a.b.c, the first element in Path will refer to
// the field 'c', while later code expects it to refer to 'a'.
Expand Down
15 changes: 9 additions & 6 deletions clang/lib/AST/ByteCode/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const void *Program::getNativePointer(unsigned Idx) {
return NativePointers[Idx];
}

unsigned Program::createGlobalString(const StringLiteral *S) {
unsigned Program::createGlobalString(const StringLiteral *S, const Expr *Base) {
const size_t CharWidth = S->getCharByteWidth();
const size_t BitWidth = CharWidth * Ctx.getCharBit();

Expand All @@ -52,12 +52,15 @@ unsigned Program::createGlobalString(const StringLiteral *S) {
llvm_unreachable("unsupported character width");
}

if (!Base)
Base = S;

// Create a descriptor for the string.
Descriptor *Desc =
allocateDescriptor(S, CharType, Descriptor::GlobalMD, S->getLength() + 1,
/*isConst=*/true,
/*isTemporary=*/false,
/*isMutable=*/false);
Descriptor *Desc = allocateDescriptor(Base, CharType, Descriptor::GlobalMD,
S->getLength() + 1,
/*isConst=*/true,
/*isTemporary=*/false,
/*isMutable=*/false);

// Allocate storage for the string.
// The byte length does not include the null terminator.
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/AST/ByteCode/Program.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ class Program final {
const void *getNativePointer(unsigned Idx);

/// Emits a string literal among global data.
unsigned createGlobalString(const StringLiteral *S);
unsigned createGlobalString(const StringLiteral *S,
const Expr *Base = nullptr);

/// Returns a pointer to a global.
Pointer getPtrGlobal(unsigned Idx) const;
Expand Down
14 changes: 11 additions & 3 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1737,9 +1737,17 @@ void NamedDecl::printNestedNameSpecifier(raw_ostream &OS,
continue;

// Suppress inline namespace if it doesn't make the result ambiguous.
if (P.SuppressInlineNamespace && Ctx->isInlineNamespace() && NameInScope &&
cast<NamespaceDecl>(Ctx)->isRedundantInlineQualifierFor(NameInScope))
continue;
if (Ctx->isInlineNamespace() && NameInScope) {
bool isRedundant =
cast<NamespaceDecl>(Ctx)->isRedundantInlineQualifierFor(NameInScope);
if (P.SuppressInlineNamespace ==
PrintingPolicy::SuppressInlineNamespaceMode::All ||
(P.SuppressInlineNamespace ==
PrintingPolicy::SuppressInlineNamespaceMode::Redundant &&
isRedundant)) {
continue;
}
}

// Skip non-named contexts such as linkage specifications and ExportDecls.
const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx);
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/AST/ExprConstShared.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@
#ifndef LLVM_CLANG_LIB_AST_EXPRCONSTSHARED_H
#define LLVM_CLANG_LIB_AST_EXPRCONSTSHARED_H

#include "clang/Basic/TypeTraits.h"

namespace llvm {
class APFloat;
}
namespace clang {
class QualType;
class LangOptions;
class ASTContext;
class CharUnits;
class Expr;
} // namespace clang
using namespace clang;
/// Values returned by __builtin_classify_type, chosen to match the values
Expand Down Expand Up @@ -66,4 +71,7 @@ void HandleComplexComplexDiv(llvm::APFloat A, llvm::APFloat B, llvm::APFloat C,
llvm::APFloat D, llvm::APFloat &ResR,
llvm::APFloat &ResI);

CharUnits GetAlignOfExpr(const ASTContext &Ctx, const Expr *E,
UnaryExprOrTypeTrait ExprKind);

#endif
48 changes: 22 additions & 26 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9620,7 +9620,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) {
return ExprEvaluatorBaseTy::VisitCastExpr(E);
}

static CharUnits GetAlignOfType(EvalInfo &Info, QualType T,
static CharUnits GetAlignOfType(const ASTContext &Ctx, QualType T,
UnaryExprOrTypeTrait ExprKind) {
// C++ [expr.alignof]p3:
// When alignof is applied to a reference type, the result is the
Expand All @@ -9631,23 +9631,22 @@ static CharUnits GetAlignOfType(EvalInfo &Info, QualType T,
return CharUnits::One();

const bool AlignOfReturnsPreferred =
Info.Ctx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7;
Ctx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7;

// __alignof is defined to return the preferred alignment.
// Before 8, clang returned the preferred alignment for alignof and _Alignof
// as well.
if (ExprKind == UETT_PreferredAlignOf || AlignOfReturnsPreferred)
return Info.Ctx.toCharUnitsFromBits(
Info.Ctx.getPreferredTypeAlign(T.getTypePtr()));
return Ctx.toCharUnitsFromBits(Ctx.getPreferredTypeAlign(T.getTypePtr()));
// alignof and _Alignof are defined to return the ABI alignment.
else if (ExprKind == UETT_AlignOf)
return Info.Ctx.getTypeAlignInChars(T.getTypePtr());
return Ctx.getTypeAlignInChars(T.getTypePtr());
else
llvm_unreachable("GetAlignOfType on a non-alignment ExprKind");
}

static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E,
UnaryExprOrTypeTrait ExprKind) {
CharUnits GetAlignOfExpr(const ASTContext &Ctx, const Expr *E,
UnaryExprOrTypeTrait ExprKind) {
E = E->IgnoreParens();

// The kinds of expressions that we have special-case logic here for
Expand All @@ -9657,22 +9656,22 @@ static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E,
// alignof decl is always accepted, even if it doesn't make sense: we default
// to 1 in those cases.
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
return Info.Ctx.getDeclAlign(DRE->getDecl(),
/*RefAsPointee*/true);
return Ctx.getDeclAlign(DRE->getDecl(),
/*RefAsPointee*/ true);

if (const MemberExpr *ME = dyn_cast<MemberExpr>(E))
return Info.Ctx.getDeclAlign(ME->getMemberDecl(),
/*RefAsPointee*/true);
return Ctx.getDeclAlign(ME->getMemberDecl(),
/*RefAsPointee*/ true);

return GetAlignOfType(Info, E->getType(), ExprKind);
return GetAlignOfType(Ctx, E->getType(), ExprKind);
}

static CharUnits getBaseAlignment(EvalInfo &Info, const LValue &Value) {
if (const auto *VD = Value.Base.dyn_cast<const ValueDecl *>())
return Info.Ctx.getDeclAlign(VD);
if (const auto *E = Value.Base.dyn_cast<const Expr *>())
return GetAlignOfExpr(Info, E, UETT_AlignOf);
return GetAlignOfType(Info, Value.Base.getTypeInfoType(), UETT_AlignOf);
return GetAlignOfExpr(Info.Ctx, E, UETT_AlignOf);
return GetAlignOfType(Info.Ctx, Value.Base.getTypeInfoType(), UETT_AlignOf);
}

/// Evaluate the value of the alignment argument to __builtin_align_{up,down},
Expand Down Expand Up @@ -9768,11 +9767,8 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,

if (BaseAlignment < Align) {
Result.Designator.setInvalid();
// FIXME: Add support to Diagnostic for long / long long.
CCEDiag(E->getArg(0),
diag::note_constexpr_baa_insufficient_alignment) << 0
<< (unsigned)BaseAlignment.getQuantity()
<< (unsigned)Align.getQuantity();
CCEDiag(E->getArg(0), diag::note_constexpr_baa_insufficient_alignment)
<< 0 << BaseAlignment.getQuantity() << Align.getQuantity();
return false;
}
}
Expand All @@ -9783,11 +9779,11 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,

(OffsetResult.Base
? CCEDiag(E->getArg(0),
diag::note_constexpr_baa_insufficient_alignment) << 1
diag::note_constexpr_baa_insufficient_alignment)
<< 1
: CCEDiag(E->getArg(0),
diag::note_constexpr_baa_value_insufficient_alignment))
<< (int)OffsetResult.Offset.getQuantity()
<< (unsigned)Align.getQuantity();
<< OffsetResult.Offset.getQuantity() << Align.getQuantity();
return false;
}

Expand Down Expand Up @@ -14478,11 +14474,11 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
case UETT_PreferredAlignOf:
case UETT_AlignOf: {
if (E->isArgumentType())
return Success(GetAlignOfType(Info, E->getArgumentType(), E->getKind()),
E);
return Success(
GetAlignOfType(Info.Ctx, E->getArgumentType(), E->getKind()), E);
else
return Success(GetAlignOfExpr(Info, E->getArgumentExpr(), E->getKind()),
E);
return Success(
GetAlignOfExpr(Info.Ctx, E->getArgumentExpr(), E->getKind()), E);
}

case UETT_PtrAuthTypeDiscriminator: {
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/AST/TypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1413,7 +1413,9 @@ void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS,

// Only suppress an inline namespace if the name has the same lookup
// results in the enclosing namespace.
if (Policy.SuppressInlineNamespace && NS->isInline() && NameInScope &&
if (Policy.SuppressInlineNamespace !=
PrintingPolicy::SuppressInlineNamespaceMode::None &&
NS->isInline() && NameInScope &&
NS->isRedundantInlineQualifierFor(NameInScope))
return AppendScope(DC->getParent(), OS, NameInScope);

Expand Down
4 changes: 3 additions & 1 deletion clang/lib/ASTMatchers/ASTMatchersInternal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,9 @@ bool HasNameMatcher::matchesNodeFullSlow(const NamedDecl &Node) const {

PrintingPolicy Policy = Node.getASTContext().getPrintingPolicy();
Policy.SuppressUnwrittenScope = SkipUnwritten;
Policy.SuppressInlineNamespace = SkipUnwritten;
Policy.SuppressInlineNamespace =
SkipUnwritten ? PrintingPolicy::SuppressInlineNamespaceMode::All
: PrintingPolicy::SuppressInlineNamespaceMode::None;
Node.printQualifiedName(OS, Policy);

const StringRef FullName = OS.str();
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Basic/IdentifierTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,9 @@ ReservedLiteralSuffixIdStatus
IdentifierInfo::isReservedLiteralSuffixId() const {
StringRef Name = getName();

// Note: the diag::warn_deprecated_literal_operator_id diagnostic depends on
// this being the first check we do, so if this order changes, we have to fix
// that as well.
if (Name[0] != '_')
return ReservedLiteralSuffixIdStatus::NotStartsWithUnderscore;

Expand Down
13 changes: 7 additions & 6 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13648,7 +13648,7 @@ Value *CodeGenFunction::EmitBPFBuiltinExpr(unsigned BuiltinID,
Value *InfoKind = ConstantInt::get(Int64Ty, C->getSExtValue());

// Built the IR for the preserve_field_info intrinsic.
llvm::Function *FnGetFieldInfo = llvm::Intrinsic::getDeclaration(
llvm::Function *FnGetFieldInfo = llvm::Intrinsic::getOrInsertDeclaration(
&CGM.getModule(), llvm::Intrinsic::bpf_preserve_field_info,
{FieldAddr->getType()});
return Builder.CreateCall(FnGetFieldInfo, {FieldAddr, InfoKind});
Expand All @@ -13670,10 +13670,10 @@ Value *CodeGenFunction::EmitBPFBuiltinExpr(unsigned BuiltinID,

llvm::Function *FnDecl;
if (BuiltinID == BPF::BI__builtin_btf_type_id)
FnDecl = llvm::Intrinsic::getDeclaration(
FnDecl = llvm::Intrinsic::getOrInsertDeclaration(
&CGM.getModule(), llvm::Intrinsic::bpf_btf_type_id, {});
else
FnDecl = llvm::Intrinsic::getDeclaration(
FnDecl = llvm::Intrinsic::getOrInsertDeclaration(
&CGM.getModule(), llvm::Intrinsic::bpf_preserve_type_info, {});
CallInst *Fn = Builder.CreateCall(FnDecl, {SeqNumVal, FlagValue});
Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);
Expand Down Expand Up @@ -13708,7 +13708,7 @@ Value *CodeGenFunction::EmitBPFBuiltinExpr(unsigned BuiltinID,
Value *FlagValue = ConstantInt::get(Int64Ty, Flag->getSExtValue());
Value *SeqNumVal = ConstantInt::get(Int32Ty, BuiltinSeqNum++);

llvm::Function *IntrinsicFn = llvm::Intrinsic::getDeclaration(
llvm::Function *IntrinsicFn = llvm::Intrinsic::getOrInsertDeclaration(
&CGM.getModule(), llvm::Intrinsic::bpf_preserve_enum_value, {});
CallInst *Fn =
Builder.CreateCall(IntrinsicFn, {SeqNumVal, EnumStrVal, FlagValue});
Expand Down Expand Up @@ -18882,7 +18882,7 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
// for the DirectX intrinsic and the demangled builtin name
switch (CGM.getTarget().getTriple().getArch()) {
case llvm::Triple::dxil:
return EmitRuntimeCall(Intrinsic::getDeclaration(
return EmitRuntimeCall(Intrinsic::getOrInsertDeclaration(
&CGM.getModule(), Intrinsic::dx_wave_getlaneindex));
case llvm::Triple::spirv:
return EmitRuntimeCall(CGM.CreateRuntimeFunction(
Expand All @@ -18895,7 +18895,8 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
}
case Builtin::BI__builtin_hlsl_wave_is_first_lane: {
Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveIsFirstLaneIntrinsic();
return EmitRuntimeCall(Intrinsic::getDeclaration(&CGM.getModule(), ID));
return EmitRuntimeCall(
Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID));
}
case Builtin::BI__builtin_hlsl_elementwise_sign: {
auto *Arg0 = E->getArg(0);
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,8 @@ PrintingPolicy CGDebugInfo::getPrintingPolicy() const {
PP.SplitTemplateClosers = true;
}

PP.SuppressInlineNamespace = false;
PP.SuppressInlineNamespace =
PrintingPolicy::SuppressInlineNamespaceMode::None;
PP.PrintCanonicalTypes = true;
PP.UsePreferredNames = false;
PP.AlwaysIncludeTypeForTemplateArgument = true;
Expand Down
8 changes: 4 additions & 4 deletions clang/lib/CodeGen/CGDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2509,17 +2509,17 @@ void CodeGenFunction::pushRegularPartialArrayCleanup(llvm::Value *arrayBegin,
llvm::Function *CodeGenModule::getLLVMLifetimeStartFn() {
if (LifetimeStartFn)
return LifetimeStartFn;
LifetimeStartFn = llvm::Intrinsic::getDeclaration(&getModule(),
llvm::Intrinsic::lifetime_start, AllocaInt8PtrTy);
LifetimeStartFn = llvm::Intrinsic::getOrInsertDeclaration(
&getModule(), llvm::Intrinsic::lifetime_start, AllocaInt8PtrTy);
return LifetimeStartFn;
}

/// Lazily declare the @llvm.lifetime.end intrinsic.
llvm::Function *CodeGenModule::getLLVMLifetimeEndFn() {
if (LifetimeEndFn)
return LifetimeEndFn;
LifetimeEndFn = llvm::Intrinsic::getDeclaration(&getModule(),
llvm::Intrinsic::lifetime_end, AllocaInt8PtrTy);
LifetimeEndFn = llvm::Intrinsic::getOrInsertDeclaration(
&getModule(), llvm::Intrinsic::lifetime_end, AllocaInt8PtrTy);
return LifetimeEndFn;
}

Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CGException.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1843,7 +1843,7 @@ Address CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF,
std::make_pair(ParentAlloca, ParentCGF.EscapedLocals.size()));
int FrameEscapeIdx = InsertPair.first->second;
// call ptr @llvm.localrecover(ptr @parentFn, ptr %fp, i32 N)
llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration(
llvm::Function *FrameRecoverFn = llvm::Intrinsic::getOrInsertDeclaration(
&CGM.getModule(), llvm::Intrinsic::localrecover);
RecoverCall = Builder.CreateCall(
FrameRecoverFn, {ParentCGF.CurFn, ParentFP,
Expand Down Expand Up @@ -1942,7 +1942,7 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF,
// %1 = call ptr @llvm.localrecover(@"?fin$0@0@main@@",..)
// %2 = load ptr, ptr %1, align 8
// ==> %2 is the frame-pointer of outermost host function
llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration(
llvm::Function *FrameRecoverFn = llvm::Intrinsic::getOrInsertDeclaration(
&CGM.getModule(), llvm::Intrinsic::localrecover);
ParentFP = Builder.CreateCall(
FrameRecoverFn, {ParentCGF.CurFn, ParentFP,
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
EscapeArgs.resize(EscapedLocals.size());
for (auto &Pair : EscapedLocals)
EscapeArgs[Pair.second] = Pair.first;
llvm::Function *FrameEscapeFn = llvm::Intrinsic::getDeclaration(
llvm::Function *FrameEscapeFn = llvm::Intrinsic::getOrInsertDeclaration(
&CGM.getModule(), llvm::Intrinsic::localescape);
CGBuilderTy(*this, AllocaInsertPt).CreateCall(FrameEscapeFn, EscapeArgs);
}
Expand Down Expand Up @@ -3130,7 +3130,7 @@ void CodeGenFunction::emitAlignmentAssumptionCheck(
llvm::Instruction *Assumption) {
assert(isa_and_nonnull<llvm::CallInst>(Assumption) &&
cast<llvm::CallInst>(Assumption)->getCalledOperand() ==
llvm::Intrinsic::getDeclaration(
llvm::Intrinsic::getOrInsertDeclaration(
Builder.GetInsertBlock()->getParent()->getParent(),
llvm::Intrinsic::assume) &&
"Assumption should be a call to llvm.assume().");
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6218,8 +6218,8 @@ void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {

llvm::Function *CodeGenModule::getIntrinsic(unsigned IID,
ArrayRef<llvm::Type*> Tys) {
return llvm::Intrinsic::getDeclaration(&getModule(), (llvm::Intrinsic::ID)IID,
Tys);
return llvm::Intrinsic::getOrInsertDeclaration(&getModule(),
(llvm::Intrinsic::ID)IID, Tys);
}

static llvm::StringMapEntry<llvm::GlobalVariable *> &
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CodeGenTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ void CodeGenTypes::addRecordTypeName(const RecordDecl *RD,
// example, we should probably enable PrintCanonicalTypes and
// FullyQualifiedNames.
PrintingPolicy Policy = RD->getASTContext().getPrintingPolicy();
Policy.SuppressInlineNamespace = false;
Policy.SuppressInlineNamespace =
PrintingPolicy::SuppressInlineNamespaceMode::None;

// Name the codegen type after the typedef name
// if there is no tag type name available
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/Targets/SystemZ.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
if (Ty->isFloatTy() || Ty->isDoubleTy() || Ty->isFP128Ty()) {
llvm::Module &M = CGM.getModule();
auto &Ctx = M.getContext();
llvm::Function *TDCFunc =
llvm::Intrinsic::getDeclaration(&M, llvm::Intrinsic::s390_tdc, Ty);
llvm::Function *TDCFunc = llvm::Intrinsic::getOrInsertDeclaration(
&M, llvm::Intrinsic::s390_tdc, Ty);
unsigned TDCBits = 0;
switch (BuiltinID) {
case Builtin::BI__builtin_isnan:
Expand Down
2 changes: 0 additions & 2 deletions clang/lib/Frontend/FrontendActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -457,8 +457,6 @@ class DefaultTemplateInstCallback : public TemplateInstantiationCallback {
return "BuildingDeductionGuides";
case CodeSynthesisContext::TypeAliasTemplateInstantiation:
return "TypeAliasTemplateInstantiation";
case CodeSynthesisContext::PartialOrderingTTP:
return "PartialOrderingTTP";
}
return "";
}
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Lex/Preprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -902,6 +902,10 @@ void Preprocessor::Lex(Token &Result) {
case tok::r_brace:
StdCXXImportSeqState.handleCloseBrace();
break;
#define PRAGMA_ANNOTATION(X) case tok::annot_##X:
// For `#pragma ...` mimic ';'.
#include "clang/Basic/TokenKinds.def"
#undef PRAGMA_ANNOTATION
// This token is injected to represent the translation of '#include "a.h"'
// into "import a.h;". Mimic the notional ';'.
case tok::annot_module_include:
Expand Down
28 changes: 17 additions & 11 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -503,17 +503,23 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
const IdentifierInfo *II = Name.Identifier;
ReservedIdentifierStatus Status = II->isReserved(PP.getLangOpts());
SourceLocation Loc = Name.getEndLoc();
if (!PP.getSourceManager().isInSystemHeader(Loc)) {
if (auto Hint = FixItHint::CreateReplacement(
Name.getSourceRange(),
(StringRef("operator\"\"") + II->getName()).str());
isReservedInAllContexts(Status)) {
Diag(Loc, diag::warn_reserved_extern_symbol)
<< II << static_cast<int>(Status) << Hint;
} else {
Diag(Loc, diag::warn_deprecated_literal_operator_id) << II << Hint;
}
}

auto Hint = FixItHint::CreateReplacement(
Name.getSourceRange(),
(StringRef("operator\"\"") + II->getName()).str());

// Only emit this diagnostic if we start with an underscore, else the
// diagnostic for C++11 requiring a space between the quotes and the
// identifier conflicts with this and gets confusing. The diagnostic stating
// this is a reserved name should force the underscore, which gets this
// back.
if (II->isReservedLiteralSuffixId() !=
ReservedLiteralSuffixIdStatus::NotStartsWithUnderscore)
Diag(Loc, diag::warn_deprecated_literal_operator_id) << II << Hint;

if (isReservedInAllContexts(Status))
Diag(Loc, diag::warn_reserved_extern_symbol)
<< II << static_cast<int>(Status) << Hint;
}

if (!SS.isValid())
Expand Down
4 changes: 1 addition & 3 deletions clang/lib/Sema/SemaLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3666,9 +3666,7 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
TemplateArgumentLoc Arg(TemplateArgument(StringLit), StringLit);
if (CheckTemplateArgument(
Params->getParam(0), Arg, FD, R.getNameLoc(), R.getNameLoc(),
0, SugaredChecked, CanonicalChecked, CTAK_Specified,
/*PartialOrdering=*/false,
/*MatchedPackOnParmToNonPackOnArg=*/nullptr) ||
0, SugaredChecked, CanonicalChecked, CTAK_Specified) ||
Trap.hasErrorOccurred())
IsTemplate = false;
}
Expand Down
50 changes: 18 additions & 32 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6864,8 +6864,7 @@ void Sema::AddOverloadCandidate(
OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
bool PartialOverloading, bool AllowExplicit, bool AllowExplicitConversions,
ADLCallKind IsADLCandidate, ConversionSequenceList EarlyConversions,
OverloadCandidateParamOrder PO, bool AggregateCandidateDeduction,
bool HasMatchedPackOnParmToNonPackOnArg) {
OverloadCandidateParamOrder PO, bool AggregateCandidateDeduction) {
const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>());
assert(Proto && "Functions without a prototype cannot be overloaded");
Expand All @@ -6884,8 +6883,7 @@ void Sema::AddOverloadCandidate(
AddMethodCandidate(Method, FoundDecl, Method->getParent(), QualType(),
Expr::Classification::makeSimpleLValue(), Args,
CandidateSet, SuppressUserConversions,
PartialOverloading, EarlyConversions, PO,
HasMatchedPackOnParmToNonPackOnArg);
PartialOverloading, EarlyConversions, PO);
return;
}
// We treat a constructor like a non-member function, since its object
Expand Down Expand Up @@ -6928,8 +6926,6 @@ void Sema::AddOverloadCandidate(
CandidateSet.getRewriteInfo().getRewriteKind(Function, PO);
Candidate.IsADLCandidate = IsADLCandidate;
Candidate.ExplicitCallArguments = Args.size();
Candidate.HasMatchedPackOnParmToNonPackOnArg =
HasMatchedPackOnParmToNonPackOnArg;

// Explicit functions are not actually candidates at all if we're not
// allowing them in this context, but keep them around so we can point
Expand Down Expand Up @@ -7457,13 +7453,16 @@ void Sema::AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType,
}
}

void Sema::AddMethodCandidate(
CXXMethodDecl *Method, DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext, QualType ObjectType,
Expr::Classification ObjectClassification, ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
bool PartialOverloading, ConversionSequenceList EarlyConversions,
OverloadCandidateParamOrder PO, bool HasMatchedPackOnParmToNonPackOnArg) {
void
Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext, QualType ObjectType,
Expr::Classification ObjectClassification,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
bool SuppressUserConversions,
bool PartialOverloading,
ConversionSequenceList EarlyConversions,
OverloadCandidateParamOrder PO) {
const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>());
assert(Proto && "Methods without a prototype cannot be overloaded");
Expand Down Expand Up @@ -7494,8 +7493,6 @@ void Sema::AddMethodCandidate(
Candidate.TookAddressOfOverload =
CandidateSet.getKind() == OverloadCandidateSet::CSK_AddressOfOverloadSet;
Candidate.ExplicitCallArguments = Args.size();
Candidate.HasMatchedPackOnParmToNonPackOnArg =
HasMatchedPackOnParmToNonPackOnArg;

bool IgnoreExplicitObject =
(Method->isExplicitObjectMemberFunction() &&
Expand Down Expand Up @@ -7666,8 +7663,8 @@ void Sema::AddMethodTemplateCandidate(
ConversionSequenceList Conversions;
if (TemplateDeductionResult Result = DeduceTemplateArguments(
MethodTmpl, ExplicitTemplateArgs, Args, Specialization, Info,
PartialOverloading, /*AggregateDeductionCandidate=*/false,
/*PartialOrdering=*/false, ObjectType, ObjectClassification,
PartialOverloading, /*AggregateDeductionCandidate=*/false, ObjectType,
ObjectClassification,
[&](ArrayRef<QualType> ParamTypes) {
return CheckNonDependentConversions(
MethodTmpl, ParamTypes, Args, CandidateSet, Conversions,
Expand Down Expand Up @@ -7705,8 +7702,7 @@ void Sema::AddMethodTemplateCandidate(
AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl,
ActingContext, ObjectType, ObjectClassification, Args,
CandidateSet, SuppressUserConversions, PartialOverloading,
Conversions, PO,
Info.hasMatchedPackOnParmToNonPackOnArg());
Conversions, PO);
}

/// Determine whether a given function template has a simple explicit specifier
Expand Down Expand Up @@ -7752,7 +7748,6 @@ void Sema::AddTemplateOverloadCandidate(
if (TemplateDeductionResult Result = DeduceTemplateArguments(
FunctionTemplate, ExplicitTemplateArgs, Args, Specialization, Info,
PartialOverloading, AggregateCandidateDeduction,
/*PartialOrdering=*/false,
/*ObjectType=*/QualType(),
/*ObjectClassification=*/Expr::Classification(),
[&](ArrayRef<QualType> ParamTypes) {
Expand Down Expand Up @@ -7793,8 +7788,7 @@ void Sema::AddTemplateOverloadCandidate(
Specialization, FoundDecl, Args, CandidateSet, SuppressUserConversions,
PartialOverloading, AllowExplicit,
/*AllowExplicitConversions=*/false, IsADLCandidate, Conversions, PO,
Info.AggregateDeductionCandidateHasMismatchedArity,
Info.hasMatchedPackOnParmToNonPackOnArg());
Info.AggregateDeductionCandidateHasMismatchedArity);
}

bool Sema::CheckNonDependentConversions(
Expand Down Expand Up @@ -7916,8 +7910,7 @@ void Sema::AddConversionCandidate(
CXXConversionDecl *Conversion, DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext, Expr *From, QualType ToType,
OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit,
bool AllowExplicit, bool AllowResultConversion,
bool HasMatchedPackOnParmToNonPackOnArg) {
bool AllowExplicit, bool AllowResultConversion) {
assert(!Conversion->getDescribedFunctionTemplate() &&
"Conversion function templates use AddTemplateConversionCandidate");
QualType ConvType = Conversion->getConversionType().getNonReferenceType();
Expand Down Expand Up @@ -7962,8 +7955,6 @@ void Sema::AddConversionCandidate(
Candidate.FinalConversion.setAllToTypes(ToType);
Candidate.Viable = true;
Candidate.ExplicitCallArguments = 1;
Candidate.HasMatchedPackOnParmToNonPackOnArg =
HasMatchedPackOnParmToNonPackOnArg;

// Explicit functions are not actually candidates at all if we're not
// allowing them in this context, but keep them around so we can point
Expand Down Expand Up @@ -8165,8 +8156,7 @@ void Sema::AddTemplateConversionCandidate(
assert(Specialization && "Missing function template specialization?");
AddConversionCandidate(Specialization, FoundDecl, ActingDC, From, ToType,
CandidateSet, AllowObjCConversionOnExplicit,
AllowExplicit, AllowResultConversion,
Info.hasMatchedPackOnParmToNonPackOnArg());
AllowExplicit, AllowResultConversion);
}

void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
Expand Down Expand Up @@ -10519,10 +10509,6 @@ bool clang::isBetterOverloadCandidate(
isa<CXXConstructorDecl>(Cand2.Function))
return isa<CXXConstructorDecl>(Cand1.Function);

if (Cand1.HasMatchedPackOnParmToNonPackOnArg !=
Cand2.HasMatchedPackOnParmToNonPackOnArg)
return Cand2.HasMatchedPackOnParmToNonPackOnArg;

// -- F1 is a non-template function and F2 is a function template
// specialization, or, if not that,
bool Cand1IsSpecialization = Cand1.Function &&
Expand Down
133 changes: 71 additions & 62 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5179,8 +5179,7 @@ bool Sema::CheckTemplateArgument(
unsigned ArgumentPackIndex,
SmallVectorImpl<TemplateArgument> &SugaredConverted,
SmallVectorImpl<TemplateArgument> &CanonicalConverted,
CheckTemplateArgumentKind CTAK, bool PartialOrdering,
bool *MatchedPackOnParmToNonPackOnArg) {
CheckTemplateArgumentKind CTAK) {
// Check template type parameters.
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
return CheckTemplateTypeArgument(TTP, Arg, SugaredConverted,
Expand Down Expand Up @@ -5395,8 +5394,8 @@ bool Sema::CheckTemplateArgument(

case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
if (CheckTemplateTemplateArgument(TempParm, Params, Arg, PartialOrdering,
MatchedPackOnParmToNonPackOnArg))
if (CheckTemplateTemplateArgument(TempParm, Params, Arg,
/*IsDeduced=*/CTAK != CTAK_Specified))
return true;

SugaredConverted.push_back(Arg.getArgument());
Expand Down Expand Up @@ -5470,7 +5469,7 @@ bool Sema::CheckTemplateArgumentList(
SmallVectorImpl<TemplateArgument> &SugaredConverted,
SmallVectorImpl<TemplateArgument> &CanonicalConverted,
bool UpdateArgsWithConversions, bool *ConstraintsNotSatisfied,
bool PartialOrderingTTP, bool *MatchedPackOnParmToNonPackOnArg) {
bool PartialOrderingTTP) {

if (ConstraintsNotSatisfied)
*ConstraintsNotSatisfied = false;
Expand Down Expand Up @@ -5503,7 +5502,8 @@ bool Sema::CheckTemplateArgumentList(
DefaultArgs && ParamIdx >= DefaultArgs.StartPos) {
// All written arguments should have been consumed by this point.
assert(ArgIdx == NumArgs && "bad default argument deduction");
if (ParamIdx == DefaultArgs.StartPos) {
// FIXME: Don't ignore parameter packs.
if (ParamIdx == DefaultArgs.StartPos && !(*Param)->isParameterPack()) {
assert(Param + DefaultArgs.Args.size() <= ParamEnd);
// Default arguments from a DeducedTemplateName are already converted.
for (const TemplateArgument &DefArg : DefaultArgs.Args) {
Expand Down Expand Up @@ -5549,8 +5549,7 @@ bool Sema::CheckTemplateArgumentList(
if (CheckTemplateArgument(*Param, NewArgs[ArgIdx], Template, TemplateLoc,
RAngleLoc, SugaredArgumentPack.size(),
SugaredConverted, CanonicalConverted,
CTAK_Specified, /*PartialOrdering=*/false,
MatchedPackOnParmToNonPackOnArg))
CTAK_Specified))
return true;

CanonicalConverted.back().setIsDefaulted(
Expand Down Expand Up @@ -5708,8 +5707,7 @@ bool Sema::CheckTemplateArgumentList(
// Check the default template argument.
if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc, RAngleLoc, 0,
SugaredConverted, CanonicalConverted,
CTAK_Specified, /*PartialOrdering=*/false,
/*MatchedPackOnParmToNonPackOnArg=*/nullptr))
CTAK_Specified))
return true;

SugaredConverted.back().setIsDefaulted(true);
Expand All @@ -5730,9 +5728,8 @@ bool Sema::CheckTemplateArgumentList(
// pack expansions; they might be empty. This can happen even if
// PartialTemplateArgs is false (the list of arguments is complete but
// still dependent).
if (PartialOrderingTTP ||
(CurrentInstantiationScope &&
CurrentInstantiationScope->getPartiallySubstitutedPack())) {
if (ArgIdx < NumArgs && CurrentInstantiationScope &&
CurrentInstantiationScope->getPartiallySubstitutedPack()) {
while (ArgIdx < NumArgs &&
NewArgs[ArgIdx].getArgument().isPackExpansion()) {
const TemplateArgument &Arg = NewArgs[ArgIdx++].getArgument();
Expand Down Expand Up @@ -7292,10 +7289,10 @@ static void DiagnoseTemplateParameterListArityMismatch(
Sema &S, TemplateParameterList *New, TemplateParameterList *Old,
Sema::TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc);

bool Sema::CheckTemplateTemplateArgument(
TemplateTemplateParmDecl *Param, TemplateParameterList *Params,
TemplateArgumentLoc &Arg, bool PartialOrdering,
bool *MatchedPackOnParmToNonPackOnArg) {
bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param,
TemplateParameterList *Params,
TemplateArgumentLoc &Arg,
bool IsDeduced) {
TemplateName Name = Arg.getArgument().getAsTemplateOrTemplatePattern();
auto [Template, DefaultArgs] = Name.getTemplateDeclAndDefaultArgs();
if (!Template) {
Expand Down Expand Up @@ -7330,47 +7327,64 @@ bool Sema::CheckTemplateTemplateArgument(
<< Template;
}

if (!getLangOpts().RelaxedTemplateTemplateArgs)
return !TemplateParameterListsAreEqual(
Template->getTemplateParameters(), Params, /*Complain=*/true,
TPL_TemplateTemplateArgumentMatch, Arg.getLocation());

// C++1z [temp.arg.template]p3: (DR 150)
// A template-argument matches a template template-parameter P when P
// is at least as specialized as the template-argument A.
if (!isTemplateTemplateParameterAtLeastAsSpecializedAs(
Params, Param, Template, DefaultArgs, Arg.getLocation(),
PartialOrdering, MatchedPackOnParmToNonPackOnArg))
return true;
// P2113
// C++20[temp.func.order]p2
// [...] If both deductions succeed, the partial ordering selects the
// more constrained template (if one exists) as determined below.
SmallVector<const Expr *, 3> ParamsAC, TemplateAC;
Params->getAssociatedConstraints(ParamsAC);
// C++20[temp.arg.template]p3
// [...] In this comparison, if P is unconstrained, the constraints on A
// are not considered.
if (ParamsAC.empty())
return false;
if (getLangOpts().RelaxedTemplateTemplateArgs) {
// Quick check for the common case:
// If P contains a parameter pack, then A [...] matches P if each of A's
// template parameters matches the corresponding template parameter in
// the template-parameter-list of P.
if (TemplateParameterListsAreEqual(
Template->getTemplateParameters(), Params, false,
TPL_TemplateTemplateArgumentMatch, Arg.getLocation()) &&
// If the argument has no associated constraints, then the parameter is
// definitely at least as specialized as the argument.
// Otherwise - we need a more thorough check.
!Template->hasAssociatedConstraints())
return false;

Template->getAssociatedConstraints(TemplateAC);
if (isTemplateTemplateParameterAtLeastAsSpecializedAs(
Params, Template, DefaultArgs, Arg.getLocation(), IsDeduced)) {
// P2113
// C++20[temp.func.order]p2
// [...] If both deductions succeed, the partial ordering selects the
// more constrained template (if one exists) as determined below.
SmallVector<const Expr *, 3> ParamsAC, TemplateAC;
Params->getAssociatedConstraints(ParamsAC);
// C++2a[temp.arg.template]p3
// [...] In this comparison, if P is unconstrained, the constraints on A
// are not considered.
if (ParamsAC.empty())
return false;

bool IsParamAtLeastAsConstrained;
if (IsAtLeastAsConstrained(Param, ParamsAC, Template, TemplateAC,
IsParamAtLeastAsConstrained))
return true;
if (!IsParamAtLeastAsConstrained) {
Diag(Arg.getLocation(),
diag::err_template_template_parameter_not_at_least_as_constrained)
<< Template << Param << Arg.getSourceRange();
Diag(Param->getLocation(), diag::note_entity_declared_at) << Param;
Diag(Template->getLocation(), diag::note_entity_declared_at) << Template;
MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Param, ParamsAC, Template,
TemplateAC);
return true;
Template->getAssociatedConstraints(TemplateAC);

bool IsParamAtLeastAsConstrained;
if (IsAtLeastAsConstrained(Param, ParamsAC, Template, TemplateAC,
IsParamAtLeastAsConstrained))
return true;
if (!IsParamAtLeastAsConstrained) {
Diag(Arg.getLocation(),
diag::err_template_template_parameter_not_at_least_as_constrained)
<< Template << Param << Arg.getSourceRange();
Diag(Param->getLocation(), diag::note_entity_declared_at) << Param;
Diag(Template->getLocation(), diag::note_entity_declared_at)
<< Template;
MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Param, ParamsAC, Template,
TemplateAC);
return true;
}
return false;
}
// FIXME: Produce better diagnostics for deduction failures.
}
return false;

return !TemplateParameterListsAreEqual(Template->getTemplateParameters(),
Params,
true,
TPL_TemplateTemplateArgumentMatch,
Arg.getLocation());
}

static Sema::SemaDiagnosticBuilder noteLocation(Sema &S, const NamedDecl &Decl,
Expand Down Expand Up @@ -9758,14 +9772,11 @@ DeclResult Sema::ActOnExplicitInstantiation(

// Check that the template argument list is well-formed for this
// template.
bool PrimaryHasMatchedPackOnParmToNonPackOnArg = false;
SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
if (CheckTemplateArgumentList(
ClassTemplate, TemplateNameLoc, TemplateArgs,
/*DefaultArgs=*/{}, false, SugaredConverted, CanonicalConverted,
/*UpdateArgsWithConversions=*/true,
/*ConstraintsNotSatisfied=*/nullptr, /*PartialOrderingTTP=*/false,
&PrimaryHasMatchedPackOnParmToNonPackOnArg))
if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, TemplateArgs,
/*DefaultArgs=*/{}, false, SugaredConverted,
CanonicalConverted,
/*UpdateArgsWithConversions=*/true))
return true;

// Find the class template specialization declaration that
Expand Down Expand Up @@ -9886,9 +9897,7 @@ DeclResult Sema::ActOnExplicitInstantiation(
= cast_or_null<ClassTemplateSpecializationDecl>(
Specialization->getDefinition());
if (!Def)
InstantiateClassTemplateSpecialization(
TemplateNameLoc, Specialization, TSK,
/*Complain=*/true, PrimaryHasMatchedPackOnParmToNonPackOnArg);
InstantiateClassTemplateSpecialization(TemplateNameLoc, Specialization, TSK);
else if (TSK == TSK_ExplicitInstantiationDefinition) {
MarkVTableUsed(TemplateNameLoc, Specialization, true);
Specialization->setPointOfInstantiation(Def->getPointOfInstantiation());
Expand Down
442 changes: 133 additions & 309 deletions clang/lib/Sema/SemaTemplateDeduction.cpp

Large diffs are not rendered by default.

39 changes: 10 additions & 29 deletions clang/lib/Sema/SemaTemplateInstantiate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,6 @@ bool Sema::CodeSynthesisContext::isInstantiationRecord() const {
case LambdaExpressionSubstitution:
case BuildingDeductionGuides:
case TypeAliasTemplateInstantiation:
case PartialOrderingTTP:
return false;

// This function should never be called when Kind's value is Memoization.
Expand Down Expand Up @@ -805,11 +804,6 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
SemaRef, CodeSynthesisContext::BuildingDeductionGuides,
PointOfInstantiation, InstantiationRange, Entity) {}

Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation ArgLoc, PartialOrderingTTP,
TemplateDecl *PArg, SourceRange InstantiationRange)
: InstantiatingTemplate(SemaRef, CodeSynthesisContext::PartialOrderingTTP,
ArgLoc, InstantiationRange, PArg) {}

void Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) {
Ctx.SavedInNonInstantiationSFINAEContext = InNonInstantiationSFINAEContext;
Expand Down Expand Up @@ -1249,14 +1243,6 @@ void Sema::PrintInstantiationStack() {
<< cast<TypeAliasTemplateDecl>(Active->Entity)
<< Active->InstantiationRange;
break;
case CodeSynthesisContext::PartialOrderingTTP:
Diags.Report(Active->PointOfInstantiation,
diag::note_template_arg_template_params_mismatch);
if (SourceLocation ParamLoc = Active->Entity->getLocation();
ParamLoc.isValid())
Diags.Report(ParamLoc, diag::note_template_prev_declaration)
<< /*isTemplateTemplateParam=*/true << Active->InstantiationRange;
break;
}
}
}
Expand Down Expand Up @@ -1299,7 +1285,6 @@ std::optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
case CodeSynthesisContext::PriorTemplateArgumentSubstitution:
case CodeSynthesisContext::DefaultTemplateArgumentChecking:
case CodeSynthesisContext::RewritingOperatorAsSpaceship:
case CodeSynthesisContext::PartialOrderingTTP:
// A default template argument instantiation and substitution into
// template parameters with arguments for prior parameters may or may
// not be a SFINAE context; look further up the stack.
Expand Down Expand Up @@ -4017,11 +4002,11 @@ bool Sema::usesPartialOrExplicitSpecialization(
/// Get the instantiation pattern to use to instantiate the definition of a
/// given ClassTemplateSpecializationDecl (either the pattern of the primary
/// template or of a partial specialization).
static ActionResult<CXXRecordDecl *> getPatternForClassTemplateSpecialization(
static ActionResult<CXXRecordDecl *>
getPatternForClassTemplateSpecialization(
Sema &S, SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec,
TemplateSpecializationKind TSK,
bool PrimaryHasMatchedPackOnParmToNonPackOnArg) {
TemplateSpecializationKind TSK) {
Sema::InstantiatingTemplate Inst(S, PointOfInstantiation, ClassTemplateSpec);
if (Inst.isInvalid())
return {/*Invalid=*/true};
Expand All @@ -4044,7 +4029,7 @@ static ActionResult<CXXRecordDecl *> getPatternForClassTemplateSpecialization(
// specialization with the template argument lists of the partial
// specializations.
typedef PartialSpecMatchResult MatchResult;
SmallVector<MatchResult, 4> Matched, ExtraMatched;
SmallVector<MatchResult, 4> Matched;
SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
Template->getPartialSpecializations(PartialSpecs);
TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation);
Expand All @@ -4061,13 +4046,11 @@ static ActionResult<CXXRecordDecl *> getPatternForClassTemplateSpecialization(
MakeDeductionFailureInfo(S.Context, Result, Info));
(void)Result;
} else {
auto &List =
Info.hasMatchedPackOnParmToNonPackOnArg() ? ExtraMatched : Matched;
List.push_back(MatchResult{Partial, Info.takeCanonical()});
Matched.push_back(PartialSpecMatchResult());
Matched.back().Partial = Partial;
Matched.back().Args = Info.takeCanonical();
}
}
if (Matched.empty() && PrimaryHasMatchedPackOnParmToNonPackOnArg)
Matched = std::move(ExtraMatched);

// If we're dealing with a member template where the template parameters
// have been instantiated, this provides the original template parameters
Expand Down Expand Up @@ -4170,18 +4153,16 @@ static ActionResult<CXXRecordDecl *> getPatternForClassTemplateSpecialization(
bool Sema::InstantiateClassTemplateSpecialization(
SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec,
TemplateSpecializationKind TSK, bool Complain,
bool PrimaryHasMatchedPackOnParmToNonPackOnArg) {
TemplateSpecializationKind TSK, bool Complain) {
// Perform the actual instantiation on the canonical declaration.
ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
ClassTemplateSpec->getCanonicalDecl());
if (ClassTemplateSpec->isInvalidDecl())
return true;

ActionResult<CXXRecordDecl *> Pattern =
getPatternForClassTemplateSpecialization(
*this, PointOfInstantiation, ClassTemplateSpec, TSK,
PrimaryHasMatchedPackOnParmToNonPackOnArg);
getPatternForClassTemplateSpecialization(*this, PointOfInstantiation,
ClassTemplateSpec, TSK);
if (!Pattern.isUsable())
return Pattern.isInvalid();

Expand Down
4 changes: 4 additions & 0 deletions clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
if (LR->getSymbolicBase() || RR->getSymbolicBase())
return;

if (!B->getLHS()->getType()->isPointerType() ||
!B->getRHS()->getType()->isPointerType())
return;

const auto *ElemLR = dyn_cast<ElementRegion>(LR);
const auto *ElemRR = dyn_cast<ElementRegion>(RR);

Expand Down
7 changes: 7 additions & 0 deletions clang/test/AST/ByteCode/cxx1z.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,10 @@ namespace Temp {
A<int &, addr({}).n> c; // both-error {{reference to subobject of temporary object}}
A<int *, &addr({}).n> d; // both-error {{pointer to subobject of temporary object}}
}

char arr[3];
A<const char*, &arr[1]> d; // both-error {{refers to subobject '&arr[1]'}}

void Func() {
A<const char*, __func__> a; // both-error {{pointer to subobject of predefined '__func__' variable}}
}
12 changes: 12 additions & 0 deletions clang/test/Analysis/pointer-sub.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=security.PointerSub -analyzer-output=text-minimal -verify %s

typedef int * Ptr;

void f1(void) {
int x, y, z[10];
int d = &y - &x; // expected-warning{{Subtraction of two pointers that do not point into the same array is undefined behavior}}
Expand All @@ -10,6 +12,12 @@ void f1(void) {
d = &x - (&x + 1); // no-warning
d = (&x + 0) - &x; // no-warning
d = (z + 10) - z; // no-warning
d = (long long)&y - (long long)&x; // no-warning
long long l = 1;
d = l - (long long)&y; // no-warning
Ptr p1 = &x;
Ptr p2 = &y;
d = p1 - p2; // expected-warning{{Subtraction of two pointers that do not point into the same array is undefined behavior}}
}

void f2(void) {
Expand All @@ -28,6 +36,10 @@ void f2(void) {

d = (int *)((char *)(&a[4]) + sizeof(int)) - &a[4]; // no-warning (pointers into the same array data)
d = (int *)((char *)(&a[4]) + 1) - &a[4]; // expected-warning{{Subtraction of two pointers that}}

long long a1 = (long long)&a[1];
long long b1 = (long long)&b[1];
d = a1 - b1;
}

void f3(void) {
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CXX/drs/cwg14xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ int i = N::f();

namespace cwg1479 { // cwg1479: 3.1
#if __cplusplus >= 201103L
int operator"" _a(const char*, std::size_t = 0);
int operator""_a(const char*, std::size_t = 0);
// since-cxx11-error@-1 {{literal operator cannot have a default argument}}
#endif
}
Expand Down
3 changes: 3 additions & 0 deletions clang/test/CXX/drs/cwg25xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ operator"" _div();
using ::cwg2521::operator"" _\u03C0___;
using ::cwg2521::operator""_div;
// since-cxx11-warning@-2 {{identifier '_Ï€___' preceded by whitespace in a literal operator declaration is deprecated}}

long double operator"" _RESERVED(long double);
// since-cxx11-warning@-1 {{identifier '_RESERVED' preceded by whitespace in a literal operator declaration is deprecated}}
#pragma clang diagnostic pop
#endif
} // namespace cwg2521
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CXX/lex/lex.literal/lex.ext/p1.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wno-deprecated-literal-operator -verify %s

void operator "" p31(long double); // expected-warning{{user-defined literal suffixes not starting with '_' are reserved}}
void operator "" _p31(long double);
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CXX/lex/lex.literal/lex.ext/p10.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -std=c++11 -verify %s
// RUN: %clang_cc1 -std=c++11 -Wno-deprecated-literal-operator -verify %s

using size_t = decltype(sizeof(int));
void operator "" wibble(const char *); // expected-warning {{user-defined literal suffixes not starting with '_' are reserved; no literal will invoke this operator}}
Expand Down
6 changes: 3 additions & 3 deletions clang/test/CXX/lex/lex.literal/lex.ext/p11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ template<typename T, typename U> struct same_type;
template<typename T> struct same_type<T, T> {};
template<typename T> using X = T;
template<typename CharT, X<CharT>...>
int operator "" _x(); // expected-warning {{string literal operator templates are a GNU extension}}
int operator ""_x(); // expected-warning {{string literal operator templates are a GNU extension}}
template<char...>
double operator "" _x();
double operator ""_x();

auto a="string"_x;
auto b=42_x;
same_type<decltype(a), int> test_a;
same_type<decltype(b), double> test_b;

char operator "" _x(const char *begin, size_t size);
char operator ""_x(const char *begin, size_t size);
auto c="string"_x;
auto d=L"string"_x;
same_type<decltype(c), char> test_c;
Expand Down
10 changes: 5 additions & 5 deletions clang/test/CXX/lex/lex.literal/lex.ext/p3.cpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s

int &operator "" _x1 (unsigned long long);
int &operator ""_x1 (unsigned long long);
int &i1 = 0x123_x1;

double &operator "" _x1 (const char *);
double &operator ""_x1 (const char *);
int &i2 = 45_x1;

template<char...> char &operator "" _x1 ();
template<char...> char &operator ""_x1 ();
int &i3 = 0377_x1;

int &i4 = 90000000000000000000000000000000000000000000000_x1; // expected-error {{integer literal is too large to be represented in any integer type}}

double &operator "" _x2 (const char *);
double &operator ""_x2 (const char *);
double &i5 = 123123123123123123123123123123123123123123123_x2;

template<char...Cs> constexpr int operator "" _x3() { return sizeof...(Cs); }
template<char...Cs> constexpr int operator ""_x3() { return sizeof...(Cs); }
static_assert(123456789012345678901234567890123456789012345678901234567890_x3 == 60, "");
10 changes: 5 additions & 5 deletions clang/test/CXX/lex/lex.literal/lex.ext/p4.cpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s

int &operator "" _x1 (long double);
int &operator ""_x1 (long double);
int &i1 = 0.123_x1;

double &operator "" _x1 (const char *);
double &operator ""_x1 (const char *);
int &i2 = 45._x1;

template<char...> char &operator "" _x1 ();
template<char...> char &operator ""_x1 ();
int &i3 = 0377e-1_x1;

int &i4 = 1e1000000_x1; // expected-warning {{too large for type 'long double'}}

double &operator "" _x2 (const char *);
double &operator ""_x2 (const char *);
double &i5 = 1e1000000_x2;

template<char...Cs> constexpr int operator "" _x3() { return sizeof...(Cs); }
template<char...Cs> constexpr int operator ""_x3() { return sizeof...(Cs); }
static_assert(1e1000000_x3 == 9, "");
8 changes: 4 additions & 4 deletions clang/test/CXX/lex/lex.literal/lex.ext/p5.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@

using size_t = decltype(sizeof(int));

int &operator "" _x1 (const char *);
double &operator "" _x1 (const char *, size_t);
int &operator ""_x1 (const char *);
double &operator ""_x1 (const char *, size_t);
double &i1 = "foo"_x1;
#if __cplusplus >= 202002L
using char8 = float;
float &operator "" _x1 (const char8_t *, size_t);
float &operator ""_x1 (const char8_t *, size_t);
#else
using char8 = double;
#endif
char8 &i2 = u8"foo"_x1;
double &i3 = L"foo"_x1; // expected-error {{no matching literal operator for call to 'operator""_x1' with arguments of types 'const wchar_t *' and 'unsigned long'}}

char &operator "" _x1(const wchar_t *, size_t);
char &operator ""_x1(const wchar_t *, size_t);
char &i4 = L"foo"_x1; // ok
double &i5 = R"(foo)"_x1; // ok
char8 &i6 = u\
Expand Down
8 changes: 4 additions & 4 deletions clang/test/CXX/lex/lex.literal/lex.ext/p6.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

using size_t = decltype(sizeof(int));

int &operator "" _x1 (const char *);
int &operator ""_x1 (const char *);
double &i1 = 'a'_x1; // expected-error {{no matching literal operator}}
double &operator "" _x1 (wchar_t);
double &operator ""_x1 (wchar_t);
double &i2 = L'a'_x1;
double &i3 = 'a'_x1; // expected-error {{no matching literal operator}}
double &i4 = operator"" _x1('a'); // ok
double &i4 = operator""_x1('a'); // ok

char &operator "" _x1(char16_t);
char &operator ""_x1(char16_t);
char &i5 = u'a'_x1; // ok
double &i6 = L'a'_x1; // ok
6 changes: 3 additions & 3 deletions clang/test/CXX/lex/lex.literal/lex.ext/p7.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ template<typename T> struct same_type<T, T> {};

namespace std_example {

long double operator "" _w(long double);
std::string operator "" _w(const char16_t*, size_t);
unsigned operator "" _w(const char*);
long double operator ""_w(long double);
std::string operator ""_w(const char16_t*, size_t);
unsigned operator ""_w(const char*);
int main() {
auto v1 = 1.2_w; // calls operator""_w(1.2L)
auto v2 = u"one"_w; // calls operator""_w(u"one", 3)
Expand Down
6 changes: 3 additions & 3 deletions clang/test/CXX/lex/lex.literal/lex.ext/p8.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
// RUN: %clang_cc1 -std=c++11 -verify %s

using size_t = decltype(sizeof(int));
constexpr const char *operator "" _id(const char *p, size_t) { return p; }
constexpr const char *operator ""_id(const char *p, size_t) { return p; }
constexpr const char *s = "foo"_id "bar" "baz"_id "quux";

constexpr bool streq(const char *p, const char *q) {
return *p == *q && (!*p || streq(p+1, q+1));
}
static_assert(streq(s, "foobarbazquux"), "");

constexpr const char *operator "" _trim(const char *p, size_t n) {
return *p == ' ' ? operator "" _trim(p + 1, n - 1) : p;
constexpr const char *operator ""_trim(const char *p, size_t n) {
return *p == ' ' ? operator ""_trim(p + 1, n - 1) : p;
}
constexpr const char *t = " " " "_trim " foo";
static_assert(streq(t, "foo"), "");
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CXX/lex/lex.literal/lex.ext/p9.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s

using size_t = decltype(sizeof(int));
void operator "" _x(const wchar_t *, size_t);
void operator ""_x(const wchar_t *, size_t);

namespace std_example {

Expand Down
28 changes: 14 additions & 14 deletions clang/test/CXX/over/over.oper/over.literal/p2.cpp
Original file line number Diff line number Diff line change
@@ -1,43 +1,43 @@
// RUN: %clang_cc1 -std=c++11 %s -verify

void operator "" _a(const char *);
void operator ""_a(const char *);

namespace N {
using ::operator "" _a;
using ::operator ""_a;

void operator "" _b(const char *);
void operator ""_b(const char *);
}

using N::operator "" _b;
using N::operator ""_b;

class C {
void operator "" _c(const char *); // expected-error {{must be in a namespace or global scope}}
void operator ""_c(const char *); // expected-error {{must be in a namespace or global scope}}

static void operator "" _c(unsigned long long); // expected-error {{must be in a namespace or global scope}}
static void operator ""_c(unsigned long long); // expected-error {{must be in a namespace or global scope}}

friend void operator "" _d(const char *);
friend void operator ""_d(const char *);
};

int operator "" _e; // expected-error {{cannot be the name of a variable}}
int operator ""_e; // expected-error {{cannot be the name of a variable}}

void f() {
int operator "" _f; // expected-error {{cannot be the name of a variable}}
int operator ""_f; // expected-error {{cannot be the name of a variable}}
}

extern "C++" {
void operator "" _g(const char *);
void operator ""_g(const char *);
}

template<char...> void operator "" _h() {}
template<char...> void operator ""_h() {}

template<> void operator "" _h<'a', 'b', 'c'>() {}
template<> void operator ""_h<'a', 'b', 'c'>() {}

template void operator "" _h<'a', 'b', 'c', 'd'>();
template void operator ""_h<'a', 'b', 'c', 'd'>();

namespace rdar13605348 {

class C {
double operator"" _x(long double value) { return double(value); } // expected-error{{literal operator 'operator""_x' must be in a namespace or global scope}}
double operator""_x(long double value) { return double(value); } // expected-error{{literal operator 'operator""_x' must be in a namespace or global scope}}
double value() { return 3.2_x; } // expected-error{{no matching literal operator for call to}}
};

Expand Down
66 changes: 33 additions & 33 deletions clang/test/CXX/over/over.oper/over.literal/p3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,38 @@
using size_t = decltype(sizeof(int));

// Acceptable parameter declarations
char operator "" _a(const char *);
char operator "" _a(const char []);
char operator "" _a(unsigned long long);
char operator "" _a(long double);
char operator "" _a(char);
char operator "" _a(const volatile char);
char operator "" _a(wchar_t);
char operator "" _a(char16_t);
char operator "" _a(char32_t);
char operator "" _a(const char *, size_t);
char operator "" _a(const wchar_t *, size_t);
char operator "" _a(const char16_t *, size_t);
char operator "" _a(const char32_t *, size_t);
char operator "" _a(const char [32], size_t);
char operator ""_a(const char *);
char operator ""_a(const char []);
char operator ""_a(unsigned long long);
char operator ""_a(long double);
char operator ""_a(char);
char operator ""_a(const volatile char);
char operator ""_a(wchar_t);
char operator ""_a(char16_t);
char operator ""_a(char32_t);
char operator ""_a(const char *, size_t);
char operator ""_a(const wchar_t *, size_t);
char operator ""_a(const char16_t *, size_t);
char operator ""_a(const char32_t *, size_t);
char operator ""_a(const char [32], size_t);

// Unacceptable parameter declarations
char operator "" _b(); // expected-error {{parameter}}
char operator "" _b(const wchar_t *); // expected-error {{parameter}}
char operator "" _b(long long); // expected-error {{parameter}}
char operator "" _b(double); // expected-error {{parameter}}
char operator "" _b(short); // expected-error {{parameter}}
char operator "" _a(char, int = 0); // expected-error {{parameter}}
char operator "" _b(unsigned short); // expected-error {{parameter}}
char operator "" _b(signed char); // expected-error {{parameter}}
char operator "" _b(unsigned char); // expected-error {{parameter}}
char operator "" _b(const short *, size_t); // expected-error {{parameter}}
char operator "" _b(const unsigned short *, size_t); // expected-error {{parameter}}
char operator "" _b(const signed char *, size_t); // expected-error {{parameter}}
char operator "" _b(const unsigned char *, size_t); // expected-error {{parameter}}
char operator "" _a(const volatile char *, size_t); // expected-error {{parameter}}
char operator "" _a(volatile wchar_t *, size_t); // expected-error {{parameter}}
char operator "" _a(char16_t *, size_t); // expected-error {{parameter}}
char operator "" _a(const char32_t *, size_t, bool = false); // expected-error {{parameter}}
char operator "" _a(const char *, signed long); // expected-error {{parameter}}
char operator "" _a(const char *, size_t = 0); // expected-error {{default argument}}
char operator ""_b(); // expected-error {{parameter}}
char operator ""_b(const wchar_t *); // expected-error {{parameter}}
char operator ""_b(long long); // expected-error {{parameter}}
char operator ""_b(double); // expected-error {{parameter}}
char operator ""_b(short); // expected-error {{parameter}}
char operator ""_a(char, int = 0); // expected-error {{parameter}}
char operator ""_b(unsigned short); // expected-error {{parameter}}
char operator ""_b(signed char); // expected-error {{parameter}}
char operator ""_b(unsigned char); // expected-error {{parameter}}
char operator ""_b(const short *, size_t); // expected-error {{parameter}}
char operator ""_b(const unsigned short *, size_t); // expected-error {{parameter}}
char operator ""_b(const signed char *, size_t); // expected-error {{parameter}}
char operator ""_b(const unsigned char *, size_t); // expected-error {{parameter}}
char operator ""_a(const volatile char *, size_t); // expected-error {{parameter}}
char operator ""_a(volatile wchar_t *, size_t); // expected-error {{parameter}}
char operator ""_a(char16_t *, size_t); // expected-error {{parameter}}
char operator ""_a(const char32_t *, size_t, bool = false); // expected-error {{parameter}}
char operator ""_a(const char *, signed long); // expected-error {{parameter}}
char operator ""_a(const char *, size_t = 0); // expected-error {{default argument}}
20 changes: 10 additions & 10 deletions clang/test/CXX/over/over.oper/over.literal/p5.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@
using size_t = decltype(sizeof(int));
template<char...> struct S {};

template<char...> void operator "" _a();
template<char... C> S<C...> operator "" _a();
template<char...> void operator ""_a();
template<char... C> S<C...> operator ""_a();

template<typename T> struct U {
friend int operator "" _a(const char *, size_t);
friend int operator ""_a(const char *, size_t);
// FIXME: It's not entirely clear whether this is intended to be legal.
friend U operator "" _a(const T *, size_t); // expected-error {{parameter}}
friend U operator ""_a(const T *, size_t); // expected-error {{parameter}}
};
template<char...> struct V {
friend void operator "" _b(); // expected-error {{parameters}}
friend void operator ""_b(); // expected-error {{parameters}}
};

template<char... C, int N = 0> void operator "" _b(); // expected-error {{template}}
template<char... C> void operator "" _b(int N = 0); // expected-error {{template}}
template<char, char...> void operator "" _b(); // expected-error {{template}}
template<typename T> T operator "" _b(const char *); // expected-error {{template}}
template<typename T> int operator "" _b(const T *, size_t); // expected-error {{template}}
template<char... C, int N = 0> void operator ""_b(); // expected-error {{template}}
template<char... C> void operator ""_b(int N = 0); // expected-error {{template}}
template<char, char...> void operator ""_b(); // expected-error {{template}}
template<typename T> T operator ""_b(const char *); // expected-error {{template}}
template<typename T> int operator ""_b(const T *, size_t); // expected-error {{template}}
12 changes: 6 additions & 6 deletions clang/test/CXX/over/over.oper/over.literal/p6.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
// RUN: %clang_cc1 -std=c++11 %s -verify

// expected-note@+1 {{extern "C" language linkage specification begins here}}
extern "C" void operator "" _a(const char *); // expected-error {{must have C++ linkage}}
extern "C" template<char...> void operator "" _b(); // expected-error {{must have C++ linkage}}
extern "C" void operator ""_a(const char *); // expected-error {{must have C++ linkage}}
extern "C" template<char...> void operator ""_b(); // expected-error {{must have C++ linkage}}
// expected-note@-1 {{extern "C" language linkage specification begins here}}

extern "C" { // expected-note 4 {{extern "C" language linkage specification begins here}}
void operator "" _c(const char *); // expected-error {{must have C++ linkage}}
template<char...> void operator "" _d(); // expected-error {{must have C++ linkage}}
void operator ""_c(const char *); // expected-error {{must have C++ linkage}}
template<char...> void operator ""_d(); // expected-error {{must have C++ linkage}}
namespace N {
void operator "" _e(const char *); // expected-error {{must have C++ linkage}}
template<char...> void operator "" _f(); // expected-error {{must have C++ linkage}}
void operator ""_e(const char *); // expected-error {{must have C++ linkage}}
template<char...> void operator ""_f(); // expected-error {{must have C++ linkage}}
}
}
10 changes: 5 additions & 5 deletions clang/test/CXX/over/over.oper/over.literal/p7.cpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
// RUN: %clang_cc1 -std=c++11 %s -verify
// expected-no-diagnostics

constexpr int operator "" _a(const char *c) {
constexpr int operator ""_a(const char *c) {
return c[0];
}

static_assert(operator "" _a("foo") == 'f', "");
static_assert(operator ""_a("foo") == 'f', "");

void puts(const char *);
static inline void operator "" _puts(const char *c) {
static inline void operator ""_puts(const char *c) {
puts(c);
}
void f() {
operator "" _puts("foo");
operator "" _puts("bar");
operator ""_puts("foo");
operator ""_puts("bar");
}
10 changes: 5 additions & 5 deletions clang/test/CXX/over/over.oper/over.literal/p8.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ namespace std {
using size_t = decltype(sizeof(int));
}

void operator "" _km(long double); // ok
string operator "" _i18n(const char*, std::size_t); // ok
template<char...> int operator "" \u03C0(); // ok, UCN for lowercase pi // expected-warning {{reserved}}
void operator ""_km(long double); // ok
string operator ""_i18n(const char*, std::size_t); // ok
template<char...> int operator ""\u03C0(); // ok, UCN for lowercase pi // expected-warning {{reserved}}
float operator ""E(const char *); // expected-error {{invalid suffix on literal}} expected-warning {{reserved}}
float operator " " B(const char *); // expected-error {{must be '""'}} expected-warning {{reserved}}
string operator "" 5X(const char *, std::size_t); // expected-error {{expected identifier}}
double operator "" _miles(double); // expected-error {{parameter}}
string operator ""5X(const char *, std::size_t); // expected-error {{expected identifier}}
double operator ""_miles(double); // expected-error {{parameter}}
template<char...> int operator "" j(const char*); // expected-error {{template}}

float operator ""_E(const char *);
31 changes: 13 additions & 18 deletions clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

template <class T> struct eval; // expected-note 3{{template is declared here}}

template <template <class, class...> class TT, class T1, class... Rest>
template <template <class, class...> class TT, class T1, class... Rest>
struct eval<TT<T1, Rest...>> { };

template <class T1> struct A;
template <class T1, class T2> struct B;
template <int N> struct C;
template <class T1, int N> struct D;
template <class T1> struct A;
template <class T1, class T2> struct B;
template <int N> struct C;
template <class T1, int N> struct D;
template <class T1, class T2, int N = 17> struct E;

eval<A<int>> eA;
Expand All @@ -17,32 +17,27 @@ eval<C<17>> eC; // expected-error{{implicit instantiation of undefined template
eval<D<int, 17>> eD; // expected-error{{implicit instantiation of undefined template 'eval<D<int, 17>>'}}
eval<E<int, float>> eE; // expected-error{{implicit instantiation of undefined template 'eval<E<int, float>>}}

template<
template <int ...N> // expected-error{{deduced non-type template argument does not have the same type as the corresponding template parameter ('int' vs 'long')}}
class TT // expected-note {{previous template template parameter is here}}
> struct X0 { };

template<template <int ...N> class TT> struct X0 { }; // expected-note{{previous non-type template parameter with type 'int' is here}}
template<int I, int J, int ...Rest> struct X0a;
template<int ...Rest> struct X0b;
template<int I, long J> struct X0c; // expected-note{{template parameter is declared here}}
template<int I, long J> struct X0c; // expected-note{{template non-type parameter has a different type 'long' in template argument}}

X0<X0a> inst_x0a;
X0<X0b> inst_x0b;
X0<X0c> inst_x0c; // expected-note{{template template argument has different template parameters than its corresponding template template parameter}}
X0<X0c> inst_x0c; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}

template<typename T,
template <T ...N> // expected-error{{deduced non-type template argument does not have the same type as the corresponding template parameter ('short' vs 'long')}}
class TT // expected-note {{previous template template parameter is here}}
> struct X1 { };
template<typename T,
template <T ...N> class TT> // expected-note{{previous non-type template parameter with type 'short' is here}}
struct X1 { };
template<int I, int J, int ...Rest> struct X1a;
template<long I, long ...Rest> struct X1b;
template<short I, short J> struct X1c;
template<short I, long J> struct X1d; // expected-note{{template parameter is declared here}}
template<short I, long J> struct X1d; // expected-note{{template non-type parameter has a different type 'long' in template argument}}

X1<int, X1a> inst_x1a;
X1<long, X1b> inst_x1b;
X1<short, X1c> inst_x1c;
X1<short, X1d> inst_x1d; // expected-note{{template template argument has different template parameters than its corresponding template template parameter}}
X1<short, X1d> inst_x1d; // expected-error{{template template argument has different template parameters than its corresponding template template paramete}}

template <int> class X2; // expected-note{{template is declared here}} \
// expected-note{{template is declared here}}
Expand Down
21 changes: 10 additions & 11 deletions clang/test/CXX/temp/temp.param/p12.cpp
Original file line number Diff line number Diff line change
@@ -1,40 +1,39 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
template<typename> struct Y1; // expected-note{{template is declared here}}
// RUN: %clang_cc1 -fsyntax-only -verify %s
template<typename> struct Y1; // expected-note{{too few template parameters in template template argument}}
template<typename, int> struct Y2;

// C++ [temp.param]p12:
template<class T1,
template<class T1,
class T2 = int> // expected-note{{previous default template argument defined here}}
class B3;
template<class T1, typename T2> class B3;
template<class T1,
template<class T1,
typename T2 = float> // expected-error{{template parameter redefines default argument}}
class B3;

template<template<class, int> class,
template<template<class, int> class,
template<class> class = Y1> // expected-note{{previous default template argument defined here}}
class B3t;

template<template<class, int> class, template<class> class> class B3t;

template<template<class, int> class,
template<template<class, int> class,
template<class> class = Y1> // expected-error{{template parameter redefines default argument}}
class B3t;

template<int N,
template<int N,
int M = 5> // expected-note{{previous default template argument defined here}}
class B3n;

template<int N, int M> class B3n;

template<int N,
template<int N,
int M = 7> // expected-error{{template parameter redefines default argument}}
class B3n;

// Check validity of default arguments
template<template<class, int> class =// expected-note {{previous template template parameter is here}}
Y1> // expected-error{{too many template arguments for class template 'Y1'}}
// expected-note@-1 {{template template argument has different template parameters than its corresponding template template parameter}}
template<template<class, int> class // expected-note{{previous template template parameter is here}}
= Y1> // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
class C1 {};

C1<> c1; // expected-note{{while checking a default template argument}}
4 changes: 2 additions & 2 deletions clang/test/FixIt/fixit-c++11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ const char *p = "foo"bar; // expected-error {{requires a space between}}
#define ord - '0'
int k = '4'ord; // expected-error {{requires a space between}}

void operator"x" _y(char); // expected-error {{must be '""'}}
void operator L"" _z(char); // expected-error {{encoding prefix}}
void operator"x"_y(char); // expected-error {{must be '""'}}
void operator L""_z(char); // expected-error {{encoding prefix}}
void operator "x" "y" U"z" ""_whoops "z" "y"(char); // expected-error {{must be '""'}}

void f() {
Expand Down
18 changes: 18 additions & 0 deletions clang/test/Headers/import_header_unit_after_pragma.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// RUN: rm -fR %t
// RUN: split-file %s %t
// RUN: cd %t
// RUN: %clang_cc1 -verify -std=c++20 -emit-header-unit -xc++-user-header bz0.h
// RUN: %clang_cc1 -verify -std=c++20 -emit-header-unit -xc++-user-header -fmodule-file=bz0.pcm bz.cpp

//--- compare
#pragma GCC visibility push(default)
#pragma GCC visibility pop

//--- bz0.h
#include "compare"
// expected-no-diagnostics

//--- bz.cpp
#include "compare"

import "bz0.h"; // expected-warning {{the implementation of header units is in an experimental phase}}
15 changes: 12 additions & 3 deletions clang/test/Modules/cxx-templates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,23 @@ void g() {

template_param_kinds_1<0>(); // ok, from cxx-templates-a.h
template_param_kinds_1<int>(); // ok, from cxx-templates-b.h
template_param_kinds_2<Tmpl_T_C>(); // ok, from cxx-templates-b.h

template_param_kinds_2<Tmpl_T_C>(); // expected-error {{no matching function}}
// expected-note@Inputs/cxx-templates-a.h:11 {{invalid explicitly-specified argument}}
// expected-note@Inputs/cxx-templates-b.h:11 {{invalid explicitly-specified argument}}

template_param_kinds_2<Tmpl_T_I_I>(); // expected-error {{ambiguous}}
// expected-note@Inputs/cxx-templates-a.h:11 {{candidate}}
// expected-note@Inputs/cxx-templates-b.h:11 {{candidate}}

template_param_kinds_3<Tmpl_T_T_A>();
template_param_kinds_3<Tmpl_T_T_B>();
// FIXME: This should be valid, but we incorrectly match the template template
// argument against both template template parameters.
template_param_kinds_3<Tmpl_T_T_A>(); // expected-error {{ambiguous}}
// expected-note@Inputs/cxx-templates-a.h:12 {{candidate}}
// expected-note@Inputs/cxx-templates-b.h:12 {{candidate}}
template_param_kinds_3<Tmpl_T_T_B>(); // expected-error {{ambiguous}}
// expected-note@Inputs/cxx-templates-a.h:12 {{candidate}}
// expected-note@Inputs/cxx-templates-b.h:12 {{candidate}}

// Trigger the instantiation of a template in 'a' that uses a type defined in
// 'common'. That type is not visible here.
Expand Down
29 changes: 16 additions & 13 deletions clang/test/Parser/cxx11-user-defined-literals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,19 @@ int cake() __attribute__((availability(macosx, unavailable, message = "is a lie"
#endif

// But they can appear in expressions.
constexpr char operator"" _id(char c) { return c; }
constexpr wchar_t operator"" _id(wchar_t c) { return c; }
constexpr char16_t operator"" _id(char16_t c) { return c; }
constexpr char32_t operator"" _id(char32_t c) { return c; }
constexpr char operator""_id(char c) { return c; }
constexpr wchar_t operator""_id(wchar_t c) { return c; }
constexpr char16_t operator""_id(char16_t c) { return c; }
constexpr char32_t operator""_id(char32_t c) { return c; }

using size_t = decltype(sizeof(int));
constexpr const char operator"" _id(const char *p, size_t n) { return *p; }
constexpr const wchar_t operator"" _id(const wchar_t *p, size_t n) { return *p; }
constexpr const char16_t operator"" _id(const char16_t *p, size_t n) { return *p; }
constexpr const char32_t operator"" _id(const char32_t *p, size_t n) { return *p; }
constexpr const char operator""_id(const char *p, size_t n) { return *p; }
constexpr const wchar_t operator""_id(const wchar_t *p, size_t n) { return *p; }
constexpr const char16_t operator""_id(const char16_t *p, size_t n) { return *p; }
constexpr const char32_t operator""_id(const char32_t *p, size_t n) { return *p; }

constexpr unsigned long long operator"" _id(unsigned long long n) { return n; }
constexpr long double operator"" _id(long double d) { return d; }
constexpr unsigned long long operator""_id(unsigned long long n) { return n; }
constexpr long double operator""_id(long double d) { return d; }

template<int n> struct S {};
S<"a"_id> sa;
Expand Down Expand Up @@ -98,19 +98,22 @@ _no_such_suffix; // expected-error {{'operator""_no_such_suffix'}}
// is "" in translation phase 7.
void operator "\
" _foo(unsigned long long); // ok
// expected-warning@-1{{identifier '_foo' preceded by whitespace in a literal operator declaration is deprecated}}

void operator R"xyzzy()xyzzy" _foo(long double); // ok
// expected-warning@-1{{identifier '_foo' preceded by whitespace in a literal operator declaration is deprecated}}

void operator"" "" R"()" "" _foo(const char *); // ok
// expected-warning@-1{{identifier '_foo' preceded by whitespace}}

void operator ""_no_space(const char *); // ok

// Ensure we diagnose the bad cases.
void operator "\0" _non_empty(const char *); // expected-error {{must be '""'}}
void operator L"" _not_char(const char *); // expected-error {{cannot have an encoding prefix}}
void operator "\0"_non_empty(const char *); // expected-error {{must be '""'}}
void operator L""_not_char(const char *); // expected-error {{cannot have an encoding prefix}}
void operator "" ""
U"" // expected-error {{cannot have an encoding prefix}}
"" _also_not_char(const char *);
""_also_not_char(const char *);
void operator "" u8"" "\u0123" "hello"_all_of_the_things ""(const char*); // expected-error {{must be '""'}}

// Make sure we treat UCNs and UTF-8 as equivalent.
Expand Down
2 changes: 2 additions & 0 deletions clang/test/Sema/builtin-assume-aligned.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -DSIZE_T_64 -fsyntax-only -Wno-strict-prototypes -triple x86_64-linux -verify %s
// RUN: %clang_cc1 -fsyntax-only -Wno-strict-prototypes -triple i386-freebsd -verify %s
// RUN: %clang_cc1 -DSIZE_T_64 -fsyntax-only -Wno-strict-prototypes -triple x86_64-linux -verify %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -fsyntax-only -Wno-strict-prototypes -triple i386-freebsd -verify %s -fexperimental-new-constant-interpreter

// __builtin_assume_aligned's second parameter is size_t, which may be 32 bits,
// so test differently when size_t is 32 bits and when it is 64 bits.
Expand Down
1 change: 1 addition & 0 deletions clang/test/SemaCXX/builtin-assume-aligned.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -triple x86_64-linux-gnu %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -triple x86_64-linux-gnu %s -fexperimental-new-constant-interpreter

int n;
constexpr int *p = 0;
Expand Down
4 changes: 2 additions & 2 deletions clang/test/SemaCXX/cxx11-user-defined-literals-unused.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// RUN: %clang_cc1 -std=c++11 -verify %s -Wunused

namespace {
double operator"" _x(long double value) { return double(value); }
int operator"" _ii(long double value) { return int(value); } // expected-warning {{not needed and will not be emitted}}
double operator""_x(long double value) { return double(value); }
int operator""_ii(long double value) { return int(value); } // expected-warning {{not needed and will not be emitted}}
}

namespace rdar13589856 {
Expand Down
60 changes: 30 additions & 30 deletions clang/test/SemaCXX/cxx11-user-defined-literals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ enum class LitKind {
CharStr, WideStr, Char16Str, Char32Str,
Integer, Floating, Raw, Template
};
constexpr LitKind operator"" _kind(char p) { return LitKind::Char; }
constexpr LitKind operator"" _kind(wchar_t p) { return LitKind::WideChar; }
constexpr LitKind operator"" _kind(char16_t p) { return LitKind::Char16; }
constexpr LitKind operator"" _kind(char32_t p) { return LitKind::Char32; }
constexpr LitKind operator"" _kind(const char *p, size_t n) { return LitKind::CharStr; }
constexpr LitKind operator"" _kind(const wchar_t *p, size_t n) { return LitKind::WideStr; }
constexpr LitKind operator"" _kind(const char16_t *p, size_t n) { return LitKind::Char16Str; }
constexpr LitKind operator"" _kind(const char32_t *p, size_t n) { return LitKind::Char32Str; }
constexpr LitKind operator"" _kind(unsigned long long n) { return LitKind::Integer; }
constexpr LitKind operator"" _kind(long double n) { return LitKind::Floating; }
constexpr LitKind operator"" _kind2(const char *p) { return LitKind::Raw; }
template<char ...Cs> constexpr LitKind operator"" _kind3() { return LitKind::Template; }
constexpr LitKind operator""_kind(char p) { return LitKind::Char; }
constexpr LitKind operator""_kind(wchar_t p) { return LitKind::WideChar; }
constexpr LitKind operator""_kind(char16_t p) { return LitKind::Char16; }
constexpr LitKind operator""_kind(char32_t p) { return LitKind::Char32; }
constexpr LitKind operator""_kind(const char *p, size_t n) { return LitKind::CharStr; }
constexpr LitKind operator""_kind(const wchar_t *p, size_t n) { return LitKind::WideStr; }
constexpr LitKind operator""_kind(const char16_t *p, size_t n) { return LitKind::Char16Str; }
constexpr LitKind operator""_kind(const char32_t *p, size_t n) { return LitKind::Char32Str; }
constexpr LitKind operator""_kind(unsigned long long n) { return LitKind::Integer; }
constexpr LitKind operator""_kind(long double n) { return LitKind::Floating; }
constexpr LitKind operator""_kind2(const char *p) { return LitKind::Raw; }
template<char ...Cs> constexpr LitKind operator""_kind3() { return LitKind::Template; }

static_assert('x'_kind == LitKind::Char, "");
static_assert(L'x'_kind == LitKind::WideChar, "");
Expand All @@ -41,7 +41,7 @@ static_assert(4e6_kind3 == LitKind::Template, "");
constexpr const char *fractional_digits_impl(const char *p) {
return *p == '.' ? p + 1 : *p ? fractional_digits_impl(p + 1) : 0;
}
constexpr const char *operator"" _fractional_digits(const char *p) {
constexpr const char *operator""_fractional_digits(const char *p) {
return fractional_digits_impl(p) ?: p;
}
constexpr bool streq(const char *p, const char *q) {
Expand All @@ -56,57 +56,57 @@ static_assert(streq(1e+97_fractional_digits, "1e+97"), "");
static_assert(streq(0377_fractional_digits, "0377"), "");
static_assert(streq(0377.5_fractional_digits, "5"), "");

int operator"" _ambiguous(char); // expected-note {{candidate}}
int operator""_ambiguous(char); // expected-note {{candidate}}
namespace N {
void *operator"" _ambiguous(char); // expected-note {{candidate}}
void *operator""_ambiguous(char); // expected-note {{candidate}}
}
using namespace N;
int k = 'x'_ambiguous; // expected-error {{ambiguous}}

int operator"" _deleted(unsigned long long) = delete; // expected-note {{here}}
int operator""_deleted(unsigned long long) = delete; // expected-note {{here}}
int m = 42_deleted; // expected-error {{attempt to use a deleted}}

namespace Using {
namespace M {
int operator"" _using(char);
int operator""_using(char);
}
int k1 = 'x'_using; // expected-error {{no matching literal operator for call to 'operator""_using'}}

using M::operator "" _using;
using M::operator ""_using;
int k2 = 'x'_using;
}

namespace AmbiguousRawTemplate {
int operator"" _ambig1(const char *); // expected-note {{candidate}}
template<char...> int operator"" _ambig1(); // expected-note {{candidate}}
int operator""_ambig1(const char *); // expected-note {{candidate}}
template<char...> int operator""_ambig1(); // expected-note {{candidate}}

int k1 = 123_ambig1; // expected-error {{call to 'operator""_ambig1' is ambiguous}}

namespace Inner {
template<char...> int operator"" _ambig2(); // expected-note 3{{candidate}}
template<char...> int operator""_ambig2(); // expected-note 3{{candidate}}
}
int operator"" _ambig2(const char *); // expected-note 3{{candidate}}
using Inner::operator"" _ambig2;
int operator""_ambig2(const char *); // expected-note 3{{candidate}}
using Inner::operator""_ambig2;

int k2 = 123_ambig2; // expected-error {{call to 'operator""_ambig2' is ambiguous}}

namespace N {
using Inner::operator"" _ambig2;
using Inner::operator""_ambig2;

int k3 = 123_ambig2; // ok

using AmbiguousRawTemplate::operator"" _ambig2;
using AmbiguousRawTemplate::operator""_ambig2;

int k4 = 123_ambig2; // expected-error {{ambiguous}}

namespace M {

template<char...> int operator"" _ambig2();
template<char...> int operator""_ambig2();

int k5 = 123_ambig2; // ok
}

int operator"" _ambig2(unsigned long long);
int operator""_ambig2(unsigned long long);

int k6 = 123_ambig2; // ok
int k7 = 123._ambig2; // expected-error {{ambiguous}}
Expand All @@ -121,15 +121,15 @@ template<char C, char...Cs> constexpr unsigned hash(unsigned a) {
return hash<Cs...>(mash(a ^ mash(C)));
}
template<typename T, T v> struct constant { constexpr static T value = v; };
template<char...Cs> constexpr unsigned operator"" _hash() {
template<char...Cs> constexpr unsigned operator""_hash() {
return constant<unsigned, hash<Cs...>(0)>::value;
}
static_assert(0x1234_hash == 0x103eff5e, "");
static_assert(hash<'0', 'x', '1', '2', '3', '4'>(0) == 0x103eff5e, "");

// Functions and literal suffixes go in separate namespaces.
namespace Namespace {
template<char...> int operator"" _x();
template<char...> int operator""_x();
int k = _x(); // expected-error {{undeclared identifier '_x'}}

int _y(unsigned long long);
Expand All @@ -138,7 +138,7 @@ namespace Namespace {

namespace PR14950 {
template<...> // expected-error {{expected template parameter}}
int operator"" _b(); // expected-error {{no function template matches function template specialization}}
int operator""_b(); // expected-error {{no function template matches function template specialization}}
int main() { return 0_b; } // expected-error {{no matching literal operator for call to 'operator""_b'}}
}

Expand Down
6 changes: 3 additions & 3 deletions clang/test/SemaCXX/cxx2a-consteval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,17 +158,17 @@ int i3 = f1(f1(f1(&f1, &f1), f1(&f1, &f1), f1(f1(&f1, &f1), &f1)));

namespace user_defined_literal {

consteval int operator"" _test(unsigned long long i) {
consteval int operator""_test(unsigned long long i) {
// expected-note@-1+ {{declared here}}
return 0;
}

int i = 0_test;

auto ptr = &operator"" _test;
auto ptr = &operator""_test;
// expected-error@-1 {{take address}}

consteval auto operator"" _test1(unsigned long long i) {
consteval auto operator""_test1(unsigned long long i) {
return &f_eval;
}

Expand Down
2 changes: 1 addition & 1 deletion clang/test/SemaCXX/cxx98-compat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ struct DelayedDefaultArgumentParseInitList {
}
};

int operator"" _hello(const char *); // expected-warning {{literal operators are incompatible with C++98}}
int operator""_hello(const char *); // expected-warning {{literal operators are incompatible with C++98}}

enum EnumFixed : int { // expected-warning {{enumeration types with a fixed underlying type are incompatible with C++98}}
};
Expand Down
46 changes: 23 additions & 23 deletions clang/test/SemaCXX/literal-operators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,46 @@
#include <stddef.h>

struct tag {
void operator "" _tag_bad (const char *); // expected-error {{literal operator 'operator""_tag_bad' must be in a namespace or global scope}}
friend void operator "" _tag_good (const char *);
void operator ""_tag_bad (const char *); // expected-error {{literal operator 'operator""_tag_bad' must be in a namespace or global scope}}
friend void operator ""_tag_good (const char *);
};

namespace ns { void operator "" _ns_good (const char *); }
namespace ns { void operator ""_ns_good (const char *); }

// Check extern "C++" declarations
extern "C++" void operator "" _extern_good (const char *);
extern "C++" { void operator "" _extern_good (const char *); }
extern "C++" void operator ""_extern_good (const char *);
extern "C++" { void operator ""_extern_good (const char *); }

void fn () { void operator "" _fn_good (const char *); }
void fn () { void operator ""_fn_good (const char *); }

// One-param declarations (const char * was already checked)
void operator "" _good (char);
void operator "" _good (wchar_t);
void operator "" _good (char16_t);
void operator "" _good (char32_t);
void operator "" _good (unsigned long long);
void operator "" _good (long double);
void operator ""_good (char);
void operator ""_good (wchar_t);
void operator ""_good (char16_t);
void operator ""_good (char32_t);
void operator ""_good (unsigned long long);
void operator ""_good (long double);

// Two-param declarations
void operator "" _good (const char *, size_t);
void operator "" _good (const wchar_t *, size_t);
void operator "" _good (const char16_t *, size_t);
void operator "" _good (const char32_t *, size_t);
void operator ""_good (const char *, size_t);
void operator ""_good (const wchar_t *, size_t);
void operator ""_good (const char16_t *, size_t);
void operator ""_good (const char32_t *, size_t);

// Check typedef and array equivalences
void operator "" _good (const char[]);
void operator ""_good (const char[]);
typedef const char c;
void operator "" _good (c*);
void operator ""_good (c*);

// Check extra cv-qualifiers
void operator "" _cv_good (volatile const char *, const size_t); // expected-error {{invalid literal operator parameter type 'const volatile char *', did you mean 'const char *'?}}
void operator ""_cv_good (volatile const char *, const size_t); // expected-error {{invalid literal operator parameter type 'const volatile char *', did you mean 'const char *'?}}

// Template declaration
template <char...> void operator "" _good ();
template <char...> void operator ""_good ();

template <typename...> void operator "" _invalid(); // expected-error {{template parameter list for literal operator must be either 'char...' or 'typename T, T...'}}
template <wchar_t...> void operator "" _invalid(); // expected-error {{template parameter list for literal operator must be either 'char...' or 'typename T, T...'}}
template <unsigned long long...> void operator "" _invalid(); // expected-error {{template parameter list for literal operator must be either 'char...' or 'typename T, T...'}}
template <typename...> void operator ""_invalid(); // expected-error {{template parameter list for literal operator must be either 'char...' or 'typename T, T...'}}
template <wchar_t...> void operator ""_invalid(); // expected-error {{template parameter list for literal operator must be either 'char...' or 'typename T, T...'}}
template <unsigned long long...> void operator ""_invalid(); // expected-error {{template parameter list for literal operator must be either 'char...' or 'typename T, T...'}}

_Complex float operator""if(long double); // expected-warning {{reserved}}
_Complex float test_if_1() { return 2.0f + 1.5if; };
Expand Down
5 changes: 3 additions & 2 deletions clang/test/SemaCXX/make_integer_seq.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,6 @@ using illformed2 = ErrorSeq<int, -5>; // expected-note{{in instantiation}}
template <typename T, T N> void f() {}
__make_integer_seq<f, int, 0> x; // expected-error{{template template parameter must be a class template or type alias template}}

__make_integer_seq<__make_integer_seq, int, 10> PR28494; // expected-note{{different template parameters}}
// expected-error@make_integer_seq.cpp:* {{template argument for template template parameter must be a class template or type alias template}}
__make_integer_seq<__make_integer_seq, int, 10> PR28494; // expected-error{{different template parameters}}
// expected-note@make_integer_seq.cpp:* {{template parameter has a different kind}}
// expected-note@make_integer_seq.cpp:* {{previous template template parameter is here}}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wsystem-headers -isystem %S %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -isystem %S %s

#include <no-warn-user-defined-literals-in-system-headers.h>

Expand Down
8 changes: 5 additions & 3 deletions clang/test/SemaCXX/reserved-identifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ namespace {
int _barbatruc; // no-warning
}

long double operator"" _BarbeBleue(long double) // expected-warning {{identifier '_BarbeBleue' is reserved because it starts with '_' followed by a capital letter}}
long double operator"" _BarbeBleue(long double) // expected-warning {{identifier '_BarbeBleue' is reserved because it starts with '_' followed by a capital letter}}\
// expected-warning {{identifier '_BarbeBleue' preceded by whitespace in a literal operator declaration is deprecated}}
{
return 0.;
}
Expand All @@ -86,10 +87,11 @@ long double operator""_SacreBleu(long double) // no-warning
return 0.;
}

long double sacrebleu = operator"" _SacreBleu(1.2); // expected-warning {{identifier '_SacreBleu' is reserved because it starts with '_' followed by a capital letter}}
long double sacrebleu = operator"" _SacreBleu(1.2); // expected-warning {{identifier '_SacreBleu' is reserved because it starts with '_' followed by a capital letter}} \
// expected-warning {{identifier '_SacreBleu' preceded by whitespace in a literal operator declaration is deprecated}}
long double sangbleu = operator""_SacreBleu(1.2); // no-warning

void operator"" _lowercase(unsigned long long); // no-warning
void operator"" _lowercase(unsigned long long); // expected-warning {{identifier '_lowercase' preceded by whitespace in a literal operator declaration is deprecated}}
void operator""_lowercase(unsigned long long); // no-warning

struct _BarbeRouge { // expected-warning {{identifier '_BarbeRouge' is reserved because it starts with '_' followed by a capital letter}}
Expand Down
6 changes: 3 additions & 3 deletions clang/test/SemaCXX/warn-xor-as-pow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
#define flexor 7

#ifdef __cplusplus
constexpr long long operator"" _xor(unsigned long long v) { return v; }
constexpr long long operator""_xor(unsigned long long v) { return v; }

constexpr long long operator"" _0b(unsigned long long v) { return v; }
constexpr long long operator"" _0X(unsigned long long v) { return v; }
constexpr long long operator""_0b(unsigned long long v) { return v; }
constexpr long long operator""_0X(unsigned long long v) { return v; }
#else
#define xor ^ // iso646.h
#endif
Expand Down
Loading