176 changes: 94 additions & 82 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaLambda.h"
#include "clang/Sema/Template.h"
Expand Down Expand Up @@ -884,8 +885,8 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,

// Exceptions aren't allowed in CUDA device code.
if (getLangOpts().CUDA)
CUDADiagIfDeviceCode(OpLoc, diag::err_cuda_device_exceptions)
<< "throw" << llvm::to_underlying(CurrentCUDATarget());
CUDA().DiagIfDeviceCode(OpLoc, diag::err_cuda_device_exceptions)
<< "throw" << llvm::to_underlying(CUDA().CurrentTarget());

if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope())
Diag(OpLoc, diag::err_omp_simd_region_cannot_use_stmt) << "throw";
Expand Down Expand Up @@ -1415,42 +1416,26 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit,
}

ExprResult Sema::ActOnCXXThis(SourceLocation Loc) {
// C++20 [expr.prim.this]p1:
// The keyword this names a pointer to the object for which an
// implicit object member function is invoked or a non-static
// data member's initializer is evaluated.
/// C++ 9.3.2: In the body of a non-static member function, the keyword this
/// is a non-lvalue expression whose value is the address of the object for
/// which the function is called.
QualType ThisTy = getCurrentThisType();

if (CheckCXXThisType(Loc, ThisTy))
return ExprError();
if (ThisTy.isNull()) {
DeclContext *DC = getFunctionLevelDeclContext();

return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false);
}
if (const auto *Method = dyn_cast<CXXMethodDecl>(DC);
Method && Method->isExplicitObjectMemberFunction()) {
return Diag(Loc, diag::err_invalid_this_use) << 1;
}

bool Sema::CheckCXXThisType(SourceLocation Loc, QualType Type) {
if (!Type.isNull())
return false;
if (isLambdaCallWithExplicitObjectParameter(CurContext))
return Diag(Loc, diag::err_invalid_this_use) << 1;

// C++20 [expr.prim.this]p3:
// If a declaration declares a member function or member function template
// of a class X, the expression this is a prvalue of type
// "pointer to cv-qualifier-seq X" wherever X is the current class between
// the optional cv-qualifier-seq and the end of the function-definition,
// member-declarator, or declarator. It shall not appear within the
// declaration of either a static member function or an explicit object
// member function of the current class (although its type and value
// category are defined within such member functions as they are within
// an implicit object member function).
DeclContext *DC = getFunctionLevelDeclContext();
if (const auto *Method = dyn_cast<CXXMethodDecl>(DC);
Method && Method->isExplicitObjectMemberFunction()) {
Diag(Loc, diag::err_invalid_this_use) << 1;
} else if (isLambdaCallWithExplicitObjectParameter(CurContext)) {
Diag(Loc, diag::err_invalid_this_use) << 1;
} else {
Diag(Loc, diag::err_invalid_this_use) << 0;
return Diag(Loc, diag::err_invalid_this_use) << 0;
}
return true;

return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false);
}

Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type,
Expand Down Expand Up @@ -1708,17 +1693,17 @@ bool Sema::isUsualDeallocationFunction(const CXXMethodDecl *Method) {
// [CUDA] Ignore this function, if we can't call it.
const FunctionDecl *Caller = getCurFunctionDecl(/*AllowLambda=*/true);
if (getLangOpts().CUDA) {
auto CallPreference = IdentifyCUDAPreference(Caller, Method);
auto CallPreference = CUDA().IdentifyPreference(Caller, Method);
// If it's not callable at all, it's not the right function.
if (CallPreference < CFP_WrongSide)
if (CallPreference < SemaCUDA::CFP_WrongSide)
return false;
if (CallPreference == CFP_WrongSide) {
if (CallPreference == SemaCUDA::CFP_WrongSide) {
// Maybe. We have to check if there are better alternatives.
DeclContext::lookup_result R =
Method->getDeclContext()->lookup(Method->getDeclName());
for (const auto *D : R) {
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
if (IdentifyCUDAPreference(Caller, FD) > CFP_WrongSide)
if (CUDA().IdentifyPreference(Caller, FD) > SemaCUDA::CFP_WrongSide)
return false;
}
}
Expand All @@ -1737,7 +1722,7 @@ bool Sema::isUsualDeallocationFunction(const CXXMethodDecl *Method) {
return llvm::none_of(PreventedBy, [&](const FunctionDecl *FD) {
assert(FD->getNumParams() == 1 &&
"Only single-operand functions should be in PreventedBy");
return IdentifyCUDAPreference(Caller, FD) >= CFP_HostDevice;
return CUDA().IdentifyPreference(Caller, FD) >= SemaCUDA::CFP_HostDevice;
});
}

Expand Down Expand Up @@ -1774,7 +1759,7 @@ namespace {
UsualDeallocFnInfo(Sema &S, DeclAccessPair Found)
: Found(Found), FD(dyn_cast<FunctionDecl>(Found->getUnderlyingDecl())),
Destroying(false), HasSizeT(false), HasAlignValT(false),
CUDAPref(Sema::CFP_Native) {
CUDAPref(SemaCUDA::CFP_Native) {
// A function template declaration is never a usual deallocation function.
if (!FD)
return;
Expand All @@ -1800,7 +1785,7 @@ namespace {

// In CUDA, determine how much we'd like / dislike to call this.
if (S.getLangOpts().CUDA)
CUDAPref = S.IdentifyCUDAPreference(
CUDAPref = S.CUDA().IdentifyPreference(
S.getCurFunctionDecl(/*AllowLambda=*/true), FD);
}

Expand Down Expand Up @@ -1831,7 +1816,7 @@ namespace {
DeclAccessPair Found;
FunctionDecl *FD;
bool Destroying, HasSizeT, HasAlignValT;
Sema::CUDAFunctionPreference CUDAPref;
SemaCUDA::CUDAFunctionPreference CUDAPref;
};
}

Expand All @@ -1855,7 +1840,7 @@ static UsualDeallocFnInfo resolveDeallocationOverload(
for (auto I = R.begin(), E = R.end(); I != E; ++I) {
UsualDeallocFnInfo Info(S, I.getPair());
if (!Info || !isNonPlacementDeallocationFunction(S, Info.FD) ||
Info.CUDAPref == Sema::CFP_Never)
Info.CUDAPref == SemaCUDA::CFP_Never)
continue;

if (!Best) {
Expand Down Expand Up @@ -2715,13 +2700,9 @@ static bool resolveAllocationOverload(
return true;

case OR_Deleted: {
if (Diagnose) {
Candidates.NoteCandidates(
PartialDiagnosticAt(R.getNameLoc(),
S.PDiag(diag::err_ovl_deleted_call)
<< R.getLookupName() << Range),
S, OCD_AllCandidates, Args);
}
if (Diagnose)
S.DiagnoseUseOfDeletedFunction(R.getNameLoc(), Range, R.getLookupName(),
Candidates, Best->Function, Args);
return true;
}
}
Expand Down Expand Up @@ -2956,8 +2937,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
}

if (getLangOpts().CUDA)
EraseUnwantedCUDAMatches(getCurFunctionDecl(/*AllowLambda=*/true),
Matches);
CUDA().EraseUnwantedMatches(getCurFunctionDecl(/*AllowLambda=*/true),
Matches);
} else {
// C++1y [expr.new]p22:
// For a non-placement allocation function, the normal deallocation
Expand Down Expand Up @@ -3375,7 +3356,9 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
// FIXME: DiagnoseUseOfDecl?
if (Operator->isDeleted()) {
if (Diagnose) {
Diag(StartLoc, diag::err_deleted_function_use);
StringLiteral *Msg = Operator->getDeletedMessage();
Diag(StartLoc, diag::err_deleted_function_use)
<< (Msg != nullptr) << (Msg ? Msg->getString() : StringRef());
NoteDeletedFunction(Operator);
}
return true;
Expand Down Expand Up @@ -3979,14 +3962,11 @@ static bool resolveBuiltinNewDeleteOverload(Sema &S, CallExpr *TheCall,
S, OCD_AmbiguousCandidates, Args);
return true;

case OR_Deleted: {
Candidates.NoteCandidates(
PartialDiagnosticAt(R.getNameLoc(), S.PDiag(diag::err_ovl_deleted_call)
<< R.getLookupName() << Range),
S, OCD_AllCandidates, Args);
case OR_Deleted:
S.DiagnoseUseOfDeletedFunction(R.getNameLoc(), Range, R.getLookupName(),
Candidates, Best->Function, Args);
return true;
}
}
llvm_unreachable("Unreachable, bad result from BestViableFunction");
}

Expand Down Expand Up @@ -5011,6 +4991,20 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
return From;
}

/// Checks that type T is not a VLA.
///
/// @returns @c true if @p T is VLA and a diagnostic was emitted,
/// @c false otherwise.
static bool DiagnoseVLAInCXXTypeTrait(Sema &S, const TypeSourceInfo *T,
clang::tok::TokenKind TypeTraitID) {
if (!T->getType()->isVariableArrayType())
return false;

S.Diag(T->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported)
<< 1 << TypeTraitID;
return true;
}

/// Check the completeness of a type in a unary type trait.
///
/// If the particular type trait requires a complete type, tries to complete
Expand Down Expand Up @@ -5187,7 +5181,9 @@ static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op,
}

static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
SourceLocation KeyLoc, QualType T) {
SourceLocation KeyLoc,
TypeSourceInfo *TInfo) {
QualType T = TInfo->getType();
assert(!T->isDependentType() && "Cannot evaluate traits of dependent type");

ASTContext &C = Self.Context;
Expand All @@ -5204,21 +5200,13 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
case UTT_IsArray:
return T->isArrayType();
case UTT_IsBoundedArray:
if (!T->isVariableArrayType()) {
return T->isArrayType() && !T->isIncompleteArrayType();
}

Self.Diag(KeyLoc, diag::err_vla_unsupported)
<< 1 << tok::kw___is_bounded_array;
return false;
if (DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___is_bounded_array))
return false;
return T->isArrayType() && !T->isIncompleteArrayType();
case UTT_IsUnboundedArray:
if (!T->isVariableArrayType()) {
return T->isIncompleteArrayType();
}

Self.Diag(KeyLoc, diag::err_vla_unsupported)
<< 1 << tok::kw___is_unbounded_array;
return false;
if (DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___is_unbounded_array))
return false;
return T->isIncompleteArrayType();
case UTT_IsPointer:
return T->isAnyPointerType();
case UTT_IsNullPointer:
Expand Down Expand Up @@ -5630,7 +5618,7 @@ static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind,
return false;

if (Kind <= UTT_Last)
return EvaluateUnaryTypeTrait(S, Kind, KWLoc, Args[0]->getType());
return EvaluateUnaryTypeTrait(S, Kind, KWLoc, Args[0]);

// Evaluate ReferenceBindsToTemporary and ReferenceConstructsFromTemporary
// alongside the IsConstructible traits to avoid duplication.
Expand Down Expand Up @@ -6092,13 +6080,24 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceI
Self.RequireCompleteType(Rhs->getTypeLoc().getBeginLoc(), RhsT,
diag::err_incomplete_type);

if (LhsT->isVariableArrayType())
Self.Diag(Lhs->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported)
<< 1 << tok::kw___is_layout_compatible;
if (RhsT->isVariableArrayType())
Self.Diag(Rhs->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported)
<< 1 << tok::kw___is_layout_compatible;
DiagnoseVLAInCXXTypeTrait(Self, Lhs, tok::kw___is_layout_compatible);
DiagnoseVLAInCXXTypeTrait(Self, Rhs, tok::kw___is_layout_compatible);

return Self.IsLayoutCompatible(LhsT, RhsT);
}
case BTT_IsPointerInterconvertibleBaseOf: {
if (LhsT->isStructureOrClassType() && RhsT->isStructureOrClassType() &&
!Self.getASTContext().hasSameUnqualifiedType(LhsT, RhsT)) {
Self.RequireCompleteType(Rhs->getTypeLoc().getBeginLoc(), RhsT,
diag::err_incomplete_type);
}

DiagnoseVLAInCXXTypeTrait(Self, Lhs,
tok::kw___is_pointer_interconvertible_base_of);
DiagnoseVLAInCXXTypeTrait(Self, Rhs,
tok::kw___is_pointer_interconvertible_base_of);

return Self.IsPointerInterconvertibleBaseOf(Lhs, Rhs);
}
default: llvm_unreachable("not a BTT");
}
Expand Down Expand Up @@ -8430,7 +8429,7 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) {
// unnecessary temporary objects. If we skip this step, IR generation is
// able to synthesize the storage for itself in the aggregate case, and
// adding the extra node to the AST is just clutter.
if (isInMaterializeTemporaryObjectContext() && getLangOpts().CPlusPlus17 &&
if (isInLifetimeExtendingContext() && getLangOpts().CPlusPlus17 &&
E->isPRValue() && !E->getType()->isVoidType()) {
ExprResult Res = TemporaryMaterializationConversion(E);
if (Res.isInvalid())
Expand Down Expand Up @@ -8643,8 +8642,21 @@ static ExprResult attemptRecovery(Sema &SemaRef,

// Detect and handle the case where the decl might be an implicit
// member.
if (SemaRef.isPotentialImplicitMemberAccess(
NewSS, R, Consumer.isAddressOfOperand()))
bool MightBeImplicitMember;
if (!Consumer.isAddressOfOperand())
MightBeImplicitMember = true;
else if (!NewSS.isEmpty())
MightBeImplicitMember = false;
else if (R.isOverloadedResult())
MightBeImplicitMember = false;
else if (R.isUnresolvableResult())
MightBeImplicitMember = true;
else
MightBeImplicitMember = isa<FieldDecl>(ND) ||
isa<IndirectFieldDecl>(ND) ||
isa<MSPropertyDecl>(ND);

if (MightBeImplicitMember)
return SemaRef.BuildPossibleImplicitMemberExpr(
NewSS, /*TemplateKWLoc*/ SourceLocation(), R,
/*TemplateArgs*/ nullptr, /*S*/ nullptr);
Expand Down
63 changes: 14 additions & 49 deletions clang/lib/Sema/SemaExprMember.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,6 @@ enum IMAKind {
/// The reference is a contextually-permitted abstract member reference.
IMA_Abstract,

/// Whether the context is static is dependent on the enclosing template (i.e.
/// in a dependent class scope explicit specialization).
IMA_Dependent,

/// The reference may be to an unresolved using declaration and the
/// context is not an instance method.
IMA_Unresolved_StaticOrExplicitContext,
Expand Down Expand Up @@ -95,18 +91,10 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,

DeclContext *DC = SemaRef.getFunctionLevelDeclContext();

bool couldInstantiateToStatic = false;
bool isStaticOrExplicitContext = SemaRef.CXXThisTypeOverride.isNull();

if (auto *MD = dyn_cast<CXXMethodDecl>(DC)) {
if (MD->isImplicitObjectMemberFunction()) {
isStaticOrExplicitContext = false;
// A dependent class scope function template explicit specialization
// that is neither declared 'static' nor with an explicit object
// parameter could instantiate to a static or non-static member function.
couldInstantiateToStatic = MD->getDependentSpecializationInfo();
}
}
bool isStaticOrExplicitContext =
SemaRef.CXXThisTypeOverride.isNull() &&
(!isa<CXXMethodDecl>(DC) || cast<CXXMethodDecl>(DC)->isStatic() ||
cast<CXXMethodDecl>(DC)->isExplicitObjectMemberFunction());

if (R.isUnresolvableResult())
return isStaticOrExplicitContext ? IMA_Unresolved_StaticOrExplicitContext
Expand Down Expand Up @@ -135,9 +123,6 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
if (Classes.empty())
return IMA_Static;

if (couldInstantiateToStatic)
return IMA_Dependent;

// C++11 [expr.prim.general]p12:
// An id-expression that denotes a non-static data member or non-static
// member function of a class can only be used:
Expand Down Expand Up @@ -278,52 +263,32 @@ static void diagnoseInstanceReference(Sema &SemaRef,
}
}

bool Sema::isPotentialImplicitMemberAccess(const CXXScopeSpec &SS,
LookupResult &R,
bool IsAddressOfOperand) {
if (!getLangOpts().CPlusPlus)
return false;
else if (R.empty() || !R.begin()->isCXXClassMember())
return false;
else if (!IsAddressOfOperand)
return true;
else if (!SS.isEmpty())
return false;
else if (R.isOverloadedResult())
return false;
else if (R.isUnresolvableResult())
return true;
else
return isa<FieldDecl, IndirectFieldDecl, MSPropertyDecl>(R.getFoundDecl());
}

/// Builds an expression which might be an implicit member expression.
ExprResult Sema::BuildPossibleImplicitMemberExpr(
const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs, const Scope *S) {
switch (IMAKind Classification = ClassifyImplicitMemberAccess(*this, R)) {
const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
UnresolvedLookupExpr *AsULE) {
switch (ClassifyImplicitMemberAccess(*this, R)) {
case IMA_Instance:
return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true, S);

case IMA_Mixed:
case IMA_Mixed_Unrelated:
case IMA_Unresolved:
return BuildImplicitMemberExpr(
SS, TemplateKWLoc, R, TemplateArgs,
/*IsKnownInstance=*/Classification == IMA_Instance, S);
return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false,
S);

case IMA_Field_Uneval_Context:
Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use)
<< R.getLookupNameInfo().getName();
[[fallthrough]];
case IMA_Static:
case IMA_Abstract:
case IMA_Dependent:
case IMA_Mixed_StaticOrExplicitContext:
case IMA_Unresolved_StaticOrExplicitContext:
if (TemplateArgs || TemplateKWLoc.isValid())
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*RequiresADL=*/false,
TemplateArgs);
return BuildDeclarationNameExpr(
SS, R, /*NeedsADL=*/false, /*AcceptInvalidDecl=*/false,
/*NeedUnresolved=*/Classification == IMA_Dependent);
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs);
return AsULE ? AsULE : BuildDeclarationNameExpr(SS, R, false);

case IMA_Error_StaticOrExplicitContext:
case IMA_Error_Unrelated:
Expand Down
19 changes: 14 additions & 5 deletions clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9763,12 +9763,15 @@ bool InitializationSequence::Diagnose(Sema &S,
break;
}
case OR_Deleted: {
S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function)
<< OnlyArg->getType() << DestType.getNonReferenceType()
<< Args[0]->getSourceRange();
OverloadCandidateSet::iterator Best;
OverloadingResult Ovl
= FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);

StringLiteral *Msg = Best->Function->getDeletedMessage();
S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function)
<< OnlyArg->getType() << DestType.getNonReferenceType()
<< (Msg != nullptr) << (Msg ? Msg->getString() : StringRef())
<< Args[0]->getSourceRange();
if (Ovl == OR_Deleted) {
S.NoteDeletedFunction(Best->Function);
} else {
Expand Down Expand Up @@ -10027,9 +10030,12 @@ bool InitializationSequence::Diagnose(Sema &S,
<< llvm::to_underlying(
S.getSpecialMember(cast<CXXMethodDecl>(Best->Function)))
<< DestType << ArgsRange;
else
else {
StringLiteral *Msg = Best->Function->getDeletedMessage();
S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init)
<< DestType << ArgsRange;
<< DestType << (Msg != nullptr)
<< (Msg ? Msg->getString() : StringRef()) << ArgsRange;
}

S.NoteDeletedFunction(Best->Function);
break;
Expand Down Expand Up @@ -11061,6 +11067,9 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
}

case OR_Deleted: {
// FIXME: There are no tests for this diagnostic, and it doesn't seem
// like we ever get here; attempts to trigger this seem to yield a
// generic c'all to deleted function' diagnostic instead.
Diag(Kind.getLocation(), diag::err_deduced_class_template_deleted)
<< TemplateName;
NoteDeletedFunction(Best->Function);
Expand Down
9 changes: 5 additions & 4 deletions clang/lib/Sema/SemaLambda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@
// This file implements semantic analysis for C++ lambda expressions.
//
//===----------------------------------------------------------------------===//
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/SemaLambda.h"
#include "TypeLocBuilder.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaLambda.h"
#include "clang/Sema/Template.h"
#include "llvm/ADT/STLExtras.h"
#include <optional>
Expand Down Expand Up @@ -1393,7 +1394,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,

// CUDA lambdas get implicit host and device attributes.
if (getLangOpts().CUDA)
CUDASetLambdaAttrs(Method);
CUDA().SetLambdaAttrs(Method);

// OpenMP lambdas might get assumumption attributes.
if (LangOpts.OpenMP)
Expand Down Expand Up @@ -2136,7 +2137,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
CaptureInits.push_back(Init.get());

if (LangOpts.CUDA)
CUDACheckLambdaCapture(CallOperator, From);
CUDA().CheckLambdaCapture(CallOperator, From);
}

Class->setCaptures(Context, Captures);
Expand Down
157 changes: 99 additions & 58 deletions clang/lib/Sema/SemaOverload.cpp

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions clang/lib/Sema/SemaStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "clang/Sema/Ownership.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
Expand Down Expand Up @@ -4574,8 +4575,8 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,

// Exceptions aren't allowed in CUDA device code.
if (getLangOpts().CUDA)
CUDADiagIfDeviceCode(TryLoc, diag::err_cuda_device_exceptions)
<< "try" << llvm::to_underlying(CurrentCUDATarget());
CUDA().DiagIfDeviceCode(TryLoc, diag::err_cuda_device_exceptions)
<< "try" << llvm::to_underlying(CUDA().CurrentTarget());

if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope())
Diag(TryLoc, diag::err_omp_simd_region_cannot_use_stmt) << "try";
Expand Down
15 changes: 8 additions & 7 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "clang/Sema/Overload.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
Expand Down Expand Up @@ -10155,9 +10156,9 @@ bool Sema::CheckFunctionTemplateSpecialization(
// take target attributes into account, we reject candidates
// here that have a different target.
if (LangOpts.CUDA &&
IdentifyCUDATarget(Specialization,
/* IgnoreImplicitHDAttr = */ true) !=
IdentifyCUDATarget(FD, /* IgnoreImplicitHDAttr = */ true)) {
CUDA().IdentifyTarget(Specialization,
/* IgnoreImplicitHDAttr = */ true) !=
CUDA().IdentifyTarget(FD, /* IgnoreImplicitHDAttr = */ true)) {
FailedCandidates.addCandidate().set(
I.getPair(), FunTmpl->getTemplatedDecl(),
MakeDeductionFailureInfo(
Expand Down Expand Up @@ -10328,7 +10329,7 @@ bool Sema::CheckFunctionTemplateSpecialization(
// virtue e.g. of being constexpr, and it passes these implicit
// attributes on to its specializations.)
if (LangOpts.CUDA)
inheritCUDATargetAttrs(FD, *Specialization->getPrimaryTemplate());
CUDA().inheritTargetAttrs(FD, *Specialization->getPrimaryTemplate());

// The "previous declaration" for this function template specialization is
// the prior function template specialization.
Expand Down Expand Up @@ -11364,9 +11365,9 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// target attributes into account, we reject candidates here that
// have a different target.
if (LangOpts.CUDA &&
IdentifyCUDATarget(Specialization,
/* IgnoreImplicitHDAttr = */ true) !=
IdentifyCUDATarget(D.getDeclSpec().getAttributes())) {
CUDA().IdentifyTarget(Specialization,
/* IgnoreImplicitHDAttr = */ true) !=
CUDA().IdentifyTarget(D.getDeclSpec().getAttributes())) {
FailedCandidates.addCandidate().set(
P.getPair(), FunTmpl->getTemplatedDecl(),
MakeDeductionFailureInfo(
Expand Down
23 changes: 8 additions & 15 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateInstCallback.h"
Expand Down Expand Up @@ -2438,7 +2439,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
return nullptr;
}
if (D->isDeleted())
SemaRef.SetDeclDeleted(Function, D->getLocation());
SemaRef.SetDeclDeleted(Function, D->getLocation(), D->getDeletedMessage());

NamedDecl *PrincipalDecl =
(TemplateParams ? cast<NamedDecl>(FunctionTemplate) : Function);
Expand Down Expand Up @@ -2814,7 +2815,8 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
return nullptr;
}
if (D->isDeletedAsWritten())
SemaRef.SetDeclDeleted(Method, Method->getLocation());
SemaRef.SetDeclDeleted(Method, Method->getLocation(),
D->getDeletedMessage());

// If this is an explicit specialization, mark the implicitly-instantiated
// template specialization as being an explicit specialization too.
Expand Down Expand Up @@ -4866,7 +4868,7 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
bool TemplateDeclInstantiator::SubstDefaultedFunction(FunctionDecl *New,
FunctionDecl *Tmpl) {
// Transfer across any unqualified lookups.
if (auto *DFI = Tmpl->getDefaultedFunctionInfo()) {
if (auto *DFI = Tmpl->getDefalutedOrDeletedInfo()) {
SmallVector<DeclAccessPair, 32> Lookups;
Lookups.reserve(DFI->getUnqualifiedLookups().size());
bool AnyChanged = false;
Expand All @@ -4881,8 +4883,8 @@ bool TemplateDeclInstantiator::SubstDefaultedFunction(FunctionDecl *New,

// It's unlikely that substitution will change any declarations. Don't
// store an unnecessary copy in that case.
New->setDefaultedFunctionInfo(
AnyChanged ? FunctionDecl::DefaultedFunctionInfo::Create(
New->setDefaultedOrDeletedInfo(
AnyChanged ? FunctionDecl::DefaultedOrDeletedFunctionInfo::Create(
SemaRef.Context, Lookups)
: DFI);
}
Expand Down Expand Up @@ -5095,14 +5097,6 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
EnterExpressionEvaluationContext EvalContext(
*this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);

Qualifiers ThisTypeQuals;
CXXRecordDecl *ThisContext = nullptr;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
ThisContext = Method->getParent();
ThisTypeQuals = Method->getMethodQualifiers();
}
CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals);

// Introduce a new scope where local variable instantiations will be
// recorded, unless we're actually a member function within a local
// class, in which case we need to merge our results with the parent
Expand Down Expand Up @@ -5489,7 +5483,6 @@ void Sema::InstantiateVariableInitializer(
*this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, Var);

keepInLifetimeExtendingContext();
keepInMaterializeTemporaryObjectContext();
// Instantiate the initializer.
ExprResult Init;

Expand Down Expand Up @@ -5537,7 +5530,7 @@ void Sema::InstantiateVariableInitializer(
}

if (getLangOpts().CUDA)
checkAllowedCUDAInitializer(Var);
CUDA().checkAllowedInitializer(Var);
}

/// Instantiate the definition of the given variable from its
Expand Down
9 changes: 5 additions & 4 deletions clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateInstCallback.h"
Expand Down Expand Up @@ -2735,7 +2736,7 @@ QualType Sema::BuildArrayType(QualType T, ArraySizeModifier ASM,
bool IsCUDADevice = (getLangOpts().CUDA && getLangOpts().CUDAIsDevice);
targetDiag(Loc,
IsCUDADevice ? diag::err_cuda_vla : diag::err_vla_unsupported)
<< (IsCUDADevice ? llvm::to_underlying(CurrentCUDATarget()) : 0);
<< (IsCUDADevice ? llvm::to_underlying(CUDA().CurrentTarget()) : 0);
} else if (sema::FunctionScopeInfo *FSI = getCurFunction()) {
// VLAs are supported on this target, but we may need to do delayed
// checking that the VLA is not being used within a coroutine.
Expand Down Expand Up @@ -3618,7 +3619,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// D.getDeclarationAttributes()) because those are always C++11 attributes,
// and those don't get distributed.
distributeTypeAttrsFromDeclarator(
state, T, SemaRef.IdentifyCUDATarget(D.getAttributes()));
state, T, SemaRef.CUDA().IdentifyTarget(D.getAttributes()));

// Find the deduced type in this type. Look in the trailing return type if we
// have one, otherwise in the DeclSpec type.
Expand Down Expand Up @@ -4139,7 +4140,7 @@ static CallingConv getCCForDeclaratorChunk(
// handleFunctionTypeAttr.
CallingConv CC;
if (!S.CheckCallingConvAttr(AL, CC, /*FunctionDecl=*/nullptr,
S.IdentifyCUDATarget(D.getAttributes())) &&
S.CUDA().IdentifyTarget(D.getAttributes())) &&
(!FTI.isVariadic || supportsVariadicCall(CC))) {
return CC;
}
Expand Down Expand Up @@ -5825,7 +5826,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,

// See if there are any attributes on this declarator chunk.
processTypeAttrs(state, T, TAL_DeclChunk, DeclType.getAttrs(),
S.IdentifyCUDATarget(D.getAttributes()));
S.CUDA().IdentifyTarget(D.getAttributes()));

if (DeclType.Kind != DeclaratorChunk::Paren) {
if (ExpectNoDerefChunk && !IsNoDerefableChunk(DeclType))
Expand Down
70 changes: 26 additions & 44 deletions clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -795,9 +795,6 @@ class TreeTransform {
ParenExpr *PE, DependentScopeDeclRefExpr *DRE, bool IsAddressOfOperand,
TypeSourceInfo **RecoveryTSI);

ExprResult TransformUnresolvedLookupExpr(UnresolvedLookupExpr *E,
bool IsAddressOfOperand);

StmtResult TransformOMPExecutableDirective(OMPExecutableDirective *S);

// FIXME: We use LLVM_ATTRIBUTE_NOINLINE because inlining causes a ridiculous
Expand Down Expand Up @@ -3312,13 +3309,12 @@ class TreeTransform {

/// Build a new C++ "this" expression.
///
/// By default, performs semantic analysis to build a new "this" expression.
/// Subclasses may override this routine to provide different behavior.
/// By default, builds a new "this" expression without performing any
/// semantic analysis. Subclasses may override this routine to provide
/// different behavior.
ExprResult RebuildCXXThisExpr(SourceLocation ThisLoc,
QualType ThisType,
bool isImplicit) {
if (getSema().CheckCXXThisType(ThisLoc, ThisType))
return ExprError();
return getSema().BuildCXXThisExpr(ThisLoc, ThisType, isImplicit);
}

Expand Down Expand Up @@ -4181,7 +4177,6 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
getSema(), EnterExpressionEvaluationContext::InitList,
Construct->isListInitialization());

getSema().keepInLifetimeExtendingContext();
getSema().keepInLifetimeExtendingContext();
SmallVector<Expr*, 8> NewArgs;
bool ArgChanged = false;
Expand Down Expand Up @@ -8756,10 +8751,6 @@ TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) {
if (getSema().getLangOpts().CPlusPlus23) {
auto &LastRecord = getSema().ExprEvalContexts.back();
LastRecord.InLifetimeExtendingContext = true;

// Materialize non-`cv void` prvalue temporaries in discarded
// expressions. These materialized temporaries may be lifetime-extented.
LastRecord.InMaterializeTemporaryObjectContext = true;
}
StmtResult Init =
S->getInit() ? getDerived().TransformStmt(S->getInit()) : StmtResult();
Expand Down Expand Up @@ -11369,11 +11360,7 @@ template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformAddressOfOperand(Expr *E) {
if (DependentScopeDeclRefExpr *DRE = dyn_cast<DependentScopeDeclRefExpr>(E))
return getDerived().TransformDependentScopeDeclRefExpr(
DRE, /*IsAddressOfOperand=*/true, nullptr);
else if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E))
return getDerived().TransformUnresolvedLookupExpr(
ULE, /*IsAddressOfOperand=*/true);
return getDerived().TransformDependentScopeDeclRefExpr(DRE, true, nullptr);
else
return getDerived().TransformExpr(E);
}
Expand Down Expand Up @@ -13079,16 +13066,10 @@ bool TreeTransform<Derived>::TransformOverloadExprDecls(OverloadExpr *Old,
return false;
}

template <typename Derived>
ExprResult TreeTransform<Derived>::TransformUnresolvedLookupExpr(
UnresolvedLookupExpr *Old) {
return TransformUnresolvedLookupExpr(Old, /*IsAddressOfOperand=*/false);
}

template <typename Derived>
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformUnresolvedLookupExpr(UnresolvedLookupExpr *Old,
bool IsAddressOfOperand) {
TreeTransform<Derived>::TransformUnresolvedLookupExpr(
UnresolvedLookupExpr *Old) {
LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(),
Sema::LookupOrdinaryName);

Expand Down Expand Up @@ -13120,8 +13101,26 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(UnresolvedLookupExpr *Old,
R.setNamingClass(NamingClass);
}

// Rebuild the template arguments, if any.
SourceLocation TemplateKWLoc = Old->getTemplateKeywordLoc();

// If we have neither explicit template arguments, nor the template keyword,
// it's a normal declaration name or member reference.
if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid()) {
NamedDecl *D = R.getAsSingle<NamedDecl>();
// In a C++11 unevaluated context, an UnresolvedLookupExpr might refer to an
// instance member. In other contexts, BuildPossibleImplicitMemberExpr will
// give a good diagnostic.
if (D && D->isCXXInstanceMember()) {
return SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R,
/*TemplateArgs=*/nullptr,
/*Scope=*/nullptr);
}

return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL());
}

// If we have template arguments, rebuild them, then rebuild the
// templateid expression.
TemplateArgumentListInfo TransArgs(Old->getLAngleLoc(), Old->getRAngleLoc());
if (Old->hasExplicitTemplateArgs() &&
getDerived().TransformTemplateArguments(Old->getTemplateArgs(),
Expand All @@ -13131,23 +13130,6 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(UnresolvedLookupExpr *Old,
return ExprError();
}

// An UnresolvedLookupExpr can refer to a class member. This occurs e.g. when
// a non-static data member is named in an unevaluated operand, or when
// a member is named in a dependent class scope function template explicit
// specialization that is neither declared static nor with an explicit object
// parameter.
if (SemaRef.isPotentialImplicitMemberAccess(SS, R, IsAddressOfOperand))
return SemaRef.BuildPossibleImplicitMemberExpr(
SS, TemplateKWLoc, R,
Old->hasExplicitTemplateArgs() ? &TransArgs : nullptr,
/*S=*/nullptr);

// If we have neither explicit template arguments, nor the template keyword,
// it's a normal declaration name or member reference.
if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid())
return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL());

// If we have template arguments, then rebuild the template-id expression.
return getDerived().RebuildTemplateIdExpr(SS, TemplateKWLoc, R,
Old->requiresADL(), &TransArgs);
}
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
#include "clang/Sema/ObjCMethodList.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/Weak.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ASTDeserializationListener.h"
Expand Down Expand Up @@ -3995,7 +3996,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
if (Record.size() != 1)
return llvm::createStringError(std::errc::illegal_byte_sequence,
"invalid cuda pragma options record");
ForceCUDAHostDeviceDepth = Record[0];
ForceHostDeviceDepth = Record[0];
break;

case ALIGN_PACK_PRAGMA_OPTIONS: {
Expand Down Expand Up @@ -8274,7 +8275,7 @@ void ASTReader::UpdateSema() {
PragmaMSPointersToMembersState,
PointersToMembersPragmaLocation);
}
SemaObj->ForceCUDAHostDeviceDepth = ForceCUDAHostDeviceDepth;
SemaObj->CUDA().ForceHostDeviceDepth = ForceHostDeviceDepth;

if (PragmaAlignPackCurrentValue) {
// The bottom of the stack might have a default value. It must be adjusted
Expand Down
18 changes: 14 additions & 4 deletions clang/lib/Serialization/ASTReaderDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1103,16 +1103,26 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
FD->setHasODRHash(true);
}

if (FD->isDefaulted()) {
if (unsigned NumLookups = Record.readInt()) {
if (FD->isDefaulted() || FD->isDeletedAsWritten()) {
// If 'Info' is nonzero, we need to read an DefaultedOrDeletedInfo; if,
// additionally, the second bit is also set, we also need to read
// a DeletedMessage for the DefaultedOrDeletedInfo.
if (auto Info = Record.readInt()) {
bool HasMessage = Info & 2;
StringLiteral *DeletedMessage =
HasMessage ? cast<StringLiteral>(Record.readExpr()) : nullptr;

unsigned NumLookups = Record.readInt();
SmallVector<DeclAccessPair, 8> Lookups;
for (unsigned I = 0; I != NumLookups; ++I) {
NamedDecl *ND = Record.readDeclAs<NamedDecl>();
AccessSpecifier AS = (AccessSpecifier)Record.readInt();
Lookups.push_back(DeclAccessPair::make(ND, AS));
}
FD->setDefaultedFunctionInfo(FunctionDecl::DefaultedFunctionInfo::Create(
Reader.getContext(), Lookups));

FD->setDefaultedOrDeletedInfo(
FunctionDecl::DefaultedOrDeletedFunctionInfo::Create(
Reader.getContext(), Lookups, DeletedMessage));
}
}

Expand Down
5 changes: 3 additions & 2 deletions clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
#include "clang/Sema/IdentifierResolver.h"
#include "clang/Sema/ObjCMethodList.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/Weak.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ASTReader.h"
Expand Down Expand Up @@ -4335,8 +4336,8 @@ void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) {
Stream.EmitRecord(OPENCL_EXTENSIONS, Record);
}
void ASTWriter::WriteCUDAPragmas(Sema &SemaRef) {
if (SemaRef.ForceCUDAHostDeviceDepth > 0) {
RecordData::value_type Record[] = {SemaRef.ForceCUDAHostDeviceDepth};
if (SemaRef.CUDA().ForceHostDeviceDepth > 0) {
RecordData::value_type Record[] = {SemaRef.CUDA().ForceHostDeviceDepth};
Stream.EmitRecord(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH, Record);
}
}
Expand Down
11 changes: 9 additions & 2 deletions clang/lib/Serialization/ASTWriterDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -749,8 +749,15 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
if (!ShouldSkipCheckingODR)
Record.push_back(D->getODRHash());

if (D->isDefaulted()) {
if (auto *FDI = D->getDefaultedFunctionInfo()) {
if (D->isDefaulted() || D->isDeletedAsWritten()) {
if (auto *FDI = D->getDefalutedOrDeletedInfo()) {
// Store both that there is an DefaultedOrDeletedInfo and whether it
// contains a DeletedMessage.
StringLiteral *DeletedMessage = FDI->getDeletedMessage();
Record.push_back(1 | (DeletedMessage ? 2 : 0));
if (DeletedMessage)
Record.AddStmt(DeletedMessage);

Record.push_back(FDI->getUnqualifiedLookups().size());
for (DeclAccessPair P : FDI->getUnqualifiedLookups()) {
Record.AddDeclRef(P.getDecl());
Expand Down
36 changes: 24 additions & 12 deletions clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,26 @@ void ModuleDepCollector::addOutputPaths(CowCompilerInvocation &CI,
}
}

void dependencies::resetBenignCodeGenOptions(frontend::ActionKind ProgramAction,
const LangOptions &LangOpts,
CodeGenOptions &CGOpts) {
// TODO: Figure out better way to set options to their default value.
if (ProgramAction == frontend::GenerateModule) {
CGOpts.MainFileName.clear();
CGOpts.DwarfDebugFlags.clear();
}
if (ProgramAction == frontend::GeneratePCH ||
(ProgramAction == frontend::GenerateModule && !LangOpts.ModulesCodegen)) {
CGOpts.DebugCompilationDir.clear();
CGOpts.CoverageCompilationDir.clear();
CGOpts.CoverageDataFile.clear();
CGOpts.CoverageNotesFile.clear();
CGOpts.ProfileInstrumentUsePath.clear();
CGOpts.SampleProfileFile.clear();
CGOpts.ProfileRemappingFile.clear();
}
}

static CowCompilerInvocation
makeCommonInvocationForModuleBuild(CompilerInvocation CI) {
CI.resetNonModularOptions();
Expand All @@ -167,18 +187,8 @@ makeCommonInvocationForModuleBuild(CompilerInvocation CI) {
// LLVM options are not going to affect the AST
CI.getFrontendOpts().LLVMArgs.clear();

// TODO: Figure out better way to set options to their default value.
CI.getCodeGenOpts().MainFileName.clear();
CI.getCodeGenOpts().DwarfDebugFlags.clear();
if (!CI.getLangOpts().ModulesCodegen) {
CI.getCodeGenOpts().DebugCompilationDir.clear();
CI.getCodeGenOpts().CoverageCompilationDir.clear();
CI.getCodeGenOpts().CoverageDataFile.clear();
CI.getCodeGenOpts().CoverageNotesFile.clear();
CI.getCodeGenOpts().ProfileInstrumentUsePath.clear();
CI.getCodeGenOpts().SampleProfileFile.clear();
CI.getCodeGenOpts().ProfileRemappingFile.clear();
}
resetBenignCodeGenOptions(frontend::GenerateModule, CI.getLangOpts(),
CI.getCodeGenOpts());

// Map output paths that affect behaviour to "-" so their existence is in the
// context hash. The final path will be computed in addOutputPaths.
Expand Down Expand Up @@ -342,6 +352,8 @@ static bool needsModules(FrontendInputFile FIF) {

void ModuleDepCollector::applyDiscoveredDependencies(CompilerInvocation &CI) {
CI.clearImplicitModuleBuildOptions();
resetBenignCodeGenOptions(CI.getFrontendOpts().ProgramAction,
CI.getLangOpts(), CI.getCodeGenOpts());

if (llvm::any_of(CI.getFrontendOpts().Inputs, needsModules)) {
Preprocessor &PP = ScanInstance.getPreprocessor();
Expand Down
23 changes: 23 additions & 0 deletions clang/test/AST/ast-dump-cxx2c-delete-with-message.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Without serialization:
// RUN: %clang_cc1 -ast-dump %s | FileCheck %s
//
// With serialization:
// RUN: %clang_cc1 -emit-pch -o %t %s
// RUN: %clang_cc1 -x c++ -include-pch %t -ast-dump-all /dev/null | FileCheck %s

struct S {
// CHECK: CXXMethodDecl {{.*}} a 'void ()' delete
// CHECK-NEXT: delete message: StringLiteral {{.*}} "foo"
void a() = delete("foo");

// CHECK: FunctionTemplateDecl {{.*}} b
// CHECK-NEXT: TemplateTypeParmDecl
// CHECK-NEXT: CXXMethodDecl {{.*}} b 'void ()' delete
// CHECK-NEXT: delete message: StringLiteral {{.*}} "bar"
template <typename>
void b() = delete("bar");
};

// CHECK: FunctionDecl {{.*}} c 'void ()' delete
// CHECK-NEXT: delete message: StringLiteral {{.*}} "baz"
void c() = delete("baz");
18 changes: 18 additions & 0 deletions clang/test/AST/ast-print-cxx2c-delete-with-message.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Without serialization:
// RUN: %clang_cc1 -ast-print %s | FileCheck %s
//
// With serialization:
// RUN: %clang_cc1 -emit-pch -o %t %s
// RUN: %clang_cc1 -x c++ -include-pch %t -ast-print /dev/null | FileCheck %s

// CHECK: struct S {
struct S {
// CHECK-NEXT: void a() = delete("foo");
void a() = delete("foo");

// CHECK-NEXT: template <typename T> T b() = delete("bar");
template <typename T> T b() = delete("bar");
};

// CHECK: void c() = delete("baz");
void c() = delete("baz");
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// RUN: %clang_cc1 -triple x86_64-linux -std=c++14 %s -pedantic-errors -emit-llvm -o - | FileCheck %s --implicit-check-not " call "
// RUN: %clang_cc1 -triple x86_64-linux -std=c++1z %s -pedantic-errors -emit-llvm -o - | FileCheck %s --implicit-check-not " call "

// dr118: yes
// cwg118: yes

struct S {
virtual void f();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#define NOTHROW noexcept(true)
#endif

namespace dr124 { // dr124: 2.7
namespace cwg124 { // cwg124: 2.7

extern void full_expr_fence() NOTHROW;

Expand All @@ -32,20 +32,20 @@ void f() {
full_expr_fence();
}

// CHECK-LABEL: define {{.*}} void @dr124::f()()
// CHECK: call void @dr124::full_expr_fence()
// CHECK-LABEL: define {{.*}} void @cwg124::f()()
// CHECK: call void @cwg124::full_expr_fence()
// CHECK: br label %arrayctor.loop
// CHECK-LABEL: arrayctor.loop:
// CHECK: call void @dr124::A::A()
// CHECK: call void @dr124::B::B(dr124::A)
// CHECK: call void @dr124::A::~A()
// CHECK: call void @cwg124::A::A()
// CHECK: call void @cwg124::B::B(cwg124::A)
// CHECK: call void @cwg124::A::~A()
// CHECK: br {{.*}}, label %arrayctor.cont, label %arrayctor.loop
// CHECK-LABEL: arrayctor.cont:
// CHECK: call void @dr124::full_expr_fence()
// CHECK: call void @cwg124::full_expr_fence()
// CHECK: br label %arraydestroy.body
// CHECK-LABEL: arraydestroy.body:
// CHECK: call void @dr124::B::~B()
// CHECK: call void @cwg124::B::~B()
// CHECK-LABEL: }


} // namespace dr124
} // namespace cwg124
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// RUN: %clang_cc1 -triple x86_64-linux -std=c++14 %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-linux -std=c++1z %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck %s

// dr158: yes
// cwg158: yes

// CHECK-LABEL: define {{.*}} @_Z1f
const int *f(const int * const *p, int **q) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | FileCheck %s
// RUN: %clang_cc1 -std=c++1z %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | FileCheck %s

// dr1748: 3.7
// cwg1748: 3.7

// FIXME: __SIZE_TYPE__ expands to 'long long' on some targets.
__extension__ typedef __SIZE_TYPE__ size_t;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
// RUN: %clang_cc1 -std=c++1z %s -fexceptions -fcxx-exceptions -pedantic-errors -ast-dump | FileCheck %s --check-prefixes=CHECK,CXX11,CXX14
// RUN: %clang_cc1 -std=c++1z %s -fexceptions -fcxx-exceptions -pedantic-errors -triple i386-windows-pc -ast-dump | FileCheck %s --check-prefixes=CHECK,CXX11,CXX14

namespace dr1772 { // dr1772: 14
namespace cwg1772 { // cwg1772: 14
// __func__ in a lambda should name operator(), not the containing function.
// CHECK: NamespaceDecl{{.+}}dr1772
// CHECK: NamespaceDecl{{.+}}cwg1772
#if __cplusplus >= 201103L
auto x = []() { __func__; };
// CXX11: LambdaExpr
Expand All @@ -30,10 +30,10 @@ namespace dr1772 { // dr1772: 14
#endif // __cplusplus >= 201103L
}

namespace dr1779 { // dr1779: 14
namespace cwg1779 { // cwg1779: 14
// __func__ in a function template, member function template, or generic
// lambda should have a dependent type.
// CHECK: NamespaceDecl{{.+}}dr1779
// CHECK: NamespaceDecl{{.+}}cwg1779

template<typename T>
void FuncTemplate() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11

namespace dr1807 { // dr1807: 3.0
namespace cwg1807 { // cwg1807: 3.0
struct S {
S() {}
~S() {}
Expand All @@ -17,12 +17,12 @@ void f() {
}
}

// CHECK-LABEL: define dso_local void @dr1807::f()
// CHECK: invoke void @dr1807::S::S(){{.+}}
// CHECK-LABEL: define dso_local void @cwg1807::f()
// CHECK: invoke void @cwg1807::S::S(){{.+}}
// CHECK-NEXT: {{.+}} unwind label %lpad
// CHECK-LABEL: lpad:
// CHECK: br {{.+}}, label {{.+}}, label %arraydestroy.body
// CHECK-LABEL: arraydestroy.body:
// CHECK: [[ARRAYDESTROY_ELEMENT:%.*]] = getelementptr {{.+}}, i64 -1
// CXX98-NEXT: invoke void @dr1807::S::~S()({{.*}}[[ARRAYDESTROY_ELEMENT]])
// SINCE-CXX11-NEXT: call void @dr1807::S::~S()({{.*}}[[ARRAYDESTROY_ELEMENT]])
// CXX98-NEXT: invoke void @cwg1807::S::~S()({{.*}}[[ARRAYDESTROY_ELEMENT]])
// SINCE-CXX11-NEXT: call void @cwg1807::S::~S()({{.*}}[[ARRAYDESTROY_ELEMENT]])
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK

namespace dr185 { // dr185: 2.7
namespace cwg185 { // cwg185: 2.7
struct A {
mutable int value;
explicit A(int i) : value(i) {}
Expand All @@ -20,11 +20,11 @@ int foo() {
return n.value;
}

// CHECK-LABEL: define {{.*}} i32 @dr185::foo()
// CHECK: call void @dr185::A::A(int)(ptr {{[^,]*}} %ref.tmp, {{.*}})
// CHECK-LABEL: define {{.*}} i32 @cwg185::foo()
// CHECK: call void @cwg185::A::A(int)(ptr {{[^,]*}} %ref.tmp, {{.*}})
// CHECK: store ptr %ref.tmp, ptr %t
// CHECK-NOT: %t =
// CHECK: [[DR185_T:%.+]] = load ptr, ptr %t
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr {{[^,]*}} %n, ptr {{[^,]*}} [[DR185_T]], {{.*}})
// CHECK: [[CWG185_T:%.+]] = load ptr, ptr %t
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr {{[^,]*}} %n, ptr {{[^,]*}} [[CWG185_T]], {{.*}})
// CHECK-LABEL: }
} // namespace dr185
} // namespace cwg185
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#define NOTHROW noexcept(true)
#endif

namespace dr193 { // dr193: 2.7
namespace cwg193 { // cwg193: 2.7
struct A {
~A() NOTHROW {}
};
Expand All @@ -35,12 +35,12 @@ void foo() {
}

// skipping over D1 (complete object destructor)
// CHECK-LABEL: define {{.*}} void @dr193::D::~D(){{.*}}
// CHECK-LABEL: define {{.*}} void @dr193::D::~D(){{.*}}
// CHECK-NOT: call void @dr193::A::~A()
// CHECK-NOT: call void @dr193::B::~B()
// CHECK: call void @dr193::C::~C()
// CHECK: call void @dr193::B::~B()
// CHECK: call void @dr193::A::~A()
// CHECK-LABEL: define {{.*}} void @cwg193::D::~D(){{.*}}
// CHECK-LABEL: define {{.*}} void @cwg193::D::~D(){{.*}}
// CHECK-NOT: call void @cwg193::A::~A()
// CHECK-NOT: call void @cwg193::B::~B()
// CHECK: call void @cwg193::C::~C()
// CHECK: call void @cwg193::B::~B()
// CHECK: call void @cwg193::A::~A()
// CHECK-LABEL: }
} // namespace dr193
} // namespace cwg193
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#define NOTHROW noexcept(true)
#endif

namespace dr199 { // dr199: 2.8
namespace cwg199 { // cwg199: 2.8
struct A {
~A() NOTHROW {}
};
Expand All @@ -25,9 +25,9 @@ void foo() {
A(), B();
}

// CHECK-LABEL: define {{.*}} void @dr199::foo()
// CHECK-NOT: call void @dr199::A::~A()
// CHECK: call void @dr199::B::~B()
// CHECK: call void @dr199::A::~A()
// CHECK-LABEL: define {{.*}} void @cwg199::foo()
// CHECK-NOT: call void @cwg199::A::~A()
// CHECK: call void @cwg199::B::~B()
// CHECK: call void @cwg199::A::~A()
// CHECK-LABEL: }
} // namespace dr199
} // namespace cwg199
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#define NOTHROW noexcept(true)
#endif

namespace dr201 { // dr201: 2.8
namespace cwg201 { // cwg201: 2.8

extern void full_expr_fence() NOTHROW;

Expand All @@ -31,12 +31,12 @@ void foo() {
full_expr_fence();
}

// CHECK-LABEL: define {{.*}} void @dr201::foo()
// CHECK: call void @dr201::full_expr_fence()
// CHECK: call void @dr201::B::B(dr201::A)
// CHECK: call void @dr201::A::~A()
// CHECK: call void @dr201::full_expr_fence()
// CHECK: call void @dr201::B::~B()
// CHECK-LABEL: define {{.*}} void @cwg201::foo()
// CHECK: call void @cwg201::full_expr_fence()
// CHECK: call void @cwg201::B::B(cwg201::A)
// CHECK: call void @cwg201::A::~A()
// CHECK: call void @cwg201::full_expr_fence()
// CHECK: call void @cwg201::B::~B()
// CHECK-LABEL: }

} // namespace dr201
} // namespace cwg201
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#pragma clang diagnostic pop
#endif

namespace dr210 { // dr210: 2.7
namespace cwg210 { // cwg210: 2.7
struct B {
long i;
B();
Expand All @@ -33,9 +33,9 @@ void toss(const B* b) {
throw *b;
}

// CHECK-LABEL: define {{.*}} void @dr210::toss(dr210::B const*)
// CHECK-LABEL: define {{.*}} void @cwg210::toss(cwg210::B const*)
// CHECK: %[[EXCEPTION:.*]] = call ptr @__cxa_allocate_exception(i64 16)
// CHECK: call void @__cxa_throw(ptr %[[EXCEPTION]], ptr @typeinfo for dr210::B, ptr @dr210::B::~B())
// CHECK: call void @__cxa_throw(ptr %[[EXCEPTION]], ptr @typeinfo for cwg210::B, ptr @cwg210::B::~B())
// CHECK-LABEL: }

} // namespace dr210
} // namespace cwg210
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// expected-no-diagnostics
#endif

namespace dr2335 { // dr2335: no drafting 2018-06
namespace cwg2335 { // cwg2335: no drafting 2018-06
// FIXME: current consensus is that the examples are well-formed.
#if __cplusplus >= 201402L
namespace ex1 {
Expand All @@ -25,24 +25,24 @@ namespace ex2 {
template <int> struct X {};
template <class T> struct partition_indices {
static auto compute_right() { return X<I>(); }
// since-cxx14-error@-1 {{no member 'I' in 'dr2335::ex2::partition_indices<int>'; it has not yet been instantiated}}
// since-cxx14-note@#dr2335-ex2-right {{in instantiation of member function 'dr2335::ex2::partition_indices<int>::compute_right' requested here}}
// since-cxx14-note@#dr2335-ex2-inst {{in instantiation of template class 'dr2335::ex2::partition_indices<int>' requested here}}
// since-cxx14-note@#dr2335-ex2-I {{not-yet-instantiated member is declared here}}
static constexpr auto right = compute_right; // #dr2335-ex2-right
static constexpr int I = sizeof(T); // #dr2335-ex2-I
// since-cxx14-error@-1 {{no member 'I' in 'cwg2335::ex2::partition_indices<int>'; it has not yet been instantiated}}
// since-cxx14-note@#cwg2335-ex2-right {{in instantiation of member function 'cwg2335::ex2::partition_indices<int>::compute_right' requested here}}
// since-cxx14-note@#cwg2335-ex2-inst {{in instantiation of template class 'cwg2335::ex2::partition_indices<int>' requested here}}
// since-cxx14-note@#cwg2335-ex2-I {{not-yet-instantiated member is declared here}}
static constexpr auto right = compute_right; // #cwg2335-ex2-right
static constexpr int I = sizeof(T); // #cwg2335-ex2-I
};
template struct partition_indices<int>; // #dr2335-ex2-inst
template struct partition_indices<int>; // #cwg2335-ex2-inst
} // namespace ex2

namespace ex3 {
struct partition_indices {
static auto compute_right() {} // #dr2335-compute_right
static constexpr auto right = compute_right; // #dr2335-ex3-right
static auto compute_right() {} // #cwg2335-compute_right
static constexpr auto right = compute_right; // #cwg2335-ex3-right
// since-cxx14-error@-1 {{function 'compute_right' with deduced return type cannot be used before it is defined}}
// since-cxx14-note@#dr2335-compute_right {{'compute_right' declared here}}
// since-cxx14-error@#dr2335-ex3-right {{declaration of variable 'right' with deduced type 'const auto' requires an initializer}}
// since-cxx14-note@#cwg2335-compute_right {{'compute_right' declared here}}
// since-cxx14-error@#cwg2335-ex3-right {{declaration of variable 'right' with deduced type 'const auto' requires an initializer}}
};
} // namespace ex3
#endif
} // namespace dr2335
} // namespace cwg2335
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -E -P %s -o - | FileCheck %s

// dr2390: 14
// cwg2390: 14

namespace PR48462 {
// Test that macro expansion of the builtin argument works.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11

namespace dr2504 { // dr2504: no
namespace cwg2504 { // cwg2504: no
#if __cplusplus >= 201103L
struct V { V() = default; V(int); };
struct Q { Q(); };
Expand All @@ -27,11 +27,11 @@ void foo() { C c; } // bar is not invoked, because the V subobject is not initia
// we are not supposed to unconditionally call `bar()` and call a constructor
// inherited from `V`.

// SINCE-CXX11-LABEL: define linkonce_odr void @dr2504::B::B()
// SINCE-CXX11-LABEL: define linkonce_odr void @cwg2504::B::B()
// SINCE-CXX11-NOT: br
// SINCE-CXX11: call noundef i32 @dr2504::bar()
// SINCE-CXX11: call noundef i32 @cwg2504::bar()
// SINCE-CXX11-NOT: br
// SINCE-CXX11: call void @dr2504::A::A(int)
// SINCE-CXX11: call void @cwg2504::A::A(int)
// SINCE-CXX11-LABEL: }

// CHECK: {{.*}}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -disable-llvm-passes -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK

namespace dr292 { // dr292: 2.9
namespace cwg292 { // cwg292: 2.9

extern int g();

Expand All @@ -18,13 +18,13 @@ void f() {
new A(g());
}

// CHECK-LABEL: define {{.*}} void @dr292::f()()
// CHECK-LABEL: define {{.*}} void @cwg292::f()()
// CHECK: %[[CALL:.+]] = call {{.*}} @operator new(unsigned long)({{.*}})
// CHECK: invoke {{.*}} i32 @dr292::g()()
// CHECK: invoke {{.*}} i32 @cwg292::g()()
// CHECK-NEXT: to {{.*}} unwind label %lpad
// CHECK-LABEL: lpad:
// CHECK: call void @operator delete(void*)(ptr {{.*}} %[[CALL]])
// CHECK-LABEL: eh.resume:
// CHECK-LABEL: }

} // namespace dr292
} // namespace cwg292
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#define NOTHROW noexcept(true)
#endif

namespace dr392 { // dr392: 2.8
namespace cwg392 { // cwg392: 2.8

struct A {
operator bool() NOTHROW;
Expand All @@ -32,9 +32,9 @@ void f()
if (C().get()) {}
}

} // namespace dr392
} // namespace cwg392

// CHECK-LABEL: define {{.*}} void @dr392::f()()
// CHECK: call {{.*}} i1 @dr392::A::operator bool()
// CHECK: call void @dr392::C::~C()
// CHECK-LABEL: define {{.*}} void @cwg392::f()()
// CHECK: call {{.*}} i1 @cwg392::A::operator bool()
// CHECK: call void @cwg392::C::~C()
// CHECK-LABEL: }
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// RUN: %clang_cc1 -std=c++23 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -DNOEXCEPT=noexcept -DBAD_ALLOC=
// RUN: %clang_cc1 -std=c++2c %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -DNOEXCEPT=noexcept -DBAD_ALLOC=

// dr412: 3.4
// cwg412: 3.4
// lwg404: yes
// lwg2340: yes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@
// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK

namespace dr438 { // dr438: 2.7
namespace cwg438 { // cwg438: 2.7

void f() {
long A[2];
A[0] = 0;
A[A[0]] = 1;
}

} // namespace dr438
} // namespace cwg438

// CHECK-LABEL: define {{.*}} void @dr438::f()()
// CHECK-LABEL: define {{.*}} void @cwg438::f()()
// CHECK: [[A:%.+]] = alloca [2 x i64]
// CHECK: {{.+}} = getelementptr inbounds [2 x i64], ptr [[A]], i64 0, i64 0
// CHECK: [[ARRAYIDX1:%.+]] = getelementptr inbounds [2 x i64], ptr [[A]], i64 0, i64 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@
// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK

namespace dr439 { // dr439: 2.7
namespace cwg439 { // cwg439: 2.7

void f() {
int* p1 = new int;
const int* p2 = static_cast<const int*>(static_cast<void *>(p1));
bool b = p1 == p2; // b will have the value true.
}

} // namespace dr439
} // namespace cwg439

// We're checking that p2 was copied from p1, and then was carried over
// to the comparison without change.

// CHECK-LABEL: define {{.*}} void @dr439::f()()
// CHECK-LABEL: define {{.*}} void @cwg439::f()()
// CHECK: [[P1:%.+]] = alloca ptr, align 8
// CHECK-NEXT: [[P2:%.+]] = alloca ptr, align 8
// CHECK: [[TEMP0:%.+]] = load ptr, ptr [[P1]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK

namespace dr441 { // dr441: 2.7
namespace cwg441 { // cwg441: 2.7

struct A {
A() {}
Expand All @@ -17,21 +17,21 @@ int i;
int& ir = i;
int* ip = &i;

} // namespace dr441
} // namespace cwg441

// CHECK-DAG: @dr441::dynamic_init = global %"struct.dr441::A" zeroinitializer
// CHECK-DAG: @dr441::i = global i32 0
// CHECK-DAG: @dr441::ir = constant ptr @dr441::i
// CHECK-DAG: @dr441::ip = global ptr @dr441::i
// CHECK-DAG: @llvm.global_ctors = appending global [{{.+}}] [{ {{.+}} } { {{.+}}, ptr @_GLOBAL__sub_I_dr441.cpp, {{.+}} }]
// CHECK-DAG: @cwg441::dynamic_init = global %"struct.cwg441::A" zeroinitializer
// CHECK-DAG: @cwg441::i = global i32 0
// CHECK-DAG: @cwg441::ir = constant ptr @cwg441::i
// CHECK-DAG: @cwg441::ip = global ptr @cwg441::i
// CHECK-DAG: @llvm.global_ctors = appending global [{{.+}}] [{ {{.+}} } { {{.+}}, ptr @_GLOBAL__sub_I_cwg441.cpp, {{.+}} }]

// CHECK-LABEL: define {{.*}} void @__cxx_global_var_init()
// CHECK-NEXT: entry:
// CHECK-NEXT: call void @dr441::A::A()({{.*}} @dr441::dynamic_init)
// CHECK-NEXT: call void @cwg441::A::A()({{.*}} @cwg441::dynamic_init)
// CHECK-NEXT: ret void
// CHECK-NEXT: }

// CHECK-LABEL: define {{.*}} void @_GLOBAL__sub_I_dr441.cpp()
// CHECK-LABEL: define {{.*}} void @_GLOBAL__sub_I_cwg441.cpp()
// CHECK-NEXT: entry:
// CHECK-NEXT: call void @__cxx_global_var_init()
// CHECK-NEXT: ret void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#define NOTHROW noexcept(true)
#endif

namespace dr462 { // dr462: 2.7
namespace cwg462 { // cwg462: 2.7

struct A {
~A() NOTHROW {}
Expand All @@ -25,9 +25,9 @@ void f() {
full_expr_fence();
}

} // namespace dr462
} // namespace cwg462

// CHECK-LABEL: define {{.*}} void @dr462::f()()
// CHECK: call void @dr462::full_expr_fence()()
// CHECK: call void @dr462::A::~A()
// CHECK-LABEL: define {{.*}} void @cwg462::f()()
// CHECK: call void @cwg462::full_expr_fence()()
// CHECK: call void @cwg462::A::~A()
// CHECK-LABEL: }
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ struct type_info {
};
}

namespace dr492 { // dr492: 2.7
namespace cwg492 { // cwg492: 2.7

void f() {
typeid(int).name();
Expand All @@ -27,9 +27,9 @@ void f() {
typeid(const volatile int).name();
}

} // namespace dr492
} // namespace cwg492

// CHECK-LABEL: define {{.*}} void @dr492::f()()
// CHECK-LABEL: define {{.*}} void @cwg492::f()()
// CHECK: {{.*}} = call {{.*}} @std::type_info::name() const({{.*}} @typeinfo for int)
// CHECK-NEXT: {{.*}} = call {{.*}} @std::type_info::name() const({{.*}} @typeinfo for int)
// CHECK-NEXT: {{.*}} = call {{.*}} @std::type_info::name() const({{.*}} @typeinfo for int)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK

namespace dr519 { // dr519: 2.7
namespace cwg519 { // cwg519: 2.7
void f() {
int *a = 0;
void *v = a;
Expand All @@ -16,12 +16,12 @@ void f() {
int *b = static_cast<int*>(w);
bool c2 = b == static_cast<int *>(0);
}
} // namespace dr519
} // namespace cwg519

// We're checking that `null`s that were initially stored in `a` and `w`
// are simply copied over all the way to respective comparisons with `null`.

// CHECK-LABEL: define {{.*}} void @dr519::f()()
// CHECK-LABEL: define {{.*}} void @cwg519::f()()
// CHECK: store ptr null, ptr [[A:%.+]],
// CHECK-NEXT: [[TEMP_A:%.+]] = load ptr, ptr [[A]]
// CHECK-NEXT: store ptr [[TEMP_A]], ptr [[V:%.+]],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK

namespace dr571 { // dr571: 2.7
namespace cwg571 { // cwg571: 2.7
typedef int &ir;
int n;
const ir r = n;
Expand All @@ -16,5 +16,5 @@ namespace dr571 { // dr571: 2.7

// Entities have external linkage by default.

// CHECK: @dr571::r = constant ptr @dr571::n
// CHECK: @dr571::r2 = constant ptr @dr571::n
// CHECK: @cwg571::r = constant ptr @cwg571::n
// CHECK: @cwg571::r2 = constant ptr @cwg571::n
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK

namespace dr605 { // dr605: 2.7
namespace cwg605 { // cwg605: 2.7

template <class T>
static T f(T t) {}
Expand All @@ -18,6 +18,6 @@ void g(int a) {
f(a);
}

} // namespace dr605
} // namespace cwg605

// CHECK: define internal {{.*}} i32 @int dr605::f<int>(int)
// CHECK: define internal {{.*}} i32 @int cwg605::f<int>(int)
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#define NOTHROW noexcept(true)
#endif

namespace dr650 { // dr650: 2.8
namespace cwg650 { // cwg650: 2.8

struct Q {
~Q() NOTHROW;
Expand All @@ -31,10 +31,10 @@ const S& f() {
return (R(), S());
}

} // namespace dr650
} // namespace cwg650

// CHECK-LABEL: define {{.*}} @dr650::f()()
// CHECK: call void @dr650::S::~S()
// CHECK: call void @dr650::R::~R()
// CHECK: call void @dr650::Q::~Q()
// CHECK-LABEL: define {{.*}} @cwg650::f()()
// CHECK: call void @cwg650::S::~S()
// CHECK: call void @cwg650::R::~R()
// CHECK: call void @cwg650::Q::~Q()
// CHECK-LABEL: }
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK

namespace dr653 { // dr653: 2.7
namespace cwg653 { // cwg653: 2.7

union U {
int a;
Expand All @@ -18,8 +18,8 @@ void f(U u) {
v = u;
}

} // namespace dr653
} // namespace cwg653

// CHECK-LABEL: define {{.*}} void @dr653::f(dr653::U)
// CHECK-LABEL: define {{.*}} void @cwg653::f(cwg653::U)
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr {{.*}} %v, ptr {{.*}} %u, {{.*}})
// CHECK-LABEL: }
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@
// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK

namespace dr658 { // dr658: 2.7
namespace cwg658 { // cwg658: 2.7

void f(int* p1) {
char* p2 = reinterpret_cast<char*>(p1);
}

} // namespace dr658
} // namespace cwg658

// We're checking that p1 is stored into p2 without changes.

// CHECK-LABEL: define {{.*}} void @dr658::f(int*)(ptr noundef %p1)
// CHECK-LABEL: define {{.*}} void @cwg658::f(int*)(ptr noundef %p1)
// CHECK: [[P1_ADDR:%.+]] = alloca ptr, align 8
// CHECK-NEXT: [[P2:%.+]] = alloca ptr, align 8
// CHECK: store ptr %p1, ptr [[P1_ADDR]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK

namespace dr661 {
namespace cwg661 {

void f(int a, int b) { // dr661: 2.7
void f(int a, int b) { // cwg661: 2.7
a == b;
a != b;
a < b;
Expand All @@ -17,9 +17,9 @@ void f(int a, int b) { // dr661: 2.7
a >= b;
}

} // namespace dr661
} // namespace cwg661

// CHECK-LABEL: define {{.*}} void @dr661::f(int, int)
// CHECK-LABEL: define {{.*}} void @cwg661::f(int, int)
// CHECK: icmp eq
// CHECK: icmp ne
// CHECK: icmp slt
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#define NOTHROW noexcept(true)
#endif

namespace dr672 { // dr672: 2.7
namespace cwg672 { // cwg672: 2.7

struct A {
A() NOTHROW;
Expand All @@ -22,11 +22,11 @@ void f() {
A *a = new A;
}

} // namespace dr672
} // namespace cwg672

// CHECK-LABEL: define {{.*}} void @dr672::f()()
// CHECK-LABEL: define {{.*}} void @cwg672::f()()
// CHECK: [[A:%.+]] = alloca ptr
// CHECK: [[CALL:%.+]] = call {{.*}} ptr @operator new(unsigned long)
// CHECK: call void @dr672::A::A()
// CHECK: call void @cwg672::A::A()
// CHECK: store ptr [[CALL]], ptr [[A]]
// CHECK-LABEL: }
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#define NOTHROW noexcept(true)
#endif

namespace dr593 { // dr593: 2.8
namespace cwg593 { // cwg593: 2.8

void f();
void fence() NOTHROW;
Expand All @@ -29,7 +29,7 @@ void g() {
A();
}

} // namespace dr593
} // namespace cwg593

// CHECK: call void @dr593::fence()()
// CHECK: call void @cwg593::fence()()
// CHECK-NEXT: invoke void @__cxa_rethrow()
842 changes: 421 additions & 421 deletions clang/test/CXX/drs/dr0xx.cpp

Large diffs are not rendered by default.

36 changes: 18 additions & 18 deletions clang/test/CXX/drs/dr10xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,44 +14,44 @@ namespace std {
};
}

namespace dr1004 { // dr1004: 5
namespace cwg1004 { // cwg1004: 5
template<typename> struct A {};
template<typename> struct B1 {};
template<template<typename> class> struct B2 {};
template<typename X> void f(); // #dr1004-f-1
template<template<typename> class X> void f(); // #dr1004-f-2
template<template<typename> class X> void g(); // #dr1004-g-1
template<typename X> void g(); // #dr1004-g-2
template<typename X> void f(); // #cwg1004-f-1
template<template<typename> class X> void f(); // #cwg1004-f-2
template<template<typename> class X> void g(); // #cwg1004-g-1
template<typename X> void g(); // #cwg1004-g-2
struct C : A<int> {
B1<A> b1a;
B2<A> b2a;
void h() {
f<A>();
// expected-error@-1 {{call to 'f' is ambiguous}}
// expected-note@#dr1004-f-1 {{candidate function [with X = dr1004::A<int>]}}
// expected-note@#dr1004-f-2 {{candidate function [with X = dr1004::A]}}
// expected-note@#cwg1004-f-1 {{candidate function [with X = cwg1004::A<int>]}}
// expected-note@#cwg1004-f-2 {{candidate function [with X = cwg1004::A]}}
g<A>();
// expected-error@-1 {{call to 'g' is ambiguous}}
// expected-note@#dr1004-g-1 {{candidate function [with X = dr1004::A]}}
// expected-note@#dr1004-g-2 {{candidate function [with X = dr1004::A<int>]}}
// expected-note@#cwg1004-g-1 {{candidate function [with X = cwg1004::A]}}
// expected-note@#cwg1004-g-2 {{candidate function [with X = cwg1004::A<int>]}}
}
};

// This example (from the standard) is actually ill-formed, because
// name lookup of "T::template A" names the constructor.
template<class T, template<class> class U = T::template A> struct Third { };
// expected-error@-1 {{is a constructor name}}
// expected-note@#dr1004-t {{in instantiation of default argument}}
Third<A<int> > t; // #dr1004-t
// expected-note@#cwg1004-t {{in instantiation of default argument}}
Third<A<int> > t; // #cwg1004-t
}

namespace dr1042 { // dr1042: 3.5
namespace cwg1042 { // cwg1042: 3.5
#if __cplusplus >= 201402L
// C++14 added an attribute that we can test the semantics of.
using foo [[deprecated]] = int; // #dr1042-using
using foo [[deprecated]] = int; // #cwg1042-using
foo f = 12;
// since-cxx14-warning@-1 {{'foo' is deprecated}}
// since-cxx14-note@#dr1042-using {{'foo' has been explicitly marked deprecated here}}
// since-cxx14-note@#cwg1042-using {{'foo' has been explicitly marked deprecated here}}
#elif __cplusplus >= 201103L
// C++11 did not have any attributes that could be applied to an alias
// declaration, so the best we can test is that we accept an empty attribute
Expand All @@ -60,7 +60,7 @@ namespace dr1042 { // dr1042: 3.5
#endif
}

namespace dr1048 { // dr1048: 3.6
namespace cwg1048 { // cwg1048: 3.6
struct A {};
const A f();
A g();
Expand All @@ -78,20 +78,20 @@ namespace dr1048 { // dr1048: 3.6
#endif
}

namespace dr1054 { // dr1054: no
namespace cwg1054 { // cwg1054: no
// FIXME: Test is incomplete.
struct A {} volatile a;
void f() {
// FIXME: This is wrong: an lvalue-to-rvalue conversion is applied here,
// which copy-initializes a temporary from 'a'. Therefore this is
// ill-formed because A does not have a volatile copy constructor.
// (We might want to track this aspect under dr1383 instead?)
// (We might want to track this aspect under cwg1383 instead?)
a;
// expected-warning@-1 {{expression result unused; assign into a variable to force a volatile load}}
}
}

namespace dr1070 { // dr1070: 3.5
namespace cwg1070 { // cwg1070: 3.5
#if __cplusplus >= 201103L
struct A {
A(std::initializer_list<int>);
Expand Down
24 changes: 12 additions & 12 deletions clang/test/CXX/drs/dr11xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,27 @@
// RUN: %clang_cc1 -std=c++17 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++2a %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors

namespace dr1111 { // dr1111: 3.2
namespace cwg1111 { // cwg1111: 3.2
namespace example1 {
template <typename> struct set; // #dr1111-struct-set
template <typename> struct set; // #cwg1111-struct-set

struct X {
template <typename T> void set(const T &value); // #dr1111-func-set
template <typename T> void set(const T &value); // #cwg1111-func-set
};
void foo() {
X x;
// FIXME: should we backport C++11 behavior?
x.set<double>(3.2);
// cxx98-error@-1 {{lookup of 'set' in member access expression is ambiguous; using member of 'X'}}
// cxx98-note@#dr1111-func-set {{lookup in the object type 'X' refers here}}
// cxx98-note@#dr1111-struct-set {{lookup from the current scope refers here}}
// cxx98-note@#cwg1111-func-set {{lookup in the object type 'X' refers here}}
// cxx98-note@#cwg1111-struct-set {{lookup from the current scope refers here}}
}

struct Y {};
void bar() {
Y y;
y.set<double>(3.2);
// expected-error@-1 {{no member named 'set' in 'dr1111::example1::Y'}}
// expected-error@-1 {{no member named 'set' in 'cwg1111::example1::Y'}}
}
} // namespace example1

Expand All @@ -42,22 +42,22 @@ void baz() {
a.operator A();
}
} // namespace example2
} // namespace dr1111
} // namespace cwg1111

namespace dr1113 { // dr1113: partial
namespace cwg1113 { // cwg1113: partial
namespace named {
extern int a; // #dr1113-a
extern int a; // #cwg1113-a
static int a;
// expected-error@-1 {{static declaration of 'a' follows non-static}}
// expected-note@#dr1113-a {{previous declaration is here}}
// expected-note@#cwg1113-a {{previous declaration is here}}
}
namespace {
extern int a;
static int a; // ok, both declarations have internal linkage
int b = a;
}

// FIXME: Per DR1113 and DR4, this is ill-formed due to ambiguity: the second
// FIXME: Per CWG1113 and CWG4, this is ill-formed due to ambiguity: the second
// 'f' has internal linkage, and so does not have C language linkage, so is
// not a redeclaration of the first 'f'.
//
Expand All @@ -71,4 +71,4 @@ namespace dr1113 { // dr1113: partial
void g() { f(); }
}

// dr1150: na
// cwg1150: na
34 changes: 17 additions & 17 deletions clang/test/CXX/drs/dr12xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx17,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx17,since-cxx14,since-cxx11,since-cxx23 -fexceptions -fcxx-exceptions -pedantic-errors

// dr1200: na
// cwg1200: na

namespace dr1213 { // dr1213: 7
namespace cwg1213 { // cwg1213: 7
#if __cplusplus >= 201103L
using T = int[3];
int &&r = T{}[1];
Expand All @@ -32,7 +32,7 @@ namespace dr1213 { // dr1213: 7
}

#if __cplusplus >= 201103L
namespace dr1223 { // dr1223: 17 drafting 2023-05-12
namespace cwg1223 { // cwg1223: 17 drafting 2023-05-12
struct M;
template <typename T>
struct V;
Expand Down Expand Up @@ -80,31 +80,31 @@ void g() {
A b(auto ()->C);
static_assert(sizeof(B ()->C[1] == sizeof(int)), "");
sizeof(auto () -> C[1]);
// since-cxx11-error@-1 {{function cannot return array type 'C[1]' (aka 'dr1223::BB[1]')}}
// since-cxx11-error@-1 {{function cannot return array type 'C[1]' (aka 'cwg1223::BB[1]')}}
}

}
#endif

#if __cplusplus >= 201103L
namespace dr1227 { // dr1227: 3.0
namespace cwg1227 { // cwg1227: 3.0
template <class T> struct A { using X = typename T::X; };
// since-cxx11-error@-1 {{type 'int' cannot be used prior to '::' because it has no members}}
// since-cxx11-note@#dr1227-g {{in instantiation of template class 'dr1227::A<int>' requested here}}
// since-cxx11-note@#dr1227-g-int {{while substituting explicitly-specified template arguments into function template 'g'}}
// since-cxx11-note@#cwg1227-g {{in instantiation of template class 'cwg1227::A<int>' requested here}}
// since-cxx11-note@#cwg1227-g-int {{while substituting explicitly-specified template arguments into function template 'g'}}
template <class T> typename T::X f(typename A<T>::X);
template <class T> void f(...) { }
template <class T> auto g(typename A<T>::X) -> typename T::X; // #dr1227-g
template <class T> auto g(typename A<T>::X) -> typename T::X; // #cwg1227-g
template <class T> void g(...) { }

void h() {
f<int>(0); // OK, substituting return type causes deduction to fail
g<int>(0); // #dr1227-g-int
g<int>(0); // #cwg1227-g-int
}
}
#endif

namespace dr1250 { // dr1250: 3.9
namespace cwg1250 { // cwg1250: 3.9
struct Incomplete;

struct Base {
Expand All @@ -116,7 +116,7 @@ struct Derived : Base {
};
}

namespace dr1265 { // dr1265: 5
namespace cwg1265 { // cwg1265: 5
#if __cplusplus >= 201103L
auto a = 0, b() -> int;
// since-cxx11-error@-1 {{declaration with trailing return type must be the only declaration in its group}}
Expand All @@ -136,9 +136,9 @@ namespace dr1265 { // dr1265: 5
#endif
}

// dr1291: na
// cwg1291: na

namespace dr1295 { // dr1295: 4
namespace cwg1295 { // cwg1295: 4
struct X {
unsigned bitfield : 4;
};
Expand All @@ -150,11 +150,11 @@ namespace dr1295 { // dr1295: 4
unsigned const &r2 = static_cast<unsigned &&>(x.bitfield);
// cxx98-error@-1 {{rvalue references are a C++11 extension}}

template<unsigned &r> struct Y {}; // #dr1295-Y
Y<x.bitfield> y; // #dr1295-y
template<unsigned &r> struct Y {}; // #cwg1295-Y
Y<x.bitfield> y; // #cwg1295-y
// cxx98-14-error@-1 {{non-type template argument does not refer to any declaration}}
// cxx98-14-note@#dr1295-Y {{template parameter is declared here}}
// since-cxx17-error@#dr1295-y {{reference cannot bind to bit-field in converted constant expression}}
// cxx98-14-note@#cwg1295-Y {{template parameter is declared here}}
// since-cxx17-error@#cwg1295-y {{reference cannot bind to bit-field in converted constant expression}}

#if __cplusplus >= 201103L
const unsigned other = 0;
Expand Down
234 changes: 117 additions & 117 deletions clang/test/CXX/drs/dr13xx.cpp

Large diffs are not rendered by default.

238 changes: 119 additions & 119 deletions clang/test/CXX/drs/dr14xx.cpp

Large diffs are not rendered by default.

370 changes: 185 additions & 185 deletions clang/test/CXX/drs/dr15xx.cpp

Large diffs are not rendered by default.

290 changes: 145 additions & 145 deletions clang/test/CXX/drs/dr16xx.cpp

Large diffs are not rendered by default.

64 changes: 32 additions & 32 deletions clang/test/CXX/drs/dr17xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors

namespace dr1710 { // dr1710: no
namespace cwg1710 { // cwg1710: no
// FIXME: all of the following is well-formed
template <typename T> struct D1 : T::template B<int>::template C<int> {};
template <typename T> struct D2 : T::B<int>::template C<int> {};
Expand All @@ -16,9 +16,9 @@ template <typename T> struct D3 : T::template B<int>::C<int> {};
template <typename T> struct D4 : T::B<int>::C<int> {};
// expected-error@-1 {{use 'template' keyword to treat 'B' as a dependent template name}}
// expected-error@-2 {{use 'template' keyword to treat 'C' as a dependent template name}}
} // namespace dr1710
} // namespace cwg1710

namespace dr1715 { // dr1715: 3.9
namespace cwg1715 { // cwg1715: 3.9
#if __cplusplus >= 201103L
struct B {
template<class T> B(T, typename T::Q);
Expand All @@ -32,21 +32,21 @@ namespace dr1715 { // dr1715: 3.9
struct D : B {
using B::B;
};
struct E : B { // #dr1715-E
template<class T> E(T t, typename T::Q q) : B(t, q) {} // #dr1715-E-ctor
struct E : B { // #cwg1715-E
template<class T> E(T t, typename T::Q q) : B(t, q) {} // #cwg1715-E-ctor
};

B b(S(), 1);
D d(S(), 2);
E e(S(), 3);
// since-cxx11-error@-1 {{no matching constructor for initialization of 'E'}}
// since-cxx11-note@#dr1715-E-ctor {{candidate template ignored: substitution failure [with T = S]: 'Q' is a private member of 'dr1715::S'}}
// since-cxx11-note@#dr1715-E {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}}
// since-cxx11-note@#dr1715-E {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}}
// since-cxx11-note@#cwg1715-E-ctor {{candidate template ignored: substitution failure [with T = S]: 'Q' is a private member of 'cwg1715::S'}}
// since-cxx11-note@#cwg1715-E {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}}
// since-cxx11-note@#cwg1715-E {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}}
#endif
}

namespace dr1719 { // dr1719: 19
namespace cwg1719 { // cwg1719: 19
#if __cplusplus >= 201103L
struct CStruct {
int one;
Expand All @@ -72,9 +72,9 @@ static_assert(__is_layout_compatible(const int, volatile int), "");
static_assert(__is_layout_compatible(CStruct, CStructWithQualifiers), "");
static_assert(__is_layout_compatible(int[], const volatile int[]), "");
#endif
} // namespace dr1719
} // namespace cwg1719

namespace dr1722 { // dr1722: 9
namespace cwg1722 { // cwg1722: 9
#if __cplusplus >= 201103L
void f() {
const auto lambda = [](int x) { return x + 1; };
Expand All @@ -84,9 +84,9 @@ void f() {
"Lambda-to-function-pointer conversion is expected to be noexcept");
}
#endif
} // namespace dr1722
} // namespace cwg1722

namespace dr1734 { // dr1734: no
namespace cwg1734 { // cwg1734: no
#if __cplusplus >= 201103L
struct A {
A(const A&) = delete;
Expand All @@ -98,7 +98,7 @@ static_assert(__is_trivially_copyable(A), "");
#endif
}

namespace dr1736 { // dr1736: 3.9
namespace cwg1736 { // cwg1736: 3.9
#if __cplusplus >= 201103L
struct S {
template <class T> S(T t) {
Expand All @@ -107,17 +107,17 @@ struct S {
};
typename T::type value;
// since-cxx11-error@-1 {{type 'int' cannot be used prior to '::' because it has no members}}
// since-cxx11-note@#dr1736-l {{in instantiation of function template specialization 'dr1736::S::S<int>' requested here}}
// since-cxx11-note@#dr1736-s {{in instantiation of function template specialization 'dr1736::S::S<dr1736::Q>' requested here}}
L l(value); // #dr1736-l
// since-cxx11-note@#cwg1736-l {{in instantiation of function template specialization 'cwg1736::S::S<int>' requested here}}
// since-cxx11-note@#cwg1736-s {{in instantiation of function template specialization 'cwg1736::S::S<cwg1736::Q>' requested here}}
L l(value); // #cwg1736-l
}
};
struct Q { typedef int type; } q;
S s(q); // #dr1736-s
S s(q); // #cwg1736-s
#endif
}

namespace dr1738 { // dr1738: sup P0136R1
namespace cwg1738 { // cwg1738: sup P0136R1
#if __cplusplus >= 201103L
struct A {
template <typename T>
Expand All @@ -134,9 +134,9 @@ template B::B(int, double);
#endif
}

// dr1748 is in dr1748.cpp
// cwg1748 is in cwg1748.cpp

namespace dr1753 { // dr1753: 11
namespace cwg1753 { // cwg1753: 11
typedef int T;
struct A { typedef int T; };
namespace B { typedef int T; }
Expand All @@ -145,9 +145,9 @@ namespace dr1753 { // dr1753: 11
n.~T();
n.T::~T();

n.dr1753::~T();
// expected-error@-1 {{'dr1753' does not refer to a type name in pseudo-destructor expression; expected the name of type 'T' (aka 'int')}}
n.dr1753::T::~T();
n.cwg1753::~T();
// expected-error@-1 {{'cwg1753' does not refer to a type name in pseudo-destructor expression; expected the name of type 'T' (aka 'int')}}
n.cwg1753::T::~T();

n.A::~T();
// expected-error@-1 {{the type of object expression ('T' (aka 'int')) does not match the type being destroyed ('A') in pseudo-destructor expression}}
Expand All @@ -167,7 +167,7 @@ namespace dr1753 { // dr1753: 11
}
}

namespace dr1756 { // dr1756: 3.7
namespace cwg1756 { // cwg1756: 3.7
#if __cplusplus >= 201103L
// Direct-list-initialization of a non-class object

Expand All @@ -178,7 +178,7 @@ namespace dr1756 { // dr1756: 3.7
#endif
}

namespace dr1758 { // dr1758: 3.7
namespace cwg1758 { // cwg1758: 3.7
#if __cplusplus >= 201103L
// Explicit conversion in copy/move list initialization

Expand All @@ -197,7 +197,7 @@ namespace dr1758 { // dr1758: 3.7
#endif
}

namespace dr1762 { // dr1762: 14
namespace cwg1762 { // cwg1762: 14
#if __cplusplus >= 201103L
float operator ""_E(const char *);
float operator ""E(const char *);
Expand All @@ -206,9 +206,9 @@ namespace dr1762 { // dr1762: 14
#endif
}

// dr1772 is in dr177x.cpp
// cwg1772 is in cwg177x.cpp

namespace dr1778 { // dr1778: 9
namespace cwg1778 { // cwg1778: 9
// Superseded by P1286R2.
#if __cplusplus >= 201103L
struct A { A() noexcept(true) = default; };
Expand All @@ -223,9 +223,9 @@ namespace dr1778 { // dr1778: 9
#endif
}

// dr1779 is in dr177x.cpp
// cwg1779 is in cwg177x.cpp

namespace dr1794 { // dr1794: yes
namespace cwg1794 { // cwg1794: yes
// NB: dup 1710
#if __cplusplus >= 201103L
template <template <typename> class Template> struct Internal {
Expand All @@ -238,4 +238,4 @@ using Instantiate = Template<Arg>;
template <template <typename> class Template, typename Argument>
using Bind = Instantiate<Internal<Template>::template Bind, Argument>;
#endif
} // namespace dr1794
} // namespace cwg1794
100 changes: 50 additions & 50 deletions clang/test/CXX/drs/dr18xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,24 @@
// cxx98-error@-1 {{variadic macros are a C99 feature}}
#endif

namespace dr1800 { // dr1800: 2.9
namespace cwg1800 { // cwg1800: 2.9
struct A { union { int n; }; };
static_assert(__is_same(__decltype(&A::n), int A::*), "");
} // namespace dr1800
} // namespace cwg1800

namespace dr1801 { // dr1801: 2.8
namespace cwg1801 { // cwg1801: 2.8
static union {
int i;
};

template <int &> struct S {}; // #dr1801-S
S<i> V; // #dr1801-S-i
template <int &> struct S {}; // #cwg1801-S
S<i> V; // #cwg1801-S-i
// cxx98-14-error@-1 {{non-type template argument does not refer to any declaration}}
// cxx98-14-note@#dr1801-S {{template parameter is declared here}}
// cxx17-error@#dr1801-S-i {{non-type template argument refers to subobject '.i'}}
// cxx98-14-note@#cwg1801-S {{template parameter is declared here}}
// cxx17-error@#cwg1801-S-i {{non-type template argument refers to subobject '.i'}}
}

namespace dr1802 { // dr1802: 3.1
namespace cwg1802 { // cwg1802: 3.1
#if __cplusplus >= 201103L
// Using a Wikipedia example of surrogate pair:
// https://en.wikipedia.org/wiki/UTF-16#Examples
Expand All @@ -37,9 +37,9 @@ static_assert(a[0] == 0xD801, "");
static_assert(a[1] == 0xDC37, "");
static_assert(a[2] == 0x0, "");
#endif
} // namespace dr1802
} // namespace cwg1802

namespace dr1803 { // dr1803: 2.9
namespace cwg1803 { // cwg1803: 2.9
#if __cplusplus >= 201103L
struct A {
enum E : int;
Expand All @@ -50,9 +50,9 @@ struct A {
enum struct ES {};
};
#endif
} // namespace dr1803
} // namespace cwg1803

namespace dr1804 { // dr1804: 2.7
namespace cwg1804 { // cwg1804: 2.7
template <typename, typename>
struct A {
void f1();
Expand Down Expand Up @@ -162,21 +162,21 @@ void A<double, U>::C<V>::f4() {
D d;
d.i = 0;
}
} // namespace dr1804
} // namespace cwg1804

// dr1807 is in dr1807.cpp
// cwg1807 is in cwg1807.cpp

namespace dr1812 { // dr1812: no
namespace cwg1812 { // cwg1812: no
// NB: dup 1710
#if __cplusplus >= 201103L
template <typename T> struct A {
using B = typename T::C<int>;
// since-cxx11-error@-1 {{use 'template' keyword to treat 'C' as a dependent template name}}
};
#endif
} // namespace dr1812
} // namespace cwg1812

namespace dr1813 { // dr1813: 7
namespace cwg1813 { // cwg1813: 7
struct B { int i; };
struct C : B {};
struct D : C {};
Expand All @@ -198,31 +198,31 @@ namespace dr1813 { // dr1813: 7
static_assert(!__is_standard_layout(U), "");
}

namespace dr1814 { // dr1814: yes
namespace cwg1814 { // cwg1814: yes
#if __cplusplus >= 201103L
void test() {
auto lam = [](int x = 42) { return x; };
}
#endif
}

namespace dr1815 { // dr1815: no
namespace cwg1815 { // cwg1815: no
#if __cplusplus >= 201402L
// FIXME: needs codegen test
struct A { int &&r = 0; }; // #dr1815-A
struct A { int &&r = 0; }; // #cwg1815-A
A a = {};
// since-cxx14-warning@-1 {{lifetime extension of temporary created by aggregate initialization using a default member initializer is not yet supported; lifetime of temporary will end at the end of the full-expression}} FIXME
// since-cxx14-note@#dr1815-A {{initializing field 'r' with default member initializer}}
// since-cxx14-note@#cwg1815-A {{initializing field 'r' with default member initializer}}

struct B { int &&r = 0; }; // #dr1815-B
struct B { int &&r = 0; }; // #cwg1815-B
// since-cxx14-error@-1 {{reference member 'r' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}}
// since-cxx14-note@#dr1815-B {{initializing field 'r' with default member initializer}}
// since-cxx14-note@#dr1815-b {{in implicit default constructor for 'dr1815::B' first required here}}
B b; // #dr1815-b
// since-cxx14-note@#cwg1815-B {{initializing field 'r' with default member initializer}}
// since-cxx14-note@#cwg1815-b {{in implicit default constructor for 'cwg1815::B' first required here}}
B b; // #cwg1815-b
#endif
}

namespace dr1821 { // dr1821: 2.9
namespace cwg1821 { // cwg1821: 2.9
struct A {
template <typename> struct B {
void f();
Expand All @@ -236,9 +236,9 @@ struct A {
void C::f() {}
// expected-error@-1 {{non-friend class member 'f' cannot have a qualified name}}
};
} // namespace dr1821
} // namespace cwg1821

namespace dr1822 { // dr1822: yes
namespace cwg1822 { // cwg1822: yes
#if __cplusplus >= 201103L
double a;
auto x = [] (int a) {
Expand All @@ -247,7 +247,7 @@ namespace dr1822 { // dr1822: yes
#endif
}

namespace dr1837 { // dr1837: 3.3
namespace cwg1837 { // cwg1837: 3.3
#if __cplusplus >= 201103L
template <typename T>
struct Fish { static const bool value = true; };
Expand Down Expand Up @@ -291,7 +291,7 @@ namespace dr1837 { // dr1837: 3.3
#endif
}

namespace dr1872 { // dr1872: 9
namespace cwg1872 { // cwg1872: 9
#if __cplusplus >= 201103L
template<typename T> struct A : T {
constexpr int f() const { return 0; }
Expand Down Expand Up @@ -320,7 +320,7 @@ namespace dr1872 { // dr1872: 9
#endif
}

namespace dr1878 { // dr1878: 18
namespace cwg1878 { // cwg1878: 18
#if __cplusplus >= 201402L
#if __cplusplus >= 202002L
template <typename T>
Expand Down Expand Up @@ -355,7 +355,7 @@ struct S {
#endif
}

namespace dr1881 { // dr1881: 7
namespace cwg1881 { // cwg1881: 7
struct A { int a : 4; };
struct B : A { int b : 3; };
static_assert(__is_standard_layout(A), "");
Expand All @@ -367,17 +367,17 @@ namespace dr1881 { // dr1881: 7
static_assert(!__is_standard_layout(D), "");
}

namespace dr1890 { // dr1890: no drafting 2018-06-04
namespace cwg1890 { // cwg1890: no drafting 2018-06-04
// FIXME: current consensus for CWG2335 is that the examples are well-formed.
namespace ex1 {
#if __cplusplus >= 201402L
struct A {
struct B {
auto foo() { return 0; } // #dr1890-foo
auto foo() { return 0; } // #cwg1890-foo
};
decltype(B().foo()) x;
// since-cxx14-error@-1 {{function 'foo' with deduced return type cannot be used before it is defined}}
// since-cxx14-note@#dr1890-foo {{'foo' declared here}}
// since-cxx14-note@#cwg1890-foo {{'foo' declared here}}
};
#endif
} // namespace ex1
Expand All @@ -389,17 +389,17 @@ struct Bar {
int a = 0;
};
static_assert(__is_constructible(Baz), "");
// since-cxx11-error@-1 {{static assertion failed due to requirement '__is_constructible(dr1890::ex2::Bar::Baz)'}}
// since-cxx11-error@-1 {{static assertion failed due to requirement '__is_constructible(cwg1890::ex2::Bar::Baz)'}}
};
#endif
} // namespace ex2
} // namespace dr1890
} // namespace cwg1890

void dr1891() { // dr1891: 4
void cwg1891() { // cwg1891: 4
#if __cplusplus >= 201103L
int n;
auto a = []{}; // #dr1891-a
auto b = [=]{ return n; }; // #dr1891-b
auto a = []{}; // #cwg1891-a
auto b = [=]{ return n; }; // #cwg1891-b
typedef decltype(a) A;
typedef decltype(b) B;

Expand All @@ -410,31 +410,31 @@ void dr1891() { // dr1891: 4
// C++20 allows default construction for non-capturing lambdas (P0624R2).
A x;
// cxx11-17-error@-1 {{no matching constructor for initialization of 'A' (aka '(lambda at}}
// cxx11-17-note@#dr1891-a {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}}
// cxx11-17-note@#dr1891-a {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}}
// cxx11-17-note@#cwg1891-a {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}}
// cxx11-17-note@#cwg1891-a {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}}
B y;
// since-cxx11-error@-1 {{no matching constructor for initialization of 'B' (aka '(lambda at}}
// since-cxx11-note@#dr1891-b {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}}
// since-cxx11-note@#dr1891-b {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}}
// since-cxx11-note@#cwg1891-b {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}}
// since-cxx11-note@#cwg1891-b {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}}

// C++20 allows assignment for non-capturing lambdas (P0624R2).
a = a;
// cxx11-17-error-re@-1 {{{{object of type '\(lambda at .+\)' cannot be assigned because its copy assignment operator is implicitly deleted}}}}
// cxx11-17-note@#dr1891-a {{lambda expression begins here}}
// cxx11-17-note@#cwg1891-a {{lambda expression begins here}}
a = static_cast<A&&>(a);
// cxx11-17-error-re@-1 {{{{object of type '\(lambda at .+\)' cannot be assigned because its copy assignment operator is implicitly deleted}}}}
// cxx11-17-note@#dr1891-a {{lambda expression begins here}}
// cxx11-17-note@#cwg1891-a {{lambda expression begins here}}
b = b;
// since-cxx11-error-re@-1 {{{{object of type '\(lambda at .+\)' cannot be assigned because its copy assignment operator is implicitly deleted}}}}
// since-cxx11-note@#dr1891-b {{lambda expression begins here}}
// since-cxx11-note@#cwg1891-b {{lambda expression begins here}}
b = static_cast<B&&>(b);
// since-cxx11-error-re@-1 {{{{object of type '\(lambda at .+\)' cannot be assigned because its copy assignment operator is implicitly deleted}}}}
// since-cxx11-note@#dr1891-b {{lambda expression begins here}}
// since-cxx11-note@#cwg1891-b {{lambda expression begins here}}
#endif
}

namespace dr1894 { // dr1894: 3.8
// NB: reusing part of dr407 test
namespace cwg1894 { // cwg1894: 3.8
// NB: reusing part of cwg407 test
namespace A {
struct S {};
}
Expand Down
Loading