276 changes: 252 additions & 24 deletions clang/lib/Sema/SemaOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,19 @@ bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind,
}
}

case OpenACCClauseKind::Gang: {
switch (DirectiveKind) {
case OpenACCDirectiveKind::Loop:
case OpenACCDirectiveKind::ParallelLoop:
case OpenACCDirectiveKind::SerialLoop:
case OpenACCDirectiveKind::KernelsLoop:
case OpenACCDirectiveKind::Routine:
return true;
default:
return false;
}
}

default:
// Do nothing so we can go to the 'unimplemented' diagnostic instead.
return true;
Expand Down Expand Up @@ -459,6 +472,23 @@ class SemaOpenACCClauseVisitor {
return nullptr;
}

// OpenACC 3.3 2.9:
// A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause
// appears.
bool DiagIfSeqClause(SemaOpenACC::OpenACCParsedClause &Clause) {
const auto *Itr =
llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSeqClause>);

if (Itr != ExistingClauses.end()) {
SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
<< Clause.getClauseKind() << (*Itr)->getClauseKind();
SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);

return true;
}
return false;
}

public:
SemaOpenACCClauseVisitor(SemaOpenACC &S,
ArrayRef<const OpenACCClause *> ExistingClauses)
Expand All @@ -470,26 +500,14 @@ class SemaOpenACCClauseVisitor {

OpenACCClause *Visit(SemaOpenACC::OpenACCParsedClause &Clause) {
switch (Clause.getClauseKind()) {
case OpenACCClauseKind::Gang:
case OpenACCClauseKind::Worker:
case OpenACCClauseKind::Vector: {
// TODO OpenACC: These are only implemented enough for the 'seq' diagnostic,
// otherwise treats itself as unimplemented. When we implement these, we
// can remove them from here.

// OpenACC 3.3 2.9:
// A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause
// appears.
const auto *Itr =
llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSeqClause>);

if (Itr != ExistingClauses.end()) {
SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
<< Clause.getClauseKind() << (*Itr)->getClauseKind();
SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
case OpenACCClauseKind::Worker:
case OpenACCClauseKind::Vector: {
// TODO OpenACC: These are only implemented enough for the 'seq'
// diagnostic, otherwise treats itself as unimplemented. When we
// implement these, we can remove them from here.
DiagIfSeqClause(Clause);
return isNotImplemented();
}
return isNotImplemented();
}

#define VISIT_CLAUSE(CLAUSE_NAME) \
case OpenACCClauseKind::CLAUSE_NAME: \
Expand Down Expand Up @@ -1006,6 +1024,84 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitIndependentClause(
Clause.getEndLoc());
}

OpenACCClause *SemaOpenACCClauseVisitor::VisitGangClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
if (DiagIfSeqClause(Clause))
return nullptr;

// Restrictions only properly implemented on 'loop' constructs, and it is
// the only construct that can do anything with this, so skip/treat as
// unimplemented for the combined constructs.
if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
return isNotImplemented();

llvm::SmallVector<OpenACCGangKind> GangKinds;
llvm::SmallVector<Expr *> IntExprs;

// Store the existing locations, so we can do duplicate checking. Index is
// the int-value of the OpenACCGangKind enum.
SourceLocation ExistingElemLoc[3];

for (unsigned I = 0; I < Clause.getIntExprs().size(); ++I) {
OpenACCGangKind GK = Clause.getGangKinds()[I];
ExprResult ER = SemaRef.CheckGangExpr(GK, Clause.getIntExprs()[I]);

if (!ER.isUsable())
continue;

// OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
// construct, the gang clause behaves as follows. ... An argument with no
// keyword or with num keyword is only allowed when num_gangs does not
// appear on the kernels construct.
if (SemaRef.getActiveComputeConstructInfo().Kind ==
OpenACCDirectiveKind::Kernels &&
GK == OpenACCGangKind::Num) {
const auto *Itr =
llvm::find_if(SemaRef.getActiveComputeConstructInfo().Clauses,
llvm::IsaPred<OpenACCNumGangsClause>);

if (Itr != SemaRef.getActiveComputeConstructInfo().Clauses.end()) {
SemaRef.Diag(ER.get()->getBeginLoc(),
diag::err_acc_gang_num_gangs_conflict);
SemaRef.Diag((*Itr)->getBeginLoc(),
diag::note_acc_previous_clause_here);
continue;
}
}

// OpenACC 3.3 2.9: 'gang-arg-list' may have at most one num, one dim, and
// one static argument.
if (ExistingElemLoc[static_cast<unsigned>(GK)].isValid()) {
SemaRef.Diag(ER.get()->getBeginLoc(), diag::err_acc_gang_multiple_elt)
<< static_cast<unsigned>(GK);
SemaRef.Diag(ExistingElemLoc[static_cast<unsigned>(GK)],
diag::note_acc_previous_expr_here);
continue;
}

ExistingElemLoc[static_cast<unsigned>(GK)] = ER.get()->getBeginLoc();
GangKinds.push_back(GK);
IntExprs.push_back(ER.get());
}

// OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
// construct, the gang clause behaves as follows. ... The region of a loop
// with a gang clause may not contain another loop with a gang clause unless
// within a nested compute region.
if (SemaRef.LoopGangClauseOnKernelLoc.isValid()) {
// This handles the 'inner loop' diagnostic, but we cannot set that we're on
// one of these until we get to the end of the construct.
SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_gang_inside_gang);
SemaRef.Diag(SemaRef.LoopGangClauseOnKernelLoc,
diag::note_acc_previous_clause_here);
return nullptr;
}

return OpenACCGangClause::Create(Ctx, Clause.getBeginLoc(),
Clause.getLParenLoc(), GangKinds, IntExprs,
Clause.getEndLoc());
}

OpenACCClause *SemaOpenACCClauseVisitor::VisitSeqClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
// Restrictions only properly implemented on 'loop' constructs, and it is
Expand Down Expand Up @@ -1118,17 +1214,44 @@ SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII(
SemaOpenACC &S, OpenACCDirectiveKind DK,
ArrayRef<const OpenACCClause *> UnInstClauses,
ArrayRef<OpenACCClause *> Clauses)
: SemaRef(S), WasInsideComputeConstruct(S.InsideComputeConstruct),
DirKind(DK), LoopRAII(SemaRef, /*PreserveDepth=*/false) {
: SemaRef(S), OldActiveComputeConstructInfo(S.ActiveComputeConstructInfo),
DirKind(DK), OldLoopGangClauseOnKernelLoc(S.LoopGangClauseOnKernelLoc),
LoopRAII(SemaRef, /*PreserveDepth=*/false) {
// Compute constructs end up taking their 'loop'.
if (DirKind == OpenACCDirectiveKind::Parallel ||
DirKind == OpenACCDirectiveKind::Serial ||
DirKind == OpenACCDirectiveKind::Kernels) {
SemaRef.InsideComputeConstruct = true;
SemaRef.ActiveComputeConstructInfo.Kind = DirKind;
SemaRef.ActiveComputeConstructInfo.Clauses = Clauses;
SemaRef.ParentlessLoopConstructs.swap(ParentlessLoopConstructs);

// OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
// construct, the gang clause behaves as follows. ... The region of a loop
// with a gang clause may not contain another loop with a gang clause unless
// within a nested compute region.
//
// Implement the 'unless within a nested compute region' part.
SemaRef.LoopGangClauseOnKernelLoc = {};
} else if (DirKind == OpenACCDirectiveKind::Loop) {
SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
SetTileInfoBeforeAssociatedStmt(UnInstClauses, Clauses);

// OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
// construct, the gang clause behaves as follows. ... The region of a loop
// with a gang clause may not contain another loop with a gang clause unless
// within a nested compute region.
//
// We don't bother doing this when this is a template instantiation, as
// there is no reason to do these checks: the existance of a
// gang/kernels/etc cannot be dependent.
if (SemaRef.getActiveComputeConstructInfo().Kind ==
OpenACCDirectiveKind::Kernels &&
UnInstClauses.empty()) {
// This handles the 'outer loop' part of this.
auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCGangClause>);
if (Itr != Clauses.end())
SemaRef.LoopGangClauseOnKernelLoc = (*Itr)->getBeginLoc();
}
}
}

Expand Down Expand Up @@ -1199,7 +1322,9 @@ void SemaOpenACC::AssociatedStmtRAII::SetTileInfoBeforeAssociatedStmt(
}

SemaOpenACC::AssociatedStmtRAII::~AssociatedStmtRAII() {
SemaRef.InsideComputeConstruct = WasInsideComputeConstruct;
SemaRef.ActiveComputeConstructInfo = OldActiveComputeConstructInfo;
SemaRef.LoopGangClauseOnKernelLoc = OldLoopGangClauseOnKernelLoc;

if (DirKind == OpenACCDirectiveKind::Parallel ||
DirKind == OpenACCDirectiveKind::Serial ||
DirKind == OpenACCDirectiveKind::Kernels) {
Expand Down Expand Up @@ -1761,6 +1886,109 @@ ExprResult SemaOpenACC::CheckCollapseLoopCount(Expr *LoopCount) {
ConstantExpr::Create(getASTContext(), LoopCount, APValue{*ICE})};
}

namespace {
ExprResult CheckGangStaticExpr(SemaOpenACC &S, Expr *E) {
if (isa<OpenACCAsteriskSizeExpr>(E))
return E;
return S.ActOnIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Gang,
E->getBeginLoc(), E);
}
} // namespace

ExprResult SemaOpenACC::CheckGangExpr(OpenACCGangKind GK, Expr *E) {
// Gang Expr legality depends on the associated compute construct.
switch (ActiveComputeConstructInfo.Kind) {
case OpenACCDirectiveKind::Invalid:
case OpenACCDirectiveKind::Parallel: {
switch (GK) {
// OpenACC 3.3 2.9.2: When the parent compute construct is a parallel
// construct, or an orphaned loop construct, the gang clause behaves as
// follows. ... The dim argument must be a constant positive integer value
// 1, 2, or 3.
case OpenACCGangKind::Dim: {
if (!E)
return ExprError();
ExprResult Res =
ActOnIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Gang,
E->getBeginLoc(), E);

if (!Res.isUsable())
return Res;

if (Res.get()->isInstantiationDependent())
return Res;

std::optional<llvm::APSInt> ICE =
Res.get()->getIntegerConstantExpr(getASTContext());

if (!ICE || *ICE <= 0 || ICE > 3) {
Diag(Res.get()->getBeginLoc(), diag::err_acc_gang_dim_value)
<< ICE.has_value() << ICE.value_or(llvm::APSInt{}).getExtValue();
return ExprError();
}

return ExprResult{
ConstantExpr::Create(getASTContext(), Res.get(), APValue{*ICE})};
}
// OpenACC 3.3 2.9.2: When the parent compute construct is a parallel
// construct, or an orphaned loop construct, the gang clause behaves as
// follows. ... The num argument is not allowed.
case OpenACCGangKind::Num:
Diag(E->getBeginLoc(), diag::err_acc_gang_arg_invalid)
<< GK
<< (/*orphan/parallel=*/ActiveComputeConstructInfo.Kind ==
OpenACCDirectiveKind::Parallel
? 1
: 0);
return ExprError();
case OpenACCGangKind::Static:
return CheckGangStaticExpr(*this, E);
}
} break;
case OpenACCDirectiveKind::Kernels: {
switch (GK) {
// OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
// construct, the gang clause behaves as follows. ... The dim argument is
// not allowed.
case OpenACCGangKind::Dim:
Diag(E->getBeginLoc(), diag::err_acc_gang_arg_invalid)
<< GK << /*kernels=*/2;
return ExprError();
// OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
// construct, the gang clause behaves as follows. ... An argument with no
// keyword or with num keyword is only allowed when num_gangs does not
// appear on the kernels construct. ... The region of a loop with the gang
// clause may not contain another loop with a gang clause unless within a
// nested compute region.
case OpenACCGangKind::Num:
// This isn't allowed if there is a 'num_gangs' on the kernel construct,
// and makes loop-with-gang-clause ill-formed inside of this 'loop', but
// nothing can be enforced here.
return ExprResult{E};
case OpenACCGangKind::Static:
return CheckGangStaticExpr(*this, E);
}
} break;
case OpenACCDirectiveKind::Serial: {
switch (GK) {
// 'dim' and 'num' don't really make sense on serial, and GCC rejects them
// too, so we disallow them too.
case OpenACCGangKind::Dim:
case OpenACCGangKind::Num:
Diag(E->getBeginLoc(), diag::err_acc_gang_arg_invalid)
<< GK << /*Kernels=*/3;
return ExprError();
case OpenACCGangKind::Static:
return CheckGangStaticExpr(*this, E);
}
}
default:
llvm_unreachable("Non compute construct in active compute construct?");
}

llvm_unreachable("Compute construct directive not handled?");
}

ExprResult SemaOpenACC::CheckTileSizeExpr(Expr *SizeExpr) {
if (!SizeExpr)
return ExprError();
Expand Down Expand Up @@ -2031,7 +2259,7 @@ StmtResult SemaOpenACC::ActOnEndStmtDirective(OpenACCDirectiveKind K,
// If we are in the scope of a compute construct, add this to the list of
// loop constructs that need assigning to the next closing compute
// construct.
if (InsideComputeConstruct)
if (isInComputeConstruct())
ParentlessLoopConstructs.push_back(LoopConstruct);

return LoopConstruct;
Expand Down
50 changes: 18 additions & 32 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6864,8 +6864,7 @@ void Sema::AddOverloadCandidate(
OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
bool PartialOverloading, bool AllowExplicit, bool AllowExplicitConversions,
ADLCallKind IsADLCandidate, ConversionSequenceList EarlyConversions,
OverloadCandidateParamOrder PO, bool AggregateCandidateDeduction,
bool HasMatchedPackOnParmToNonPackOnArg) {
OverloadCandidateParamOrder PO, bool AggregateCandidateDeduction) {
const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>());
assert(Proto && "Functions without a prototype cannot be overloaded");
Expand All @@ -6884,8 +6883,7 @@ void Sema::AddOverloadCandidate(
AddMethodCandidate(Method, FoundDecl, Method->getParent(), QualType(),
Expr::Classification::makeSimpleLValue(), Args,
CandidateSet, SuppressUserConversions,
PartialOverloading, EarlyConversions, PO,
HasMatchedPackOnParmToNonPackOnArg);
PartialOverloading, EarlyConversions, PO);
return;
}
// We treat a constructor like a non-member function, since its object
Expand Down Expand Up @@ -6928,8 +6926,6 @@ void Sema::AddOverloadCandidate(
CandidateSet.getRewriteInfo().getRewriteKind(Function, PO);
Candidate.IsADLCandidate = IsADLCandidate;
Candidate.ExplicitCallArguments = Args.size();
Candidate.HasMatchedPackOnParmToNonPackOnArg =
HasMatchedPackOnParmToNonPackOnArg;

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

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

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

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

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

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

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

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

// -- F1 is a non-template function and F2 is a function template
// specialization, or, if not that,
bool Cand1IsSpecialization = Cand1.Function &&
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Sema/SemaStmtAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,10 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
case ParsedAttr::AT_Annotate:
return S.CreateAnnotationAttr(A);
default:
if (Attr *AT = nullptr; A.getInfo().handleStmtAttribute(S, St, A, AT) !=
ParsedAttrInfo::NotHandled) {
return AT;
}
// N.B., ClangAttrEmitter.cpp emits a diagnostic helper that ensures a
// declaration attribute is not written on a statement, but this code is
// needed for attributes in Attr.td that do not list any subjects.
Expand Down
326 changes: 163 additions & 163 deletions clang/lib/Sema/SemaTemplate.cpp

Large diffs are not rendered by default.

475 changes: 136 additions & 339 deletions clang/lib/Sema/SemaTemplateDeduction.cpp

Large diffs are not rendered by default.

45 changes: 16 additions & 29 deletions clang/lib/Sema/SemaTemplateDeductionGuide.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
}
// Template arguments used to transform the template arguments in
// DeducedResults.
SmallVector<TemplateArgument> TemplateArgsForBuildingRC(
SmallVector<TemplateArgument> InnerArgsForBuildingRC(
F->getTemplateParameters()->size());
// Transform the transformed template args
MultiLevelTemplateArgumentList Args;
Expand All @@ -778,33 +778,30 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
NamedDecl *TP = F->getTemplateParameters()->getParam(Index);
MultiLevelTemplateArgumentList Args;
Args.setKind(TemplateSubstitutionKind::Rewrite);
Args.addOuterTemplateArguments(TemplateArgsForBuildingRC);
Args.addOuterTemplateArguments(InnerArgsForBuildingRC);
// Rebuild the template parameter with updated depth and index.
NamedDecl *NewParam =
transformTemplateParameter(SemaRef, F->getDeclContext(), TP, Args,
/*NewIndex=*/FirstUndeducedParamIdx,
getDepthAndIndex(TP).first + AdjustDepth);
FirstUndeducedParamIdx += 1;
assert(TemplateArgsForBuildingRC[Index].isNull());
TemplateArgsForBuildingRC[Index] =
Context.getInjectedTemplateArg(NewParam);
assert(InnerArgsForBuildingRC[Index].isNull());
InnerArgsForBuildingRC[Index] = Context.getInjectedTemplateArg(NewParam);
continue;
}
TemplateArgumentLoc Input =
SemaRef.getTrivialTemplateArgumentLoc(D, QualType(), SourceLocation{});
TemplateArgumentLoc Output;
if (!SemaRef.SubstTemplateArgument(Input, Args, Output)) {
assert(TemplateArgsForBuildingRC[Index].isNull() &&
assert(InnerArgsForBuildingRC[Index].isNull() &&
"InstantiatedArgs must be null before setting");
TemplateArgsForBuildingRC[Index] = Output.getArgument();
InnerArgsForBuildingRC[Index] = Output.getArgument();
}
}

// A list of template arguments for transforming the require-clause of F.
// It must contain the entire set of template argument lists.
MultiLevelTemplateArgumentList ArgsForBuildingRC;
ArgsForBuildingRC.setKind(clang::TemplateSubstitutionKind::Rewrite);
ArgsForBuildingRC.addOuterTemplateArguments(TemplateArgsForBuildingRC);
// A list of template arguments for transforming the require-clause using
// the transformed template arguments as the template argument list of F.
//
// For 2), if the underlying deduction guide F is nested in a class template,
// we need the entire template argument list, as the constraint AST in the
// require-clause of F remains completely uninstantiated.
Expand All @@ -827,25 +824,15 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
// - The occurrence of U in the function parameter is [depth:0, index:0]
// - The template parameter of U is [depth:0, index:0]
//
// We add the outer template arguments which is [int] to the multi-level arg
// list to ensure that the occurrence U in `C<U>` will be replaced with int
// during the substitution.
//
// NOTE: The underlying deduction guide F is instantiated -- either from an
// explicitly-written deduction guide member, or from a constructor.
// getInstantiatedFromMemberTemplate() can only handle the former case, so we
// check the DeclContext kind.
if (F->getLexicalDeclContext()->getDeclKind() ==
clang::Decl::ClassTemplateSpecialization) {
auto OuterLevelArgs = SemaRef.getTemplateInstantiationArgs(
F, F->getLexicalDeclContext(),
/*Final=*/false, /*Innermost=*/std::nullopt,
/*RelativeToPrimary=*/true,
/*Pattern=*/nullptr,
/*ForConstraintInstantiation=*/true);
for (auto It : OuterLevelArgs)
ArgsForBuildingRC.addOuterTemplateArguments(It.Args);
}
MultiLevelTemplateArgumentList ArgsForBuildingRC =
SemaRef.getTemplateInstantiationArgs(F, F->getLexicalDeclContext(),
/*Final=*/false,
/*Innermost=*/InnerArgsForBuildingRC,
/*RelativeToPrimary=*/true,
/*ForConstraintInstantiation=*/true);
ArgsForBuildingRC.setKind(clang::TemplateSubstitutionKind::Rewrite);

ExprResult E = SemaRef.SubstExpr(RC, ArgsForBuildingRC);
if (E.isInvalid())
Expand Down
797 changes: 383 additions & 414 deletions clang/lib/Sema/SemaTemplateInstantiate.cpp

Large diffs are not rendered by default.

46 changes: 37 additions & 9 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "TreeTransform.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
Expand Down Expand Up @@ -4688,6 +4689,36 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
ParmVarDecl *Param) {
assert(Param->hasUninstantiatedDefaultArg());

NamedDecl *Pattern = FD;
std::optional<ArrayRef<TemplateArgument>> Innermost;

// C++ [dcl.fct.default]p4
// For non-template functions, default arguments can be added in later
// declarations of a function that inhabit the same scope.
//
// C++ [dcl.fct.default]p6
// Except for member functions of templated classes, the default arguments
// in a member function definition that appears outside of the class
// definition are added to the set of default arguments provided by the
// member function declaration in the class definition; the program is
// ill-formed if a default constructor, copy or move constructor, or copy
// or move assignment operator is so declared. Default arguments for a
// member function of a templated class shall be specified on the initial
// declaration of the member function within the templated class.
//
// We need to collect the template arguments from the context of the function
// where the default argument was defined. For a specialization of a function
// template explicitly specialized for an implicit instantiation of a class
// template, that context is the (implicitly instantiated) declaration in the
// definition of the class template specialization.
if (FD->isCXXClassMember() &&
!isGenericLambdaCallOperatorOrStaticInvokerSpecialization(FD)) {
if (FunctionTemplateDecl *FTD = FD->getPrimaryTemplate()) {
Pattern = FTD->getFirstDecl();
Innermost = FD->getTemplateSpecializationArgs()->asArray();
}
}

// Instantiate the expression.
//
// FIXME: Pass in a correct Pattern argument, otherwise
Expand All @@ -4705,12 +4736,10 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
//
// template<typename T>
// A<T> Foo(int a = A<T>::FooImpl());
MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
FD, FD->getLexicalDeclContext(),
/*Final=*/false, /*Innermost=*/std::nullopt,
/*RelativeToPrimary=*/true, /*Pattern=*/nullptr,
/*ForConstraintInstantiation=*/false, /*SkipForSpecialization=*/false,
/*ForDefaultArgumentSubstitution=*/true);
MultiLevelTemplateArgumentList TemplateArgs =
getTemplateInstantiationArgs(Pattern, Pattern->getLexicalDeclContext(),
/*Final=*/false, Innermost,
/*RelativeToPrimary=*/true);

if (SubstDefaultArgument(CallLoc, Param, TemplateArgs, /*ForCallExpr*/ true))
return true;
Expand Down Expand Up @@ -4751,7 +4780,7 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
MultiLevelTemplateArgumentList TemplateArgs =
getTemplateInstantiationArgs(Decl, Decl->getLexicalDeclContext(),
/*Final=*/false, /*Innermost=*/std::nullopt,
/*RelativeToPrimary*/ true);
/*RelativeToPrimary=*/true);

// FIXME: We can't use getTemplateInstantiationPattern(false) in general
// here, because for a non-defining friend declaration in a class template,
Expand Down Expand Up @@ -5199,8 +5228,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
SetDeclDefaulted(Function, PatternDecl->getLocation());
} else {
MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
Function, Function->getLexicalDeclContext(), /*Final=*/false,
/*Innermost=*/std::nullopt, false, PatternDecl);
Function, Function->getLexicalDeclContext());

// Substitute into the qualifier; we can get a substitution failure here
// through evil use of alias templates.
Expand Down
42 changes: 26 additions & 16 deletions clang/lib/Sema/SemaTemplateVariadic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "llvm/Support/SaveAndRestore.h"
#include <optional>

using namespace clang;
Expand All @@ -36,7 +37,7 @@ namespace {

SmallVectorImpl<UnexpandedParameterPack> &Unexpanded;

bool InLambda = false;
bool InLambdaOrBlock = false;
unsigned DepthLimit = (unsigned)-1;

#ifndef NDEBUG
Expand Down Expand Up @@ -140,7 +141,7 @@ namespace {
/// do not contain unexpanded parameter packs.
bool TraverseStmt(Stmt *S) {
Expr *E = dyn_cast_or_null<Expr>(S);
if ((E && E->containsUnexpandedParameterPack()) || InLambda)
if ((E && E->containsUnexpandedParameterPack()) || InLambdaOrBlock)
return inherited::TraverseStmt(S);

return true;
Expand All @@ -149,7 +150,8 @@ namespace {
/// Suppress traversal into types that do not contain
/// unexpanded parameter packs.
bool TraverseType(QualType T) {
if ((!T.isNull() && T->containsUnexpandedParameterPack()) || InLambda)
if ((!T.isNull() && T->containsUnexpandedParameterPack()) ||
InLambdaOrBlock)
return inherited::TraverseType(T);

return true;
Expand All @@ -160,7 +162,7 @@ namespace {
bool TraverseTypeLoc(TypeLoc TL) {
if ((!TL.getType().isNull() &&
TL.getType()->containsUnexpandedParameterPack()) ||
InLambda)
InLambdaOrBlock)
return inherited::TraverseTypeLoc(TL);

return true;
Expand Down Expand Up @@ -262,20 +264,28 @@ namespace {
if (!Lambda->containsUnexpandedParameterPack())
return true;

bool WasInLambda = InLambda;
SaveAndRestore _(InLambdaOrBlock, true);
unsigned OldDepthLimit = DepthLimit;

InLambda = true;
if (auto *TPL = Lambda->getTemplateParameterList())
DepthLimit = TPL->getDepth();

inherited::TraverseLambdaExpr(Lambda);

InLambda = WasInLambda;
DepthLimit = OldDepthLimit;
return true;
}

/// Analogously for blocks.
bool TraverseBlockExpr(BlockExpr *Block) {
if (!Block->containsUnexpandedParameterPack())
return true;

SaveAndRestore _(InLambdaOrBlock, true);
inherited::TraverseBlockExpr(Block);
return true;
}

/// Suppress traversal within pack expansions in lambda captures.
bool TraverseLambdaCapture(LambdaExpr *Lambda, const LambdaCapture *C,
Expr *Init) {
Expand Down Expand Up @@ -323,11 +333,11 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,

// If we are within a lambda expression and referencing a pack that is not
// declared within the lambda itself, that lambda contains an unexpanded
// parameter pack, and we are done.
// parameter pack, and we are done. Analogously for blocks.
// FIXME: Store 'Unexpanded' on the lambda so we don't need to recompute it
// later.
SmallVector<UnexpandedParameterPack, 4> LambdaParamPackReferences;
if (auto *LSI = getEnclosingLambda()) {
SmallVector<UnexpandedParameterPack, 4> ParamPackReferences;
if (sema::CapturingScopeInfo *CSI = getEnclosingLambdaOrBlock()) {
for (auto &Pack : Unexpanded) {
auto DeclaresThisPack = [&](NamedDecl *LocalPack) {
if (auto *TTPT = Pack.first.dyn_cast<const TemplateTypeParmType *>()) {
Expand All @@ -336,11 +346,11 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
}
return declaresSameEntity(Pack.first.get<NamedDecl *>(), LocalPack);
};
if (llvm::any_of(LSI->LocalPacks, DeclaresThisPack))
LambdaParamPackReferences.push_back(Pack);
if (llvm::any_of(CSI->LocalPacks, DeclaresThisPack))
ParamPackReferences.push_back(Pack);
}

if (LambdaParamPackReferences.empty()) {
if (ParamPackReferences.empty()) {
// Construct in lambda only references packs declared outside the lambda.
// That's OK for now, but the lambda itself is considered to contain an
// unexpanded pack in this case, which will require expansion outside the
Expand All @@ -363,16 +373,16 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
}
// Coumpound-statements outside the lambda are OK for now; we'll check
// for those when we finish handling the lambda.
if (Func == LSI)
if (Func == CSI)
break;
}

if (!EnclosingStmtExpr) {
LSI->ContainsUnexpandedParameterPack = true;
CSI->ContainsUnexpandedParameterPack = true;
return false;
}
} else {
Unexpanded = LambdaParamPackReferences;
Unexpanded = ParamPackReferences;
}
}

Expand Down
23 changes: 23 additions & 0 deletions clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -11940,6 +11940,29 @@ void OpenACCClauseTransform<Derived>::VisitTileClause(
ParsedClause.getLParenLoc(), ParsedClause.getIntExprs(),
ParsedClause.getEndLoc());
}
template <typename Derived>
void OpenACCClauseTransform<Derived>::VisitGangClause(
const OpenACCGangClause &C) {
llvm::SmallVector<OpenACCGangKind> TransformedGangKinds;
llvm::SmallVector<Expr *> TransformedIntExprs;

for (unsigned I = 0; I < C.getNumExprs(); ++I) {
ExprResult ER = Self.TransformExpr(const_cast<Expr *>(C.getExpr(I).second));
if (!ER.isUsable())
continue;

ER = Self.getSema().OpenACC().CheckGangExpr(C.getExpr(I).first, ER.get());
if (!ER.isUsable())
continue;
TransformedGangKinds.push_back(C.getExpr(I).first);
TransformedIntExprs.push_back(ER.get());
}

NewClause = OpenACCGangClause::Create(
Self.getSema().getASTContext(), ParsedClause.getBeginLoc(),
ParsedClause.getLParenLoc(), TransformedGangKinds, TransformedIntExprs,
ParsedClause.getEndLoc());
}
} // namespace
template <typename Derived>
OpenACCClause *TreeTransform<Derived>::TransformOpenACCClause(
Expand Down
16 changes: 14 additions & 2 deletions clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10003,7 +10003,8 @@ void ASTReader::finishPendingActions() {

auto RTD = cast<RedeclarableTemplateDecl>(D)->getCanonicalDecl();
for (auto *R = getMostRecentExistingDecl(RTD); R; R = R->getPreviousDecl())
cast<RedeclarableTemplateDecl>(R)->Common = RTD->Common;
cast<RedeclarableTemplateDecl>(R)->setCommonPtr(
RTD->getCommonPtrInternal());
}
PendingDefinitions.clear();

Expand Down Expand Up @@ -12326,6 +12327,18 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() {
return OpenACCTileClause::Create(getContext(), BeginLoc, LParenLoc,
SizeExprs, EndLoc);
}
case OpenACCClauseKind::Gang: {
SourceLocation LParenLoc = readSourceLocation();
unsigned NumExprs = readInt();
llvm::SmallVector<OpenACCGangKind> GangKinds;
llvm::SmallVector<Expr *> Exprs;
for (unsigned I = 0; I < NumExprs; ++I) {
GangKinds.push_back(readEnum<OpenACCGangKind>());
Exprs.push_back(readSubExpr());
}
return OpenACCGangClause::Create(getContext(), BeginLoc, LParenLoc,
GangKinds, Exprs, EndLoc);
}

case OpenACCClauseKind::Finalize:
case OpenACCClauseKind::IfPresent:
Expand All @@ -12342,7 +12355,6 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() {
case OpenACCClauseKind::Bind:
case OpenACCClauseKind::DeviceNum:
case OpenACCClauseKind::DefaultAsync:
case OpenACCClauseKind::Gang:
case OpenACCClauseKind::Invalid:
llvm_unreachable("Clause serialization not yet implemented");
}
Expand Down
18 changes: 9 additions & 9 deletions clang/lib/Serialization/ASTReaderDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2416,11 +2416,13 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
// Make sure we've allocated the Common pointer first. We do this before
// VisitTemplateDecl so that getCommonPtr() can be used during initialization.
RedeclarableTemplateDecl *CanonD = D->getCanonicalDecl();
if (!CanonD->Common) {
CanonD->Common = CanonD->newCommon(Reader.getContext());
if (!CanonD->getCommonPtrInternal()) {
CanonD->setCommonPtr(CanonD->newCommon(Reader.getContext()));
Reader.PendingDefinitions.insert(CanonD);
}
D->Common = CanonD->Common;
D->setCommonPtr(CanonD->getCommonPtrInternal());
if (Record.readInt())
D->setMemberSpecialization();

// If this is the first declaration of the template, fill in the information
// for the 'common' pointer.
Expand All @@ -2429,8 +2431,6 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
assert(RTD->getKind() == D->getKind() &&
"InstantiatedFromMemberTemplate kind mismatch");
D->setInstantiatedFromMemberTemplate(RTD);
if (Record.readInt())
D->setMemberSpecialization();
}
}

Expand Down Expand Up @@ -2562,12 +2562,12 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
D->TemplateParams = Params;

RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D);
D->InstantiatedFromMember.setInt(Record.readInt());

// These are read/set from/to the first declaration.
if (ThisDeclID == Redecl.getFirstID()) {
D->InstantiatedFromMember.setPointer(
readDeclAs<ClassTemplatePartialSpecializationDecl>());
D->InstantiatedFromMember.setInt(Record.readInt());
readDeclAs<ClassTemplatePartialSpecializationDecl>());
}
}

Expand Down Expand Up @@ -2660,12 +2660,12 @@ void ASTDeclReader::VisitVarTemplatePartialSpecializationDecl(
D->TemplateParams = Params;

RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D);
D->InstantiatedFromMember.setInt(Record.readInt());

// These are read/set from/to the first declaration.
if (ThisDeclID == Redecl.getFirstID()) {
D->InstantiatedFromMember.setPointer(
readDeclAs<VarTemplatePartialSpecializationDecl>());
D->InstantiatedFromMember.setInt(Record.readInt());
}
}

Expand Down Expand Up @@ -2888,7 +2888,7 @@ void ASTDeclReader::mergeRedeclarableTemplate(RedeclarableTemplateDecl *D,
// If we merged the template with a prior declaration chain, merge the
// common pointer.
// FIXME: Actually merge here, don't just overwrite.
D->Common = D->getCanonicalDecl()->Common;
D->setCommonPtr(D->getCanonicalDecl()->getCommonPtrInternal());
}

/// "Cast" to type T, asserting if we don't have an implicit conversion.
Expand Down
11 changes: 10 additions & 1 deletion clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8182,6 +8182,16 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
AddStmt(E);
return;
}
case OpenACCClauseKind::Gang: {
const auto *GC = cast<OpenACCGangClause>(C);
writeSourceLocation(GC->getLParenLoc());
writeUInt32(GC->getNumExprs());
for (unsigned I = 0; I < GC->getNumExprs(); ++I) {
writeEnum(GC->getExpr(I).first);
AddStmt(const_cast<Expr *>(GC->getExpr(I).second));
}
return;
}

case OpenACCClauseKind::Finalize:
case OpenACCClauseKind::IfPresent:
Expand All @@ -8198,7 +8208,6 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
case OpenACCClauseKind::Bind:
case OpenACCClauseKind::DeviceNum:
case OpenACCClauseKind::DefaultAsync:
case OpenACCClauseKind::Gang:
case OpenACCClauseKind::Invalid:
llvm_unreachable("Clause serialization not yet implemented");
}
Expand Down
17 changes: 7 additions & 10 deletions clang/lib/Serialization/ASTWriterDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1713,14 +1713,13 @@ void ASTDeclWriter::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) {
void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
VisitRedeclarable(D);

Record.push_back(D->isMemberSpecialization());

// Emit data to initialize CommonOrPrev before VisitTemplateDecl so that
// getCommonPtr() can be used while this is still initializing.
if (D->isFirstDecl()) {
if (D->isFirstDecl())
// This declaration owns the 'common' pointer, so serialize that data now.
Record.AddDeclRef(D->getInstantiatedFromMemberTemplate());
if (D->getInstantiatedFromMemberTemplate())
Record.push_back(D->isMemberSpecialization());
}

VisitTemplateDecl(D);
Record.push_back(D->getIdentifierNamespace());
Expand Down Expand Up @@ -1806,11 +1805,10 @@ void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl(

VisitClassTemplateSpecializationDecl(D);

Record.push_back(D->isMemberSpecialization());
// These are read/set from/to the first declaration.
if (D->getPreviousDecl() == nullptr) {
if (D->isFirstDecl())
Record.AddDeclRef(D->getInstantiatedFromMember());
Record.push_back(D->isMemberSpecialization());
}

Code = serialization::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION;
}
Expand Down Expand Up @@ -1874,12 +1872,11 @@ void ASTDeclWriter::VisitVarTemplatePartialSpecializationDecl(
Record.AddTemplateParameterList(D->getTemplateParameters());

VisitVarTemplateSpecializationDecl(D);
Record.push_back(D->isMemberSpecialization());

// These are read/set from/to the first declaration.
if (D->getPreviousDecl() == nullptr) {
if (D->isFirstDecl())
Record.AddDeclRef(D->getInstantiatedFromMember());
Record.push_back(D->isMemberSpecialization());
}

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

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

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

Expand Down
4 changes: 4 additions & 0 deletions clang/test/AST/ByteCode/cxx1z.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@ namespace Temp {

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

void Func() {
A<const char*, __func__> a; // both-error {{pointer to subobject of predefined '__func__' variable}}
}
82 changes: 82 additions & 0 deletions clang/test/AST/ast-print-openacc-loop-construct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,86 @@ void foo() {
for(;;)
for(;;)
for(;;);

// CHECK: #pragma acc loop gang(dim: 2)
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc loop gang(dim:2)
for(;;);

// CHECK: #pragma acc loop gang(static: i)
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc loop gang(static:i)
for(;;);

// CHECK: #pragma acc loop gang(static: i) gang(dim: 2)
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc loop gang(static:i) gang(dim:2)
for(;;);

// CHECK: #pragma acc parallel
// CHECK-NEXT: #pragma acc loop gang(dim: 2)
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc parallel
#pragma acc loop gang(dim:2)
for(;;);

// CHECK: #pragma acc parallel
// CHECK-NEXT: #pragma acc loop gang(static: i)
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc parallel
#pragma acc loop gang(static:i)
for(;;);

// CHECK: #pragma acc parallel
// CHECK-NEXT: #pragma acc loop gang(static: i) gang(dim: 2)
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc parallel
#pragma acc loop gang(static:i) gang(dim:2)
for(;;);

// CHECK: #pragma acc kernels
// CHECK-NEXT: #pragma acc loop gang(num: i) gang(static: i)
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc kernels
#pragma acc loop gang(i) gang(static:i)
for(;;);

// CHECK: #pragma acc kernels
// CHECK-NEXT: #pragma acc loop gang(num: i) gang(static: i)
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc kernels
#pragma acc loop gang(num:i) gang(static:i)
for(;;);

// CHECK: #pragma acc serial
// CHECK-NEXT: #pragma acc loop gang(static: i)
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc serial
#pragma acc loop gang(static:i)
for(;;);

// CHECK: #pragma acc serial
// CHECK-NEXT: #pragma acc loop gang(static: *)
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc serial
#pragma acc loop gang(static:*)
for(;;);

// CHECK: #pragma acc serial
// CHECK-NEXT: #pragma acc loop
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc serial
#pragma acc loop gang
for(;;);
}
12 changes: 12 additions & 0 deletions clang/test/Analysis/pointer-sub.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=security.PointerSub -analyzer-output=text-minimal -verify %s

typedef int * Ptr;

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

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

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

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

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

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

long double operator"" _RESERVED(long double);
// since-cxx11-warning@-1 {{identifier '_RESERVED' preceded by whitespace in a literal operator declaration is deprecated}}
#pragma clang diagnostic pop
#endif
} // namespace cwg2521
Expand Down
7 changes: 3 additions & 4 deletions clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,16 @@ void call_with_lambda() {

template<typename ... Args> static void f1()
{
(void)^(Args args) { // expected-error{{block contains unexpanded parameter pack 'Args'}}
(void)^(Args args) { // expected-error{{expression contains unexpanded parameter pack 'Args'}}
};
}

template<typename ... Args> static void f2()
{
// FIXME: Allow this.
f(
^(Args args) // expected-error{{block contains unexpanded parameter pack 'Args'}}
^(Args args)
{ }
... // expected-error{{pack expansion does not contain any unexpanded parameter packs}}
...
);
}

Expand Down
2 changes: 1 addition & 1 deletion clang/test/CXX/lex/lex.literal/lex.ext/p1.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wno-deprecated-literal-operator -verify %s

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

using size_t = decltype(sizeof(int));

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

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

using size_t = decltype(sizeof(int));

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

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

namespace std_example {

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

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

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

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

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

namespace std_example {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

namespace rdar13605348 {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

template <int> class X2; // expected-note{{template is declared here}} \
// expected-note{{template is declared here}}
Expand Down
175 changes: 175 additions & 0 deletions clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
// RUN: %clang_cc1 -std=c++20 -verify %s
// expected-no-diagnostics

template<typename T>
concept D = true;

template<typename T>
struct A {
template<typename U, bool V>
void f() requires V;

template<>
void f<short, true>();

template<D U>
void g();

template<typename U, bool V> requires V
struct B;

template<typename U, bool V> requires V
struct B<U*, V>;

template<>
struct B<short, true>;

template<D U>
struct C;

template<D U>
struct C<U*>;

template<typename U, bool V> requires V
static int x;

template<typename U, bool V> requires V
static int x<U*, V>;

template<>
int x<short, true>;

template<D U>
static int y;

template<D U>
static int y<U*>;
};

template<typename T>
template<typename U, bool V>
void A<T>::f() requires V { }

template<typename T>
template<D U>
void A<T>::g() { }

template<typename T>
template<typename U, bool V> requires V
struct A<T>::B { };

template<typename T>
template<typename U, bool V> requires V
struct A<T>::B<U*, V> { };

template<typename T>
template<typename U, bool V> requires V
struct A<T>::B<U&, V> { };

template<typename T>
template<D U>
struct A<T>::C { };

template<typename T>
template<D U>
struct A<T>::C<U*> { };

template<typename T>
template<typename U, bool V> requires V
int A<T>::x = 0;

template<typename T>
template<typename U, bool V> requires V
int A<T>::x<U*, V> = 0;

template<typename T>
template<typename U, bool V> requires V
int A<T>::x<U&, V> = 0;

template<typename T>
template<D U>
int A<T>::y = 0;

template<typename T>
template<D U>
int A<T>::y<U*> = 0;

template<>
template<typename U, bool V>
void A<short>::f() requires V;

template<>
template<>
void A<short>::f<int, true>();

template<>
template<>
void A<void>::f<int, true>();

template<>
template<D U>
void A<short>::g();

template<>
template<typename U, bool V> requires V
struct A<int>::B;

template<>
template<>
struct A<int>::B<int, true>;

template<>
template<>
struct A<void>::B<int, true>;

template<>
template<typename U, bool V> requires V
struct A<int>::B<U*, V>;

template<>
template<typename U, bool V> requires V
struct A<int>::B<U&, V>;

template<>
template<D U>
struct A<int>::C;

template<>
template<D U>
struct A<int>::C<U*>;

template<>
template<D U>
struct A<int>::C<U&>;

template<>
template<typename U, bool V> requires V
int A<long>::x;

template<>
template<>
int A<long>::x<int, true>;

template<>
template<>
int A<void>::x<int, true>;

template<>
template<typename U, bool V> requires V
int A<long>::x<U*, V>;

template<>
template<typename U, bool V> requires V
int A<long>::x<U&, V>;

template<>
template<D U>
int A<long>::y;

template<>
template<D U>
int A<long>::y<U*>;

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

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

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

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

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

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

template<int N, int M> class B3n;

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

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

C1<> c1; // expected-note{{while checking a default template argument}}
228 changes: 228 additions & 0 deletions clang/test/CXX/temp/temp.spec/temp.expl.spec/p7.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s

namespace Undefined {
template<typename T>
struct A {
template<typename U>
static constexpr int f(); // expected-note {{declared here}}

template<typename U>
static const int x; // expected-note {{declared here}}

template<typename U>
static const int x<U*>; // expected-note {{declared here}}

template<typename U>
struct B; // expected-note {{template is declared here}}

template<typename U>
struct B<U*>; // expected-note {{template is declared here}}
};

template<>
template<typename U>
constexpr int A<short>::f() {
return A<long>::f<U>();
}

template<>
template<typename U>
constexpr int A<short>::x = A<long>::x<U>;

template<>
template<typename U>
constexpr int A<short>::x<U*> = A<long>::x<U*>;

template<>
template<typename U>
struct A<short>::B<U*> {
static constexpr int y = A<long>::B<U*>::y;
};

template<>
template<typename U>
struct A<short>::B {
static constexpr int y = A<long>::B<U>::y;
};

template<>
template<typename U>
constexpr int A<long>::f() {
return 1;
}

template<>
template<typename U>
constexpr int A<long>::x = 1;

template<>
template<typename U>
constexpr int A<long>::x<U*> = 2;

template<>
template<typename U>
struct A<long>::B {
static constexpr int y = 1;
};

template<>
template<typename U>
struct A<long>::B<U*> {
static constexpr int y = 2;
};

static_assert(A<int>::f<int>() == 0); // expected-error {{static assertion expression is not an integral constant expression}}
// expected-note@-1 {{undefined function 'f<int>' cannot be used in a constant expression}}
static_assert(A<int>::x<int> == 0); // expected-error {{static assertion expression is not an integral constant expression}}
// expected-note@-1 {{initializer of 'x<int>' is unknown}}
static_assert(A<int>::x<int*> == 0); // expected-error {{static assertion expression is not an integral constant expression}}
// expected-note@-1 {{initializer of 'x<int *>' is unknown}}
static_assert(A<int>::B<int>::y == 0); // expected-error {{implicit instantiation of undefined template 'Undefined::A<int>::B<int>'}}
static_assert(A<int>::B<int*>::y == 0); // expected-error {{implicit instantiation of undefined template 'Undefined::A<int>::B<int *>'}}

static_assert(A<short>::f<int>() == 1);
static_assert(A<short>::x<int> == 1);
static_assert(A<short>::x<int*> == 2);
static_assert(A<short>::B<int>::y == 1);
static_assert(A<short>::B<int*>::y == 2);
} // namespace Undefined

namespace Defined {
template<typename T>
struct A {
template<typename U>
static constexpr int f() {
return 0;
};

template<typename U>
static const int x = 0;

template<typename U>
static const int x<U*> = 0;

template<typename U>
struct B {
static constexpr int y = 0;
};

template<typename U>
struct B<U*> {
static constexpr int y = 0;
};
};

template<>
template<typename U>
constexpr int A<short>::f() {
return A<long>::f<U>();
}

template<>
template<typename U>
constexpr int A<short>::x = A<long>::x<U>;

template<>
template<typename U>
constexpr int A<short>::x<U*> = A<long>::x<U*>;

template<>
template<typename U>
struct A<short>::B<U*> {
static constexpr int y = A<long>::B<U*>::y;
};

template<>
template<typename U>
struct A<short>::B {
static constexpr int y = A<long>::B<U>::y;
};

template<>
template<typename U>
constexpr int A<long>::f() {
return 1;
}

template<>
template<typename U>
constexpr int A<long>::x = 1;

template<>
template<typename U>
constexpr int A<long>::x<U*> = 2;

template<>
template<typename U>
struct A<long>::B {
static constexpr int y = 1;
};

template<>
template<typename U>
struct A<long>::B<U*> {
static constexpr int y = 2;
};

static_assert(A<int>::f<int>() == 0);
static_assert(A<int>::x<int> == 0);
static_assert(A<int>::x<int*> == 0);
static_assert(A<int>::B<int>::y == 0);
static_assert(A<int>::B<int*>::y == 0);

static_assert(A<short>::f<int>() == 1);
static_assert(A<short>::x<int> == 1);
static_assert(A<short>::x<int*> == 2);
static_assert(A<short>::B<int>::y == 1);
static_assert(A<short>::B<int*>::y == 2);
} // namespace Defined

namespace Dependent {
template<int I>
struct A {
template<int J>
static constexpr int f();

template<int J>
static const int x;

template<int J>
struct B;
};

template<>
template<int J>
constexpr int A<0>::f() {
return A<1>::f<J>();
}

template<>
template<int J>
constexpr int A<1>::f() {
return J;
}

template<>
template<int J>
constexpr int A<0>::x = A<1>::x<J>;

template<>
template<int J>
constexpr int A<1>::x = J;

template<>
template<int J>
struct A<0>::B {
static constexpr int y = A<1>::B<J>::y;
};

template<>
template<int J>
struct A<1>::B {
static constexpr int y = J;
};

static_assert(A<0>::f<2>() == 2);
static_assert(A<0>::x<2> == 2);
static_assert(A<0>::B<2>::y == 2);
} // namespace Dependent
4 changes: 2 additions & 2 deletions clang/test/FixIt/fixit-c++11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ const char *p = "foo"bar; // expected-error {{requires a space between}}
#define ord - '0'
int k = '4'ord; // expected-error {{requires a space between}}

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

void f() {
Expand Down
52 changes: 45 additions & 7 deletions clang/test/Frontend/plugin-attribute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,57 @@
// REQUIRES: plugins, examples
//--- good_attr.cpp
// expected-no-diagnostics
void fn1a() __attribute__((example)) {}
[[example]] void fn1b() {}
[[plugin::example]] void fn1c() {}
void fn2() __attribute__((example("somestring", 1, 2.0))) {}
// CHECK-COUNT-4: -AnnotateAttr 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} "example"
void fn1a() __attribute__((example)) {
__attribute__((example)) for (int i = 0; i < 9; ++i) {}
}
[[example]] void fn1b() {
[[example]] for (int i = 0; i < 9; ++i) {}
}
[[plugin::example]] void fn1c() {
[[plugin::example]] for (int i = 0; i < 9; ++i) {}
}
void fn2() __attribute__((example("somestring", 1, 2.0))) {
__attribute__((example("abc", 3, 4.0))) for (int i = 0; i < 9; ++i) {}
}
template <int N> void template_fn() __attribute__((example("template", N))) {
__attribute__((example("def", N + 1))) for (int i = 0; i < 9; ++i) {}
}
void fn3() { template_fn<5>(); }
// CHECK: -AttributedStmt 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}}
// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} "example"
// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} "example"
// CHECK: -AttributedStmt 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}}
// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} "example"
// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} "example"
// CHECK: -AttributedStmt 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}}
// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} "example"
// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} "example"
// CHECK: -AttributedStmt 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}}
// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} "example"
// CHECK: -StringLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'const char[{{[0-9]+}}]' lvalue "abc"
// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 3
// CHECK: -FloatingLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'double' 4.000000e+00
// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} "example"
// CHECK: -StringLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'const char[{{[0-9]+}}]' lvalue "somestring"
// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 1
// CHECK: -FloatingLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'double' 2.000000e+00
// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} Implicit "example"
// CHECK: -StringLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'const char[{{[0-9]+}}]' lvalue "def"
// CHECK: -BinaryOperator 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' '+'
// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} 'int' 5
// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 1
// CHECK: -AnnotateAttr 0x{{[0-9a-z]+}} {{<line:[0-9]+:[0-9]+(, col:[0-9]+)?>}} "example"
// CHECK: -StringLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'const char[{{[0-9]+}}]' lvalue "template"
// CHECK: -IntegerLiteral 0x{{[0-9a-z]+}} {{<col:[0-9]+(, col:[0-9]+)?>}} 'int' 5

//--- bad_attr.cpp
int var1 __attribute__((example("otherstring"))) = 1; // expected-warning {{'example' attribute only applies to functions}}
class Example {
void __attribute__((example)) fn3(); // expected-error {{'example' attribute only allowed at file scope}}
};
void fn4() __attribute__((example(123))) { } // expected-error {{first argument to the 'example' attribute must be a string literal}}
void fn5() __attribute__((example("a","b", 3, 4.0))) { } // expected-error {{'example' attribute only accepts at most three arguments}}
void fn4() __attribute__((example(123))) { // expected-error {{first argument to the 'example' attribute must be a string literal}}
__attribute__((example("somestring"))) while (true); // expected-warning {{'example' attribute only applies to for loop statements}}
}
void fn5() __attribute__((example("a","b", 3, 4.0))) { // expected-error {{'example' attribute only accepts at most three arguments}}
__attribute__((example("a","b", 3, 4.0))) for (int i = 0; i < 10; ++i) {} // expected-error {{'example' attribute only accepts at most three arguments}}
}
18 changes: 18 additions & 0 deletions clang/test/Headers/import_header_unit_after_pragma.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// RUN: rm -fR %t
// RUN: split-file %s %t
// RUN: cd %t
// RUN: %clang_cc1 -verify -std=c++20 -emit-header-unit -xc++-user-header bz0.h
// RUN: %clang_cc1 -verify -std=c++20 -emit-header-unit -xc++-user-header -fmodule-file=bz0.pcm bz.cpp

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

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

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

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

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

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

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

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

// Trigger the instantiation of a template in 'a' that uses a type defined in
// 'common'. That type is not visible here.
Expand Down Expand Up @@ -190,9 +199,7 @@ namespace hidden_specializations {
cls<char*> uk4; // expected-error 1+{{partial specialization of 'cls<T *>' must be imported}} expected-error 1+{{definition of}}
cls<void>::nested_cls unk1; // expected-error 1+{{explicit specialization of 'nested_cls' must be imported}} expected-error 1+{{definition of}}
cls<void>::nested_cls_t<int> unk2; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}} expected-error 1+{{definition of}}
// expected-error@cxx-templates-unimported.h:29 {{explicit specialization of 'nested_cls_t' must be imported}}
// expected-note@-2 {{in evaluation of exception specification}}
cls<void>::nested_cls_t<char> unk3; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}}
cls<void>::nested_cls_t<char> unk3; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}} expected-error 1+{{definition of}}

// For enums, uses that would trigger instantiations of definitions are not
// allowed.
Expand Down
29 changes: 16 additions & 13 deletions clang/test/Parser/cxx11-user-defined-literals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,19 @@ int cake() __attribute__((availability(macosx, unavailable, message = "is a lie"
#endif

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

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

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

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

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

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

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

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

// Make sure we treat UCNs and UTF-8 as equivalent.
Expand Down
50 changes: 22 additions & 28 deletions clang/test/ParserOpenACC/parse-clauses.c
Original file line number Diff line number Diff line change
Expand Up @@ -1202,76 +1202,65 @@ void Tile() {
}

void Gang() {
// expected-warning@+1{{OpenACC clause 'gang' not yet implemented, clause ignored}}
#pragma acc loop gang
for(;;){}
// expected-error@+3{{expected expression}}
// expected-error@+2{{expected ')'}}
// expected-note@+1{{to match this '('}}
#pragma acc loop gang(
for(;;){}
// expected-error@+2{{expected expression}}
// expected-warning@+1{{OpenACC clause 'gang' not yet implemented, clause ignored}}
// expected-error@+1{{expected expression}}
#pragma acc loop gang()
for(;;){}

// expected-error@+2{{expected expression}}
// expected-warning@+1{{OpenACC clause 'gang' not yet implemented, clause ignored}}
// expected-error@+1{{expected expression}}
#pragma acc loop gang(5, *)
for(;;){}

// expected-error@+2{{expected expression}}
// expected-warning@+1{{OpenACC clause 'gang' not yet implemented, clause ignored}}
// expected-error@+1{{expected expression}}
#pragma acc loop gang(*)
for(;;){}

// expected-error@+2{{expected expression}}
// expected-warning@+1{{OpenACC clause 'gang' not yet implemented, clause ignored}}
// expected-error@+1{{expected expression}}
#pragma acc loop gang(5, num:*)
for(;;){}

// expected-error@+2{{expected expression}}
// expected-warning@+1{{OpenACC clause 'gang' not yet implemented, clause ignored}}
// expected-error@+1{{expected expression}}
#pragma acc loop gang(num:5, *)
for(;;){}

// expected-error@+2{{expected expression}}
// expected-warning@+1{{OpenACC clause 'gang' not yet implemented, clause ignored}}
// expected-error@+1{{expected expression}}
#pragma acc loop gang(num:5, num:*)
for(;;){}

// expected-error@+2{{expected expression}}
// expected-warning@+1{{OpenACC clause 'gang' not yet implemented, clause ignored}}
// expected-error@+1{{expected expression}}
#pragma acc loop gang(num:*)
for(;;){}

// expected-warning@+1{{OpenACC clause 'gang' not yet implemented, clause ignored}}
#pragma acc loop gang(dim:5)
#pragma acc loop gang(dim:2)
for(;;){}

// expected-error@+2{{expected expression}}
// expected-warning@+1{{OpenACC clause 'gang' not yet implemented, clause ignored}}
// expected-error@+1{{expected expression}}
#pragma acc loop gang(dim:5, dim:*)
for(;;){}

// expected-error@+2{{expected expression}}
// expected-warning@+1{{OpenACC clause 'gang' not yet implemented, clause ignored}}
// expected-error@+1{{expected expression}}
#pragma acc loop gang(dim:*)
for(;;){}

// expected-warning@+1{{OpenACC clause 'gang' not yet implemented, clause ignored}}
#pragma acc loop gang(static:*)
for(;;){}

// expected-warning@+1{{OpenACC clause 'gang' not yet implemented, clause ignored}}
// expected-error@+2{{OpenACC 'gang' clause may have at most one 'static' argument}}
// expected-note@+1{{previous expression is here}}
#pragma acc loop gang(static:*, static:5)
for(;;){}

// expected-warning@+1{{OpenACC clause 'gang' not yet implemented, clause ignored}}
#pragma acc kernels
#pragma acc loop gang(static:*, 5)
for(;;){}

// expected-warning@+1{{OpenACC clause 'gang' not yet implemented, clause ignored}}
#pragma acc kernels
#pragma acc loop gang(static:45, 5)
for(;;){}

Expand Down Expand Up @@ -1330,11 +1319,16 @@ void Gang() {
#pragma acc loop gang(dim:45
for(;;){}

// expected-warning@+1{{OpenACC clause 'gang' not yet implemented, clause ignored}}
#pragma acc loop gang(static:*, dim:returns_int(), 5)
#pragma acc kernels
#pragma acc loop gang(static:*, 5)
for(;;){}

// expected-error@+1{{argument to 'gang' clause dimension must be a constant expression}}
#pragma acc loop gang(static:*, dim:returns_int())
for(;;){}

// expected-warning@+1{{OpenACC clause 'gang' not yet implemented, clause ignored}}
// expected-error@+2 2{{'num' argument on 'gang' clause is not permitted on an orphaned 'loop' construct}}
// expected-error@+1{{argument to 'gang' clause dimension must be a constant expression}}
#pragma acc loop gang(num: 32, static:*, dim:returns_int(), 5)
for(;;){}

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

// __builtin_assume_aligned's second parameter is size_t, which may be 32 bits,
// so test differently when size_t is 32 bits and when it is 64 bits.
Expand Down
64 changes: 64 additions & 0 deletions clang/test/SemaCXX/block-packs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin -fsyntax-only -verify -Wno-unused %s
// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin -fsyntax-only -verify -Wno-unused %s -frecovery-ast -frecovery-ast-type

template <typename ...Ts>
void f() {
((^ { Ts t; }), ...);
((^ (Ts t) {}), ...);
((^ Ts () {}), ...);

^ { Ts t; }; // expected-error {{unexpanded parameter pack 'Ts'}}
^ (Ts t) {}; // expected-error {{unexpanded parameter pack 'Ts'}}
^ Ts () {}; // expected-error {{unexpanded parameter pack 'Ts'}}
}

template <typename ...Ts>
void gh109148() {
(^Ts); // expected-error {{expected expression}}

[] {
(^Ts); // expected-error {{expected expression}}
^Ts; // expected-error {{expected expression}}
^(Ts); // expected-error {{expected expression}}
^ Ts); // expected-error {{expected expression}}
};

([] {
(^Ts); // expected-error {{expected expression}}
^Ts; // expected-error {{expected expression}}
^(Ts); // expected-error {{expected expression}}
^ Ts); // expected-error {{expected expression}}
}, ...); // expected-error {{pack expansion does not contain any unexpanded parameter packs}}

[] { // expected-error {{unexpanded parameter pack 'Ts'}}
^ (Ts) {};
};

[] { // expected-error {{unexpanded parameter pack 'Ts'}}
^ { Ts x; };
};

[] { // expected-error {{unexpanded parameter pack 'Ts'}}
Ts s;
(^Ts); // expected-error {{expected expression}}
};

([] {
Ts s;
(^Ts); // expected-error {{expected expression}}
}, ...);

[] { // expected-error {{unexpanded parameter pack 'Ts'}}
^ { Ts s; return not_defined; }; // expected-error {{use of undeclared identifier 'not_defined'}}
};
}

void g() {
f<>();
f<int>();
f<long, float>();

gh109148<>();
gh109148<int>();
gh109148<long, float>();
}
1 change: 1 addition & 0 deletions clang/test/SemaCXX/builtin-assume-aligned.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -triple x86_64-linux-gnu %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -triple x86_64-linux-gnu %s -fexperimental-new-constant-interpreter

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

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

namespace rdar13589856 {
Expand Down
Loading