78 changes: 36 additions & 42 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1415,42 +1415,26 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit,
}

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

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

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

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

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

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

Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type,
Expand Down Expand Up @@ -5895,7 +5879,8 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceI
return false;

if (Self.RequireCompleteType(
KeyLoc, RhsT, diag::err_incomplete_type_used_in_type_trait_expr))
Rhs->getTypeLoc().getBeginLoc(), RhsT,
diag::err_incomplete_type_used_in_type_trait_expr))
return false;

return BaseInterface->isSuperClassOf(DerivedInterface);
Expand All @@ -5918,8 +5903,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceI
// If Base and Derived are class types and are different types
// (ignoring possible cv-qualifiers) then Derived shall be a
// complete type.
if (Self.RequireCompleteType(KeyLoc, RhsT,
diag::err_incomplete_type_used_in_type_trait_expr))
if (Self.RequireCompleteType(
Rhs->getTypeLoc().getBeginLoc(), RhsT,
diag::err_incomplete_type_used_in_type_trait_expr))
return false;

return cast<CXXRecordDecl>(rhsRecord->getDecl())
Expand Down Expand Up @@ -5971,7 +5957,8 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceI
return LhsT->isVoidType();

// A function definition requires a complete, non-abstract return type.
if (!Self.isCompleteType(KeyLoc, RhsT) || Self.isAbstractType(KeyLoc, RhsT))
if (!Self.isCompleteType(Rhs->getTypeLoc().getBeginLoc(), RhsT) ||
Self.isAbstractType(Rhs->getTypeLoc().getBeginLoc(), RhsT))
return false;

// Compute the result of add_rvalue_reference.
Expand Down Expand Up @@ -6021,12 +6008,14 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceI
// For both, T and U shall be complete types, (possibly cv-qualified)
// void, or arrays of unknown bound.
if (!LhsT->isVoidType() && !LhsT->isIncompleteArrayType() &&
Self.RequireCompleteType(KeyLoc, LhsT,
diag::err_incomplete_type_used_in_type_trait_expr))
Self.RequireCompleteType(
Lhs->getTypeLoc().getBeginLoc(), LhsT,
diag::err_incomplete_type_used_in_type_trait_expr))
return false;
if (!RhsT->isVoidType() && !RhsT->isIncompleteArrayType() &&
Self.RequireCompleteType(KeyLoc, RhsT,
diag::err_incomplete_type_used_in_type_trait_expr))
Self.RequireCompleteType(
Rhs->getTypeLoc().getBeginLoc(), RhsT,
diag::err_incomplete_type_used_in_type_trait_expr))
return false;

// cv void is never assignable.
Expand Down Expand Up @@ -6081,12 +6070,17 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceI
}
case BTT_IsLayoutCompatible: {
if (!LhsT->isVoidType() && !LhsT->isIncompleteArrayType())
Self.RequireCompleteType(KeyLoc, LhsT, diag::err_incomplete_type);
Self.RequireCompleteType(Lhs->getTypeLoc().getBeginLoc(), LhsT,
diag::err_incomplete_type);
if (!RhsT->isVoidType() && !RhsT->isIncompleteArrayType())
Self.RequireCompleteType(KeyLoc, RhsT, diag::err_incomplete_type);
Self.RequireCompleteType(Rhs->getTypeLoc().getBeginLoc(), RhsT,
diag::err_incomplete_type);

if (LhsT->isVariableArrayType() || RhsT->isVariableArrayType())
Self.Diag(KeyLoc, diag::err_vla_unsupported)
if (LhsT->isVariableArrayType())
Self.Diag(Lhs->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported)
<< 1 << tok::kw___is_layout_compatible;
if (RhsT->isVariableArrayType())
Self.Diag(Rhs->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported)
<< 1 << tok::kw___is_layout_compatible;
return Self.IsLayoutCompatible(LhsT, RhsT);
}
Expand Down
42 changes: 12 additions & 30 deletions clang/lib/Sema/SemaExprMember.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,6 @@ enum IMAKind {
/// The reference is a contextually-permitted abstract member reference.
IMA_Abstract,

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

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

DeclContext *DC = SemaRef.getFunctionLevelDeclContext();

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

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

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

if (couldInstantiateToStatic)
return IMA_Dependent;

// C++11 [expr.prim.general]p12:
// An id-expression that denotes a non-static data member or non-static
// member function of a class can only be used:
Expand Down Expand Up @@ -283,30 +268,27 @@ ExprResult Sema::BuildPossibleImplicitMemberExpr(
const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
UnresolvedLookupExpr *AsULE) {
switch (IMAKind Classification = ClassifyImplicitMemberAccess(*this, R)) {
switch (ClassifyImplicitMemberAccess(*this, R)) {
case IMA_Instance:
return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true, S);

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

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

case IMA_Error_StaticOrExplicitContext:
case IMA_Error_Unrelated:
Expand Down
65 changes: 58 additions & 7 deletions clang/lib/Sema/SemaOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,27 @@ bool diagnoseConstructAppertainment(SemaOpenACC &S, OpenACCDirectiveKind K,

bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind,
OpenACCClauseKind ClauseKind) {
// FIXME: For each clause as we implement them, we can add the
// 'legalization' list here.

// Do nothing so we can go to the 'unimplemented' diagnostic instead.
return true;
switch (ClauseKind) {
// FIXME: For each clause as we implement them, we can add the
// 'legalization' list here.
case OpenACCClauseKind::Default:
switch (DirectiveKind) {
case OpenACCDirectiveKind::Parallel:
case OpenACCDirectiveKind::Serial:
case OpenACCDirectiveKind::Kernels:
case OpenACCDirectiveKind::ParallelLoop:
case OpenACCDirectiveKind::SerialLoop:
case OpenACCDirectiveKind::KernelsLoop:
case OpenACCDirectiveKind::Data:
return true;
default:
return false;
}
default:
// Do nothing so we can go to the 'unimplemented' diagnostic instead.
return true;
}
llvm_unreachable("Invalid clause kind");
}
} // namespace

Expand All @@ -63,8 +79,43 @@ SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
return nullptr;
}

// TODO OpenACC: Switch over the clauses we implement here and 'create'
// them.
switch (Clause.getClauseKind()) {
case OpenACCClauseKind::Default: {
// Restrictions only properly implemented on 'compute' constructs, and
// 'compute' constructs are the only construct that can do anything with
// this yet, so skip/treat as unimplemented in this case.
if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Parallel &&
Clause.getDirectiveKind() != OpenACCDirectiveKind::Serial &&
Clause.getDirectiveKind() != OpenACCDirectiveKind::Kernels)
break;

// Don't add an invalid clause to the AST.
if (Clause.getDefaultClauseKind() == OpenACCDefaultClauseKind::Invalid)
return nullptr;

// OpenACC 3.3, Section 2.5.4:
// At most one 'default' clause may appear, and it must have a value of
// either 'none' or 'present'.
// Second half of the sentence is diagnosed during parsing.
auto Itr = llvm::find_if(ExistingClauses, [](const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Default;
});

if (Itr != ExistingClauses.end()) {
Diag(Clause.getBeginLoc(),
diag::err_acc_duplicate_clause_disallowed)
<< Clause.getDirectiveKind() << Clause.getClauseKind();
Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
return nullptr;
}

return OpenACCDefaultClause::Create(
getASTContext(), Clause.getDefaultClauseKind(), Clause.getBeginLoc(),
Clause.getLParenLoc(), Clause.getEndLoc());
}
default:
break;
}

Diag(Clause.getBeginLoc(), diag::warn_acc_clause_unimplemented)
<< Clause.getClauseKind();
Expand Down
86 changes: 83 additions & 3 deletions clang/lib/Sema/SemaOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4478,6 +4478,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
Params);
break;
}
// For 'target teams loop', collect all captured regions so codegen can
// later decide the best IR to emit given the associated loop-nest.
case OMPD_target_teams_loop:
case OMPD_target_teams_distribute_parallel_for:
case OMPD_target_teams_distribute_parallel_for_simd: {
Expand Down Expand Up @@ -6135,6 +6137,79 @@ processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack,
}
}

namespace {
/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
/// call in the associated loop-nest cannot be a 'parallel for'.
class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
Sema &SemaRef;

public:
bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }

// Is there a nested OpenMP loop bind(parallel)
void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
if (const auto *C = D->getSingleClause<OMPBindClause>())
if (C->getBindKind() == OMPC_BIND_parallel) {
TeamsLoopCanBeParallelFor = false;
// No need to continue visiting any more
return;
}
}
for (const Stmt *Child : D->children())
if (Child)
Visit(Child);
}

void VisitCallExpr(const CallExpr *C) {
// Function calls inhibit parallel loop translation of 'target teams loop'
// unless the assume-no-nested-parallelism flag has been specified.
// OpenMP API runtime library calls do not inhibit parallel loop
// translation, regardless of the assume-no-nested-parallelism.
if (C) {
bool IsOpenMPAPI = false;
auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl());
if (FD) {
std::string Name = FD->getNameInfo().getAsString();
IsOpenMPAPI = Name.find("omp_") == 0;
}
TeamsLoopCanBeParallelFor =
IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
if (!TeamsLoopCanBeParallelFor)
return;
}
for (const Stmt *Child : C->children())
if (Child)
Visit(Child);
}

void VisitCapturedStmt(const CapturedStmt *S) {
if (!S)
return;
Visit(S->getCapturedDecl()->getBody());
}

void VisitStmt(const Stmt *S) {
if (!S)
return;
for (const Stmt *Child : S->children())
if (Child)
Visit(Child);
}
explicit TeamsLoopChecker(Sema &SemaRef)
: SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}

private:
bool TeamsLoopCanBeParallelFor;
};
} // namespace

static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
TeamsLoopChecker Checker(SemaRef);
Checker.Visit(AStmt);
return Checker.teamsLoopCanBeParallelFor();
}

bool Sema::mapLoopConstruct(llvm::SmallVector<OMPClause *> &ClausesWithoutBind,
ArrayRef<OMPClause *> Clauses,
OpenMPBindClauseKind &BindKind,
Expand Down Expand Up @@ -10895,7 +10970,8 @@ StmtResult Sema::ActOnOpenMPTargetTeamsGenericLoopDirective(
setFunctionHasBranchProtectedScope();

return OMPTargetTeamsGenericLoopDirective::Create(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
teamsLoopCanBeParallelFor(AStmt, *this));
}

StmtResult Sema::ActOnOpenMPParallelGenericLoopDirective(
Expand Down Expand Up @@ -15645,14 +15721,19 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
CaptureRegion = OMPD_target;
break;
case OMPD_teams_loop:
case OMPD_target_teams_loop:
// For [target] teams loop, assume capture region is 'teams' so it's
// available for codegen later to use if/when necessary.
CaptureRegion = OMPD_teams;
break;
case OMPD_target_teams_distribute_parallel_for_simd:
if (OpenMPVersion >= 50 &&
(NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
CaptureRegion = OMPD_parallel;
break;
}
[[fallthrough]];
case OMPD_target_teams_loop:
case OMPD_target_teams_distribute_parallel_for:
// If this clause applies to the nested 'parallel' region, capture within
// the 'teams' region, otherwise do not capture.
Expand Down Expand Up @@ -15775,7 +15856,6 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_loop:
case OMPD_teams_loop:
case OMPD_teams:
case OMPD_tile:
case OMPD_unroll:
Expand Down
52 changes: 39 additions & 13 deletions clang/lib/Sema/SemaSYCL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
// This implements Semantic Analysis for SYCL constructs.
//===----------------------------------------------------------------------===//

#include "clang/Sema/SemaSYCL.h"
#include "clang/AST/Mangle.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaDiagnostic.h"
Expand All @@ -18,28 +19,30 @@ using namespace clang;
// SYCL device specific diagnostics implementation
// -----------------------------------------------------------------------------

Sema::SemaDiagnosticBuilder Sema::SYCLDiagIfDeviceCode(SourceLocation Loc,
SemaSYCL::SemaSYCL(Sema &S) : SemaBase(S) {}

Sema::SemaDiagnosticBuilder SemaSYCL::DiagIfDeviceCode(SourceLocation Loc,
unsigned DiagID) {
assert(getLangOpts().SYCLIsDevice &&
"Should only be called during SYCL compilation");
FunctionDecl *FD = dyn_cast<FunctionDecl>(getCurLexicalContext());
FunctionDecl *FD = dyn_cast<FunctionDecl>(SemaRef.getCurLexicalContext());
SemaDiagnosticBuilder::Kind DiagKind = [this, FD] {
if (!FD)
return SemaDiagnosticBuilder::K_Nop;
if (getEmissionStatus(FD) == Sema::FunctionEmissionStatus::Emitted)
if (SemaRef.getEmissionStatus(FD) == Sema::FunctionEmissionStatus::Emitted)
return SemaDiagnosticBuilder::K_ImmediateWithCallStack;
return SemaDiagnosticBuilder::K_Deferred;
}();
return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, FD, *this);
return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, FD, SemaRef);
}

static bool isZeroSizedArray(Sema &SemaRef, QualType Ty) {
if (const auto *CAT = SemaRef.getASTContext().getAsConstantArrayType(Ty))
static bool isZeroSizedArray(SemaSYCL &S, QualType Ty) {
if (const auto *CAT = S.getASTContext().getAsConstantArrayType(Ty))
return CAT->isZeroSize();
return false;
}

void Sema::deepTypeCheckForSYCLDevice(SourceLocation UsedAt,
void SemaSYCL::deepTypeCheckForDevice(SourceLocation UsedAt,
llvm::DenseSet<QualType> Visited,
ValueDecl *DeclToCheck) {
assert(getLangOpts().SYCLIsDevice &&
Expand All @@ -51,18 +54,18 @@ void Sema::deepTypeCheckForSYCLDevice(SourceLocation UsedAt,
auto Check = [&](QualType TypeToCheck, const ValueDecl *D) {
bool ErrorFound = false;
if (isZeroSizedArray(*this, TypeToCheck)) {
SYCLDiagIfDeviceCode(UsedAt, diag::err_typecheck_zero_array_size) << 1;
DiagIfDeviceCode(UsedAt, diag::err_typecheck_zero_array_size) << 1;
ErrorFound = true;
}
// Checks for other types can also be done here.
if (ErrorFound) {
if (NeedToEmitNotes) {
if (auto *FD = dyn_cast<FieldDecl>(D))
SYCLDiagIfDeviceCode(FD->getLocation(),
diag::note_illegal_field_declared_here)
DiagIfDeviceCode(FD->getLocation(),
diag::note_illegal_field_declared_here)
<< FD->getType()->isPointerType() << FD->getType();
else
SYCLDiagIfDeviceCode(D->getLocation(), diag::note_declared_at);
DiagIfDeviceCode(D->getLocation(), diag::note_declared_at);
}
}

Expand Down Expand Up @@ -93,8 +96,8 @@ void Sema::deepTypeCheckForSYCLDevice(SourceLocation UsedAt,
auto EmitHistory = [&]() {
// The first element is always nullptr.
for (uint64_t Index = 1; Index < History.size(); ++Index) {
SYCLDiagIfDeviceCode(History[Index]->getLocation(),
diag::note_within_field_of_type)
DiagIfDeviceCode(History[Index]->getLocation(),
diag::note_within_field_of_type)
<< History[Index]->getType();
}
};
Expand Down Expand Up @@ -130,3 +133,26 @@ void Sema::deepTypeCheckForSYCLDevice(SourceLocation UsedAt,
}
} while (!StackForRecursion.empty());
}

ExprResult SemaSYCL::BuildUniqueStableNameExpr(SourceLocation OpLoc,
SourceLocation LParen,
SourceLocation RParen,
TypeSourceInfo *TSI) {
return SYCLUniqueStableNameExpr::Create(getASTContext(), OpLoc, LParen,
RParen, TSI);
}

ExprResult SemaSYCL::ActOnUniqueStableNameExpr(SourceLocation OpLoc,
SourceLocation LParen,
SourceLocation RParen,
ParsedType ParsedTy) {
TypeSourceInfo *TSI = nullptr;
QualType Ty = SemaRef.GetTypeFromParser(ParsedTy, &TSI);

if (Ty.isNull())
return ExprError();
if (!TSI)
TSI = getASTContext().getTrivialTypeSourceInfo(Ty, LParen);

return BuildUniqueStableNameExpr(OpLoc, LParen, RParen, TSI);
}
8 changes: 0 additions & 8 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5093,14 +5093,6 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
EnterExpressionEvaluationContext EvalContext(
*this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);

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

// Introduce a new scope where local variable instantiations will be
// recorded, unless we're actually a member function within a local
// class, in which case we need to merge our results with the parent
Expand Down
11 changes: 11 additions & 0 deletions clang/lib/Sema/SemaTemplateVariadic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1243,6 +1243,17 @@ std::optional<unsigned> Sema::getFullyPackExpandedSize(TemplateArgument Arg) {
// expanded this pack expansion into the enclosing pack if we could.
if (Elem.isPackExpansion())
return std::nullopt;
// Don't guess the size of unexpanded packs. The pack within a template
// argument may have yet to be of a PackExpansion type before we see the
// ellipsis in the annotation stage.
//
// This doesn't mean we would invalidate the optimization: Arg can be an
// unexpanded pack regardless of Elem's dependence. For instance,
// A TemplateArgument that contains either a SubstTemplateTypeParmPackType
// or SubstNonTypeTemplateParmPackExpr is always considered Unexpanded, but
// the underlying TemplateArgument thereof may not.
if (Elem.containsUnexpandedParameterPack())
return std::nullopt;
}
return Pack.pack_size();
}
Expand Down
53 changes: 45 additions & 8 deletions clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaOpenACC.h"
#include "clang/Sema/SemaSYCL.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
Expand Down Expand Up @@ -2632,7 +2633,8 @@ class TreeTransform {
SourceLocation LParen,
SourceLocation RParen,
TypeSourceInfo *TSI) {
return getSema().BuildSYCLUniqueStableNameExpr(OpLoc, LParen, RParen, TSI);
return getSema().SYCL().BuildUniqueStableNameExpr(OpLoc, LParen, RParen,
TSI);
}

/// Build a new predefined expression.
Expand Down Expand Up @@ -3307,13 +3309,12 @@ class TreeTransform {

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

Expand Down Expand Up @@ -4034,6 +4035,11 @@ class TreeTransform {
llvm::SmallVector<OpenACCClause *>
TransformOpenACCClauseList(OpenACCDirectiveKind DirKind,
ArrayRef<const OpenACCClause *> OldClauses);

OpenACCClause *
TransformOpenACCClause(ArrayRef<const OpenACCClause *> ExistingClauses,
OpenACCDirectiveKind DirKind,
const OpenACCClause *OldClause);
};

template <typename Derived>
Expand Down Expand Up @@ -11074,13 +11080,44 @@ OMPClause *TreeTransform<Derived>::TransformOMPXBareClause(OMPXBareClause *C) {
//===----------------------------------------------------------------------===//
// OpenACC transformation
//===----------------------------------------------------------------------===//
template <typename Derived>
OpenACCClause *TreeTransform<Derived>::TransformOpenACCClause(
ArrayRef<const OpenACCClause *> ExistingClauses,
OpenACCDirectiveKind DirKind, const OpenACCClause *OldClause) {

SemaOpenACC::OpenACCParsedClause ParsedClause(
DirKind, OldClause->getClauseKind(), OldClause->getBeginLoc());
ParsedClause.setEndLoc(OldClause->getEndLoc());

if (const auto *WithParms = dyn_cast<OpenACCClauseWithParams>(OldClause))
ParsedClause.setLParenLoc(WithParms->getLParenLoc());

switch (OldClause->getClauseKind()) {
case OpenACCClauseKind::Default:
// There is nothing to do here as nothing dependent can appear in this
// clause. So just set the values so Sema can set the right value.
ParsedClause.setDefaultDetails(
cast<OpenACCDefaultClause>(OldClause)->getDefaultClauseKind());
break;
default:
assert(false && "Unhandled OpenACC clause in TreeTransform");
return nullptr;
}

return getSema().OpenACC().ActOnClause(ExistingClauses, ParsedClause);
}

template <typename Derived>
llvm::SmallVector<OpenACCClause *>
TreeTransform<Derived>::TransformOpenACCClauseList(
OpenACCDirectiveKind DirKind, ArrayRef<const OpenACCClause *> OldClauses) {
// TODO OpenACC: Ensure we loop through the list and transform the individual
// clauses.
return {};
llvm::SmallVector<OpenACCClause *> TransformedClauses;
for (const auto *Clause : OldClauses) {
if (OpenACCClause *TransformedClause = getDerived().TransformOpenACCClause(
TransformedClauses, DirKind, Clause))
TransformedClauses.push_back(TransformedClause);
}
return TransformedClauses;
}

template <typename Derived>
Expand Down
16 changes: 8 additions & 8 deletions clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6626,8 +6626,6 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {
"Invalid data, missing pragma diagnostic states");
FileID FID = ReadFileID(F, Record, Idx);
assert(FID.isValid() && "invalid FileID for transition");
// FIXME: Remove this once we don't need the side-effects.
(void)SourceMgr.getSLocEntryOrNull(FID);
unsigned Transitions = Record[Idx++];

// Note that we don't need to set up Parent/ParentOffset here, because
Expand Down Expand Up @@ -11756,14 +11754,16 @@ void ASTRecordReader::readOMPChildren(OMPChildren *Data) {

OpenACCClause *ASTRecordReader::readOpenACCClause() {
OpenACCClauseKind ClauseKind = readEnum<OpenACCClauseKind>();
// TODO OpenACC: We don't have these used anywhere, but eventually we should
// be constructing the Clauses with them, so these attributes can go away at
// that point.
[[maybe_unused]] SourceLocation BeginLoc = readSourceLocation();
[[maybe_unused]] SourceLocation EndLoc = readSourceLocation();
SourceLocation BeginLoc = readSourceLocation();
SourceLocation EndLoc = readSourceLocation();

switch (ClauseKind) {
case OpenACCClauseKind::Default:
case OpenACCClauseKind::Default: {
SourceLocation LParenLoc = readSourceLocation();
OpenACCDefaultClauseKind DCK = readEnum<OpenACCDefaultClauseKind>();
return OpenACCDefaultClause::Create(getContext(), DCK, BeginLoc, LParenLoc,
EndLoc);
}
case OpenACCClauseKind::Finalize:
case OpenACCClauseKind::IfPresent:
case OpenACCClauseKind::Seq:
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Serialization/ASTReaderStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2769,6 +2769,7 @@ void ASTStmtReader::VisitOMPTeamsGenericLoopDirective(
void ASTStmtReader::VisitOMPTargetTeamsGenericLoopDirective(
OMPTargetTeamsGenericLoopDirective *D) {
VisitOMPLoopDirective(D);
D->setCanBeParallelFor(Record.readBool());
}

void ASTStmtReader::VisitOMPParallelGenericLoopDirective(
Expand Down
28 changes: 23 additions & 5 deletions clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,13 @@ static TypeCode getTypeCodeForTypeClass(Type::TypeClass id) {

namespace {

std::set<const FileEntry *> GetAffectingModuleMaps(const Preprocessor &PP,
Module *RootModule) {
std::optional<std::set<const FileEntry *>>
GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) {
// Without implicit module map search, there's no good reason to know about
// any module maps that are not affecting.
if (!PP.getHeaderSearchInfo().getHeaderSearchOpts().ImplicitModuleMaps)
return std::nullopt;

SmallVector<const Module *> ModulesToProcess{RootModule};

const HeaderSearch &HS = PP.getHeaderSearchInfo();
Expand Down Expand Up @@ -4735,8 +4740,16 @@ void ASTWriter::computeNonAffectingInputFiles() {
if (!Cache->OrigEntry)
continue;

if (!isModuleMap(File.getFileCharacteristic()) ||
llvm::is_contained(AffectingModuleMaps, *Cache->OrigEntry))
// Don't prune anything other than module maps.
if (!isModuleMap(File.getFileCharacteristic()))
continue;

// Don't prune module maps if all are guaranteed to be affecting.
if (!AffectingModuleMaps)
continue;

// Don't prune module maps that are affecting.
if (llvm::is_contained(*AffectingModuleMaps, *Cache->OrigEntry))
continue;

IsSLocAffecting[I] = false;
Expand Down Expand Up @@ -7406,7 +7419,12 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
writeSourceLocation(C->getEndLoc());

switch (C->getClauseKind()) {
case OpenACCClauseKind::Default:
case OpenACCClauseKind::Default: {
const auto *DC = cast<OpenACCDefaultClause>(C);
writeSourceLocation(DC->getLParenLoc());
writeEnum(DC->getDefaultClauseKind());
return;
}
case OpenACCClauseKind::Finalize:
case OpenACCClauseKind::IfPresent:
case OpenACCClauseKind::Seq:
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Serialization/ASTWriterStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2821,6 +2821,7 @@ void ASTStmtWriter::VisitOMPTeamsGenericLoopDirective(
void ASTStmtWriter::VisitOMPTargetTeamsGenericLoopDirective(
OMPTargetTeamsGenericLoopDirective *D) {
VisitOMPLoopDirective(D);
Record.writeBool(D->canBeParallelFor());
Code = serialization::STMT_OMP_TARGET_TEAMS_GENERIC_LOOP_DIRECTIVE;
}

Expand Down
1 change: 1 addition & 0 deletions clang/test/APINotes/instancetype.m
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -verify %s

@import InstancetypeModule;
Expand Down
120 changes: 120 additions & 0 deletions clang/test/AST/Interp/builtin-functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,9 @@ void test_noexcept(int *i) {
#undef TEST_TYPE
} // end namespace test_launder


/// FIXME: The commented out tests here use a IntAP value and fail.
/// This currently means we will leak the IntAP value since nothing cleans it up.
namespace clz {
char clz1[__builtin_clz(1) == BITSIZE(int) - 1 ? 1 : -1];
char clz2[__builtin_clz(7) == BITSIZE(int) - 3 ? 1 : -1];
Expand All @@ -492,6 +495,63 @@ namespace clz {
char clz7[__builtin_clzs(0x1) == BITSIZE(short) - 1 ? 1 : -1];
char clz8[__builtin_clzs(0xf) == BITSIZE(short) - 4 ? 1 : -1];
char clz9[__builtin_clzs(0xfff) == BITSIZE(short) - 12 ? 1 : -1];

int clz10 = __builtin_clzg((unsigned char)0);
char clz11[__builtin_clzg((unsigned char)0, 42) == 42 ? 1 : -1];
char clz12[__builtin_clzg((unsigned char)0x1) == BITSIZE(char) - 1 ? 1 : -1];
char clz13[__builtin_clzg((unsigned char)0x1, 42) == BITSIZE(char) - 1 ? 1 : -1];
char clz14[__builtin_clzg((unsigned char)0xf) == BITSIZE(char) - 4 ? 1 : -1];
char clz15[__builtin_clzg((unsigned char)0xf, 42) == BITSIZE(char) - 4 ? 1 : -1];
char clz16[__builtin_clzg((unsigned char)(1 << (BITSIZE(char) - 1))) == 0 ? 1 : -1];
char clz17[__builtin_clzg((unsigned char)(1 << (BITSIZE(char) - 1)), 42) == 0 ? 1 : -1];
int clz18 = __builtin_clzg((unsigned short)0);
char clz19[__builtin_clzg((unsigned short)0, 42) == 42 ? 1 : -1];
char clz20[__builtin_clzg((unsigned short)0x1) == BITSIZE(short) - 1 ? 1 : -1];
char clz21[__builtin_clzg((unsigned short)0x1, 42) == BITSIZE(short) - 1 ? 1 : -1];
char clz22[__builtin_clzg((unsigned short)0xf) == BITSIZE(short) - 4 ? 1 : -1];
char clz23[__builtin_clzg((unsigned short)0xf, 42) == BITSIZE(short) - 4 ? 1 : -1];
char clz24[__builtin_clzg((unsigned short)(1 << (BITSIZE(short) - 1))) == 0 ? 1 : -1];
char clz25[__builtin_clzg((unsigned short)(1 << (BITSIZE(short) - 1)), 42) == 0 ? 1 : -1];
int clz26 = __builtin_clzg(0U);
char clz27[__builtin_clzg(0U, 42) == 42 ? 1 : -1];
char clz28[__builtin_clzg(0x1U) == BITSIZE(int) - 1 ? 1 : -1];
char clz29[__builtin_clzg(0x1U, 42) == BITSIZE(int) - 1 ? 1 : -1];
char clz30[__builtin_clzg(0xfU) == BITSIZE(int) - 4 ? 1 : -1];
char clz31[__builtin_clzg(0xfU, 42) == BITSIZE(int) - 4 ? 1 : -1];
char clz32[__builtin_clzg(1U << (BITSIZE(int) - 1)) == 0 ? 1 : -1];
char clz33[__builtin_clzg(1U << (BITSIZE(int) - 1), 42) == 0 ? 1 : -1];
int clz34 = __builtin_clzg(0UL);
char clz35[__builtin_clzg(0UL, 42) == 42 ? 1 : -1];
char clz36[__builtin_clzg(0x1UL) == BITSIZE(long) - 1 ? 1 : -1];
char clz37[__builtin_clzg(0x1UL, 42) == BITSIZE(long) - 1 ? 1 : -1];
char clz38[__builtin_clzg(0xfUL) == BITSIZE(long) - 4 ? 1 : -1];
char clz39[__builtin_clzg(0xfUL, 42) == BITSIZE(long) - 4 ? 1 : -1];
char clz40[__builtin_clzg(1UL << (BITSIZE(long) - 1)) == 0 ? 1 : -1];
char clz41[__builtin_clzg(1UL << (BITSIZE(long) - 1), 42) == 0 ? 1 : -1];
int clz42 = __builtin_clzg(0ULL);
char clz43[__builtin_clzg(0ULL, 42) == 42 ? 1 : -1];
char clz44[__builtin_clzg(0x1ULL) == BITSIZE(long long) - 1 ? 1 : -1];
char clz45[__builtin_clzg(0x1ULL, 42) == BITSIZE(long long) - 1 ? 1 : -1];
char clz46[__builtin_clzg(0xfULL) == BITSIZE(long long) - 4 ? 1 : -1];
char clz47[__builtin_clzg(0xfULL, 42) == BITSIZE(long long) - 4 ? 1 : -1];
char clz48[__builtin_clzg(1ULL << (BITSIZE(long long) - 1)) == 0 ? 1 : -1];
char clz49[__builtin_clzg(1ULL << (BITSIZE(long long) - 1), 42) == 0 ? 1 : -1];
#ifdef __SIZEOF_INT128__
// int clz50 = __builtin_clzg((unsigned __int128)0);
char clz51[__builtin_clzg((unsigned __int128)0, 42) == 42 ? 1 : -1];
char clz52[__builtin_clzg((unsigned __int128)0x1) == BITSIZE(__int128) - 1 ? 1 : -1];
char clz53[__builtin_clzg((unsigned __int128)0x1, 42) == BITSIZE(__int128) - 1 ? 1 : -1];
char clz54[__builtin_clzg((unsigned __int128)0xf) == BITSIZE(__int128) - 4 ? 1 : -1];
char clz55[__builtin_clzg((unsigned __int128)0xf, 42) == BITSIZE(__int128) - 4 ? 1 : -1];
#endif
#ifndef __AVR__
// int clz58 = __builtin_clzg((unsigned _BitInt(128))0);
char clz59[__builtin_clzg((unsigned _BitInt(128))0, 42) == 42 ? 1 : -1];
char clz60[__builtin_clzg((unsigned _BitInt(128))0x1) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1];
char clz61[__builtin_clzg((unsigned _BitInt(128))0x1, 42) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1];
char clz62[__builtin_clzg((unsigned _BitInt(128))0xf) == BITSIZE(_BitInt(128)) - 4 ? 1 : -1];
char clz63[__builtin_clzg((unsigned _BitInt(128))0xf, 42) == BITSIZE(_BitInt(128)) - 4 ? 1 : -1];
#endif
}

namespace ctz {
Expand All @@ -502,6 +562,66 @@ namespace ctz {
char ctz5[__builtin_ctzl(0x10L) == 4 ? 1 : -1];
char ctz6[__builtin_ctzll(0x100LL) == 8 ? 1 : -1];
char ctz7[__builtin_ctzs(1 << (BITSIZE(short) - 1)) == BITSIZE(short) - 1 ? 1 : -1];
int ctz8 = __builtin_ctzg((unsigned char)0);
char ctz9[__builtin_ctzg((unsigned char)0, 42) == 42 ? 1 : -1];
char ctz10[__builtin_ctzg((unsigned char)0x1) == 0 ? 1 : -1];
char ctz11[__builtin_ctzg((unsigned char)0x1, 42) == 0 ? 1 : -1];
char ctz12[__builtin_ctzg((unsigned char)0x10) == 4 ? 1 : -1];
char ctz13[__builtin_ctzg((unsigned char)0x10, 42) == 4 ? 1 : -1];
char ctz14[__builtin_ctzg((unsigned char)(1 << (BITSIZE(char) - 1))) == BITSIZE(char) - 1 ? 1 : -1];
char ctz15[__builtin_ctzg((unsigned char)(1 << (BITSIZE(char) - 1)), 42) == BITSIZE(char) - 1 ? 1 : -1];
int ctz16 = __builtin_ctzg((unsigned short)0);
char ctz17[__builtin_ctzg((unsigned short)0, 42) == 42 ? 1 : -1];
char ctz18[__builtin_ctzg((unsigned short)0x1) == 0 ? 1 : -1];
char ctz19[__builtin_ctzg((unsigned short)0x1, 42) == 0 ? 1 : -1];
char ctz20[__builtin_ctzg((unsigned short)0x10) == 4 ? 1 : -1];
char ctz21[__builtin_ctzg((unsigned short)0x10, 42) == 4 ? 1 : -1];
char ctz22[__builtin_ctzg((unsigned short)(1 << (BITSIZE(short) - 1))) == BITSIZE(short) - 1 ? 1 : -1];
char ctz23[__builtin_ctzg((unsigned short)(1 << (BITSIZE(short) - 1)), 42) == BITSIZE(short) - 1 ? 1 : -1];
int ctz24 = __builtin_ctzg(0U);
char ctz25[__builtin_ctzg(0U, 42) == 42 ? 1 : -1];
char ctz26[__builtin_ctzg(0x1U) == 0 ? 1 : -1];
char ctz27[__builtin_ctzg(0x1U, 42) == 0 ? 1 : -1];
char ctz28[__builtin_ctzg(0x10U) == 4 ? 1 : -1];
char ctz29[__builtin_ctzg(0x10U, 42) == 4 ? 1 : -1];
char ctz30[__builtin_ctzg(1U << (BITSIZE(int) - 1)) == BITSIZE(int) - 1 ? 1 : -1];
char ctz31[__builtin_ctzg(1U << (BITSIZE(int) - 1), 42) == BITSIZE(int) - 1 ? 1 : -1];
int ctz32 = __builtin_ctzg(0UL);
char ctz33[__builtin_ctzg(0UL, 42) == 42 ? 1 : -1];
char ctz34[__builtin_ctzg(0x1UL) == 0 ? 1 : -1];
char ctz35[__builtin_ctzg(0x1UL, 42) == 0 ? 1 : -1];
char ctz36[__builtin_ctzg(0x10UL) == 4 ? 1 : -1];
char ctz37[__builtin_ctzg(0x10UL, 42) == 4 ? 1 : -1];
char ctz38[__builtin_ctzg(1UL << (BITSIZE(long) - 1)) == BITSIZE(long) - 1 ? 1 : -1];
char ctz39[__builtin_ctzg(1UL << (BITSIZE(long) - 1), 42) == BITSIZE(long) - 1 ? 1 : -1];
int ctz40 = __builtin_ctzg(0ULL);
char ctz41[__builtin_ctzg(0ULL, 42) == 42 ? 1 : -1];
char ctz42[__builtin_ctzg(0x1ULL) == 0 ? 1 : -1];
char ctz43[__builtin_ctzg(0x1ULL, 42) == 0 ? 1 : -1];
char ctz44[__builtin_ctzg(0x10ULL) == 4 ? 1 : -1];
char ctz45[__builtin_ctzg(0x10ULL, 42) == 4 ? 1 : -1];
char ctz46[__builtin_ctzg(1ULL << (BITSIZE(long long) - 1)) == BITSIZE(long long) - 1 ? 1 : -1];
char ctz47[__builtin_ctzg(1ULL << (BITSIZE(long long) - 1), 42) == BITSIZE(long long) - 1 ? 1 : -1];
#ifdef __SIZEOF_INT128__
// int ctz48 = __builtin_ctzg((unsigned __int128)0);
char ctz49[__builtin_ctzg((unsigned __int128)0, 42) == 42 ? 1 : -1];
char ctz50[__builtin_ctzg((unsigned __int128)0x1) == 0 ? 1 : -1];
char ctz51[__builtin_ctzg((unsigned __int128)0x1, 42) == 0 ? 1 : -1];
char ctz52[__builtin_ctzg((unsigned __int128)0x10) == 4 ? 1 : -1];
char ctz53[__builtin_ctzg((unsigned __int128)0x10, 42) == 4 ? 1 : -1];
char ctz54[__builtin_ctzg((unsigned __int128)1 << (BITSIZE(__int128) - 1)) == BITSIZE(__int128) - 1 ? 1 : -1];
char ctz55[__builtin_ctzg((unsigned __int128)1 << (BITSIZE(__int128) - 1), 42) == BITSIZE(__int128) - 1 ? 1 : -1];
#endif
#ifndef __AVR__
// int ctz56 = __builtin_ctzg((unsigned _BitInt(128))0);
char ctz57[__builtin_ctzg((unsigned _BitInt(128))0, 42) == 42 ? 1 : -1];
char ctz58[__builtin_ctzg((unsigned _BitInt(128))0x1) == 0 ? 1 : -1];
char ctz59[__builtin_ctzg((unsigned _BitInt(128))0x1, 42) == 0 ? 1 : -1];
char ctz60[__builtin_ctzg((unsigned _BitInt(128))0x10) == 4 ? 1 : -1];
char ctz61[__builtin_ctzg((unsigned _BitInt(128))0x10, 42) == 4 ? 1 : -1];
char ctz62[__builtin_ctzg((unsigned _BitInt(128))1 << (BITSIZE(_BitInt(128)) - 1)) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1];
char ctz63[__builtin_ctzg((unsigned _BitInt(128))1 << (BITSIZE(_BitInt(128)) - 1), 42) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1];
#endif
}

namespace bswap {
Expand Down
18 changes: 18 additions & 0 deletions clang/test/AST/Interp/c.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,21 @@ const struct StrA * const sb = &sa;
const struct StrA sc = *sb;
_Static_assert(sc.a == 12, ""); // pedantic-ref-warning {{GNU extension}} \
// pedantic-expected-warning {{GNU extension}}

_Static_assert(((void*)0 + 1) != (void*)0, ""); // pedantic-expected-warning {{arithmetic on a pointer to void is a GNU extension}} \
// pedantic-expected-warning {{not an integer constant expression}} \
// pedantic-expected-note {{cannot perform pointer arithmetic on null pointer}} \
// pedantic-ref-warning {{arithmetic on a pointer to void is a GNU extension}} \
// pedantic-ref-warning {{not an integer constant expression}} \
// pedantic-ref-note {{cannot perform pointer arithmetic on null pointer}}

typedef __INTPTR_TYPE__ intptr_t;
int array[(intptr_t)(int*)1]; // ref-warning {{variable length array folded to constant array}} \
// pedantic-ref-warning {{variable length array folded to constant array}} \
// expected-warning {{variable length array folded to constant array}} \
// pedantic-expected-warning {{variable length array folded to constant array}}

int castViaInt[*(int*)(unsigned long)"test"]; // ref-error {{variable length array}} \
// pedantic-ref-error {{variable length array}} \
// expected-error {{variable length array}} \
// pedantic-expected-error {{variable length array}}
192 changes: 192 additions & 0 deletions clang/test/AST/Interp/const-eval.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
// RUN: %clang_cc1 -fsyntax-only -verify=both,ref -triple x86_64-linux %s -Wno-tautological-pointer-compare -Wno-pointer-to-int-cast
// RUN: %clang_cc1 -fsyntax-only -verify=both,expected -triple x86_64-linux %s -Wno-tautological-pointer-compare -Wno-pointer-to-int-cast -fexperimental-new-constant-interpreter -DNEW_INTERP
// RUN: %clang_cc1 -fsyntax-only -verify=both,ref -triple powerpc64-ibm-aix-xcoff %s -Wno-tautological-pointer-compare -Wno-pointer-to-int-cast
// RUN: %clang_cc1 -fsyntax-only -verify=both,expected -triple powerpc64-ibm-aix-xcoff %s -Wno-tautological-pointer-compare -Wno-pointer-to-int-cast -fexperimental-new-constant-interpreter -DNEW_INTERP

/// This is a version of test/Sema/const-eval.c with the
/// tests commented out that the new constant expression interpreter does
/// not support yet. They are all marked with the NEW_INTERP define:
///
/// - builtin_constant_p
/// - unions


#define EVAL_EXPR(testno, expr) enum { test##testno = (expr) }; struct check_positive##testno { int a[test##testno]; };
int x;
EVAL_EXPR(1, (_Bool)&x)
EVAL_EXPR(2, (int)(1.0+(double)4))
EVAL_EXPR(3, (int)(1.0+(float)4.0))
EVAL_EXPR(4, (_Bool)(1 ? (void*)&x : 0))
EVAL_EXPR(5, (_Bool)(int[]){0})
struct y {int x,y;};
EVAL_EXPR(6, (int)(1+(struct y*)0))
_Static_assert((long)&((struct y*)0)->y > 0, "");
EVAL_EXPR(7, (int)&((struct y*)0)->y)
EVAL_EXPR(8, (_Bool)"asdf")
EVAL_EXPR(9, !!&x)
EVAL_EXPR(10, ((void)1, 12))
void g0(void);
EVAL_EXPR(11, (g0(), 12)) // both-error {{not an integer constant expression}}
EVAL_EXPR(12, 1.0&&2.0)
EVAL_EXPR(13, x || 3.0) // both-error {{not an integer constant expression}}

unsigned int l_19 = 1;
EVAL_EXPR(14, (1 ^ l_19) && 1); // both-error {{not an integer constant expression}}

void f(void)
{
int a;
EVAL_EXPR(15, (_Bool)&a);
}

_Complex float g16 = (1.0f + 1.0fi);

// ?: in constant expressions.
int g17[(3?:1) - 2];

EVAL_EXPR(18, ((int)((void*)10 + 10)) == 20 ? 1 : -1);

struct s {
int a[(int)-1.0f]; // both-error {{array size is negative}}
};

EVAL_EXPR(19, ((int)&*(char*)10 == 10 ? 1 : -1));

#ifndef NEW_INTERP
EVAL_EXPR(20, __builtin_constant_p(*((int*) 10)));
#endif

EVAL_EXPR(21, (__imag__ 2i) == 2 ? 1 : -1);

EVAL_EXPR(22, (__real__ (2i+3)) == 3 ? 1 : -1);

int g23[(int)(1.0 / 1.0)] = { 1 }; // both-warning {{folded to constant array}}
int g24[(int)(1.0 / 1.0)] = { 1 , 2 }; // both-warning {{folded to constant array}} \
// both-warning {{excess elements in array initializer}}
int g25[(int)(1.0 + 1.0)], g26 = sizeof(g25); // both-warning {{folded to constant array}}

EVAL_EXPR(26, (_Complex double)0 ? -1 : 1)
EVAL_EXPR(27, (_Complex int)0 ? -1 : 1)
EVAL_EXPR(28, (_Complex double)1 ? 1 : -1)
EVAL_EXPR(29, (_Complex int)1 ? 1 : -1)

// PR4027
struct a { int x, y; };
static struct a V2 = (struct a)(struct a){ 1, 2};
static const struct a V1 = (struct a){ 1, 2};

EVAL_EXPR(30, (int)(_Complex float)((1<<30)-1) == (1<<30) ? 1 : -1)
EVAL_EXPR(31, (int*)0 == (int*)0 ? 1 : -1)
EVAL_EXPR(32, (int*)0 != (int*)0 ? -1 : 1)
EVAL_EXPR(33, (void*)0 - (void*)0 == 0 ? 1 : -1)

void foo(void) {}
EVAL_EXPR(34, (foo == (void *)0) ? -1 : 1)

// No PR. Mismatched bitwidths lead to a crash on second evaluation.
const _Bool constbool = 0;
EVAL_EXPR(35, constbool)
EVAL_EXPR(36, constbool)

EVAL_EXPR(37, ((void)1,2.0) == 2.0 ? 1 : -1)
EVAL_EXPR(38, __builtin_expect(1,1) == 1 ? 1 : -1)

// PR7884
EVAL_EXPR(39, __real__(1.f) == 1 ? 1 : -1)
EVAL_EXPR(40, __imag__(1.f) == 0 ? 1 : -1)

// From gcc testsuite
EVAL_EXPR(41, (int)(1+(_Complex unsigned)2))

void rdar8875946(void) {
double _Complex P;
float _Complex P2 = 3.3f + P;
}

double d = (d = 0.0); // both-error {{not a compile-time constant}}
double d2 = ++d; // both-error {{not a compile-time constant}}

int n = 2;
int intLvalue[*(int*)((long)&n ?: 1)] = { 1, 2 }; // both-error {{variable length array}}

union u { int a; char b[4]; };
char c = ((union u)(123456)).b[0]; // both-error {{not a compile-time constant}}

#ifndef NEW_INTERP
extern const int weak_int __attribute__((weak));
const int weak_int = 42;
int weak_int_test = weak_int; // both-error {{not a compile-time constant}}
#endif

int literalVsNull1 = "foo" == 0;
int literalVsNull2 = 0 == "foo";

// PR11385.
int castViaInt[*(int*)(unsigned long)"test"]; // both-error {{variable length array}}

// PR11391.
#ifndef NEW_INTERP
struct PR11391 { _Complex float f; } pr11391;
EVAL_EXPR(42, __builtin_constant_p(pr11391.f = 1))
#endif

// PR12043
float varfloat;
const float constfloat = 0;
EVAL_EXPR(43, varfloat && constfloat) // both-error {{not an integer constant expression}}
EVAL_EXPR(45, ((char*)-1) + 1 == 0 ? 1 : -1)
EVAL_EXPR(46, ((char*)-1) + 1 < (char*) -1 ? 1 : -1)
EVAL_EXPR(47, &x < &x + 1 ? 1 : -1)
EVAL_EXPR(48, &x != &x - 1 ? 1 : -1)
EVAL_EXPR(49, &x < &x - 100 ? 1 : -1) // ref-error {{not an integer constant expression}}

/// FIXME: Rejecting this is correct, BUT when converting the innermost pointer
/// to an integer, we do not preserve the information where it came from. So when we later
/// create a pointer from it, it also doesn't have that information, which means
/// hasSameBase() for those two pointers will return false. And in those cases, we emit
/// the diagnostic:
/// comparison between '&Test50' and '&(631578)' has unspecified value
extern struct Test50S Test50;
EVAL_EXPR(50, &Test50 < (struct Test50S*)((unsigned long)&Test50 + 10)) // both-error {{not an integer constant expression}} \
// expected-note {{comparison between}}

EVAL_EXPR(51, 0 != (float)1e99)

// PR21945
void PR21945(void) { int i = (({}), 0l); }

void PR24622(void);
struct PR24622 {} pr24622;
EVAL_EXPR(52, &pr24622 == (void *)&PR24622);

// We evaluate these by providing 2s' complement semantics in constant
// expressions, like we do for integers.
void *PR28739a = (__int128)(unsigned long)-1 + &PR28739a; // both-warning {{the pointer incremented by 18446744073709551615 refers past the last possible element for an array in 64-bit address space containing 64-bit (8-byte) elements (max possible 2305843009213693952 elements)}}

void *PR28739b = &PR28739b + (__int128)(unsigned long)-1; // both-warning {{refers past the last possible element}}
__int128 PR28739c = (&PR28739c + (__int128)(unsigned long)-1) - &PR28739c; // both-warning {{refers past the last possible element}}
void *PR28739d = &(&PR28739d)[(__int128)(unsigned long)-1]; // both-warning {{refers past the last possible element}}

struct PR35214_X {
int k;
int arr[];
};
int PR35214_x;
int PR35214_y = ((struct PR35214_X *)&PR35214_x)->arr[1]; // both-error {{not a compile-time constant}}
#ifndef NEW_INTERP
int *PR35214_z = &((struct PR35214_X *)&PR35214_x)->arr[1]; // ok, &PR35214_x + 2
#endif

/// From const-eval-64.c
EVAL_EXPR(53, ((char*)-1LL) + 1 == 0 ? 1 : -1)
EVAL_EXPR(54, ((char*)-1LL) + 1 < (char*) -1 ? 1 : -1)

/// === Additions ===
#if __SIZEOF_INT__ == 4
typedef __INTPTR_TYPE__ intptr_t;
const intptr_t A = (intptr_t)(((int*) 0) + 1);
const intptr_t B = (intptr_t)(((char*)0) + 3);
_Static_assert(A > B, "");
#else
#error :(
#endif
15 changes: 15 additions & 0 deletions clang/test/AST/Interp/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,21 @@ namespace FunctionReturnType {
constexpr int (*invalidFnPtr)() = m;
static_assert(invalidFnPtr() == 5, ""); // both-error {{not an integral constant expression}} \
// both-note {{non-constexpr function 'm'}}


namespace ToBool {
void mismatched(int x) {}
typedef void (*callback_t)(int);
void foo() {
callback_t callback = (callback_t)mismatched; // warns
/// Casts a function pointer to a boolean and then back to a function pointer.
/// This is extracted from test/Sema/callingconv-cast.c
callback = (callback_t)!mismatched; // both-warning {{address of function 'mismatched' will always evaluate to 'true'}} \
// both-note {{prefix with the address-of operator to silence this warning}}
}
}


}

namespace Comparison {
Expand Down
22 changes: 22 additions & 0 deletions clang/test/AST/Interp/vectors.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s
// RUN: %clang_cc1 -verify=ref,both %s

// both-no-diagnostics

typedef int __attribute__((vector_size(16))) VI4;
constexpr VI4 A = {1,2,3,4};

/// From constant-expression-cxx11.cpp
namespace Vector {
typedef int __attribute__((vector_size(16))) VI4;
constexpr VI4 f(int n) {
return VI4 { n * 3, n + 4, n - 5, n / 6 };
}
constexpr auto v1 = f(10);

typedef double __attribute__((vector_size(32))) VD4;
constexpr VD4 g(int n) {
return (VD4) { n / 2.0, n + 1.5, n - 5.4, n * 0.9 };
}
constexpr auto v2 = g(4);
}
18 changes: 18 additions & 0 deletions clang/test/CodeGen/X86/x86_64-arguments.c
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,24 @@ typedef float t66 __attribute__((__vector_size__(128), __aligned__(128)));
void f66(t66 a0) {
}

typedef long long t67 __attribute__((aligned (4)));
struct s67 {
int a;
t67 b;
};
// CHECK-LABEL: define{{.*}} void @f67(ptr noundef byval(%struct.s67) align 8 %x)
void f67(struct s67 x) {
}

typedef double t68 __attribute__((aligned (4)));
struct s68 {
int a;
t68 b;
};
// CHECK-LABEL: define{{.*}} void @f68(ptr noundef byval(%struct.s68) align 8 %x)
void f68(struct s68 x) {
}

/// The synthesized __va_list_tag does not have file/line fields.
// CHECK: = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "__va_list_tag",
// CHECK-NOT: file:
Expand Down
14 changes: 14 additions & 0 deletions clang/test/CodeGenCXX/arm64ec-vectorcall.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// RUN: %clang_cc1 -triple arm64ec-windows-msvc -emit-llvm -o - %s -verify

// ARM64EC doesn't support generating __vectorcall calls... but __vectorcall
// function types need to be distinct from __cdecl function types to support
// compiling the STL. Make sure we only diagnose constructs that actually
// require generating code.
void __vectorcall f1();
void f2(void __vectorcall p()) {}
void f2(void p()) {}
void __vectorcall (*f3)();
void __vectorcall f4(); // expected-error {{__vectorcall}}
void __vectorcall f5() { // expected-error {{__vectorcall}}
f4(); // expected-error{{__vectorcall}}
}
364 changes: 364 additions & 0 deletions clang/test/CodeGenCXX/control-flow-in-stmt-expr.cpp

Large diffs are not rendered by default.

93 changes: 93 additions & 0 deletions clang/test/CodeGenCoroutines/coro-suspend-cleanups.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// RUN: %clang_cc1 --std=c++20 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s

#include "Inputs/coroutine.h"

struct Printy {
Printy(const char *name) : name(name) {}
~Printy() {}
const char *name;
};

struct coroutine {
struct promise_type;
std::coroutine_handle<promise_type> handle;
~coroutine() {
if (handle) handle.destroy();
}
};

struct coroutine::promise_type {
coroutine get_return_object() {
return {std::coroutine_handle<promise_type>::from_promise(*this)};
}
std::suspend_never initial_suspend() noexcept { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
void return_void() {}
void unhandled_exception() {}
};

struct Awaiter : std::suspend_always {
Printy await_resume() { return {"awaited"}; }
};

int foo() { return 2; }

coroutine ArrayInitCoro() {
// Verify that:
// - We do the necessary stores for array cleanups.
// - Array cleanups are called by await.cleanup.
// - We activate the cleanup after the first element and deactivate it in await.ready (see cleanup.isactive).

// CHECK-LABEL: define dso_local void @_Z13ArrayInitCorov
// CHECK: %arrayinit.endOfInit = alloca ptr, align 8
// CHECK: %cleanup.isactive = alloca i1, align 1
Printy arr[2] = {
Printy("a"),
// CHECK: %arrayinit.begin = getelementptr inbounds [2 x %struct.Printy], ptr %arr.reload.addr, i64 0, i64 0
// CHECK-NEXT: %arrayinit.begin.spill.addr = getelementptr inbounds %_Z13ArrayInitCorov.Frame, ptr %0, i32 0, i32 10
// CHECK-NEXT: store ptr %arrayinit.begin, ptr %arrayinit.begin.spill.addr, align 8
// CHECK-NEXT: store i1 true, ptr %cleanup.isactive.reload.addr, align 1
// CHECK-NEXT: store ptr %arrayinit.begin, ptr %arrayinit.endOfInit.reload.addr, align 8
// CHECK-NEXT: call void @_ZN6PrintyC1EPKc(ptr noundef nonnull align 8 dereferenceable(8) %arrayinit.begin, ptr noundef @.str)
// CHECK-NEXT: %arrayinit.element = getelementptr inbounds %struct.Printy, ptr %arrayinit.begin, i64 1
// CHECK-NEXT: %arrayinit.element.spill.addr = getelementptr inbounds %_Z13ArrayInitCorov.Frame, ptr %0, i32 0, i32 11
// CHECK-NEXT: store ptr %arrayinit.element, ptr %arrayinit.element.spill.addr, align 8
// CHECK-NEXT: store ptr %arrayinit.element, ptr %arrayinit.endOfInit.reload.addr, align 8
co_await Awaiter{}
// CHECK-NEXT: @_ZNSt14suspend_always11await_readyEv
// CHECK-NEXT: br i1 %{{.+}}, label %await.ready, label %CoroSave30
};
// CHECK: await.cleanup: ; preds = %AfterCoroSuspend{{.*}}
// CHECK-NEXT: br label %cleanup{{.*}}.from.await.cleanup

// CHECK: cleanup{{.*}}.from.await.cleanup: ; preds = %await.cleanup
// CHECK: br label %cleanup{{.*}}

// CHECK: await.ready:
// CHECK-NEXT: %arrayinit.element.reload.addr = getelementptr inbounds %_Z13ArrayInitCorov.Frame, ptr %0, i32 0, i32 11
// CHECK-NEXT: %arrayinit.element.reload = load ptr, ptr %arrayinit.element.reload.addr, align 8
// CHECK-NEXT: call void @_ZN7Awaiter12await_resumeEv
// CHECK-NEXT: store i1 false, ptr %cleanup.isactive.reload.addr, align 1
// CHECK-NEXT: br label %cleanup{{.*}}.from.await.ready

// CHECK: cleanup{{.*}}: ; preds = %cleanup{{.*}}.from.await.ready, %cleanup{{.*}}.from.await.cleanup
// CHECK: %cleanup.is_active = load i1, ptr %cleanup.isactive.reload.addr, align 1
// CHECK-NEXT: br i1 %cleanup.is_active, label %cleanup.action, label %cleanup.done

// CHECK: cleanup.action:
// CHECK: %arraydestroy.isempty = icmp eq ptr %arrayinit.begin.reload{{.*}}, %{{.*}}
// CHECK-NEXT: br i1 %arraydestroy.isempty, label %arraydestroy.done{{.*}}, label %arraydestroy.body.from.cleanup.action
// Ignore rest of the array cleanup.
}

coroutine ArrayInitWithCoReturn() {
// CHECK-LABEL: define dso_local void @_Z21ArrayInitWithCoReturnv
// Verify that we start to emit the array destructor.
// CHECK: %arrayinit.endOfInit = alloca ptr, align 8
Printy arr[2] = {"a", ({
if (foo()) {
co_return;
}
"b";
})};
}
6 changes: 6 additions & 0 deletions clang/test/Driver/amdgpu-features.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,9 @@

// RUN: %clang -### -target amdgcn -mcpu=gfx1010 -mno-cumode %s 2>&1 | FileCheck --check-prefix=NO-CUMODE %s
// NO-CUMODE: "-target-feature" "-cumode"

// RUN: %clang -### -target amdgcn -mcpu=gfx1010 -mamdgpu-precise-memory-op %s 2>&1 | FileCheck --check-prefix=PREC-MEM %s
// PREC-MEM: "-target-feature" "+precise-memory"

// RUN: %clang -### -target amdgcn -mcpu=gfx1010 -mno-amdgpu-precise-memory-op %s 2>&1 | FileCheck --check-prefix=NO-PREC-MEM %s
// NO-PREC-MEM-NOT: {{".*precise-memory"}}
4 changes: 4 additions & 0 deletions clang/test/Driver/linker-wrapper-libs.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ int bar() { return weak; }
// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
// RUN: --linker-path=/usr/bin/ld %t.o %t.a -o a.out 2>&1 \
// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
// RUN: --linker-path=/usr/bin/ld %t.a %t.o -o a.out 2>&1 \
// RUN: | FileCheck %s --check-prefix=LIBRARY-RESOLVES

// LIBRARY-RESOLVES: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o
Expand All @@ -66,6 +68,8 @@ int bar() { return weak; }
// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
// RUN: --linker-path=/usr/bin/ld %t.o %t.a -o a.out 2>&1 \
// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
// RUN: --linker-path=/usr/bin/ld %t.a %t.o -o a.out 2>&1 \
// RUN: | FileCheck %s --check-prefix=LIBRARY-GLOBAL

// LIBRARY-GLOBAL: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o
Expand Down
8 changes: 4 additions & 4 deletions clang/test/Driver/lld-repro.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
// RUN: echo "-nostartfiles -nostdlib -fuse-ld=lld -gen-reproducer=error -fcrash-diagnostics-dir=%t" \
// RUN: | sed -e 's/\\/\\\\/g' > %t.rsp

// RUN: not %clang %s @%t.rsp -fcrash-diagnostics=all 2>&1 \
// RUN: not %clang %s @%t.rsp -fcrash-diagnostics=all -o /dev/null 2>&1 \
// RUN: | FileCheck %s

// Test that the reproducer can still be created even when the input source cannot be preprocessed
// again, like when reading from stdin.
// RUN: not %clang -x c - @%t.rsp -fcrash-diagnostics=all 2>&1 < %s \
// RUN: not %clang -x c - @%t.rsp -fcrash-diagnostics=all -o /dev/null 2>&1 < %s \
// RUN: | FileCheck %s

// check that we still get lld's output
Expand All @@ -20,9 +20,9 @@
// CHECK-NEXT: note: diagnostic msg:
// CHECK: ********************

// RUN: not %clang %s @%t.rsp -fcrash-diagnostics=compiler 2>&1 \
// RUN: not %clang %s @%t.rsp -fcrash-diagnostics=compiler -o /dev/null 2>&1 \
// RUN: | FileCheck %s --check-prefix=NO-LINKER
// RUN: not %clang %s @%t.rsp 2>&1 \
// RUN: not %clang %s @%t.rsp -o /dev/null 2>&1 \
// RUN: | FileCheck %s --check-prefix=NO-LINKER

// NO-LINKER-NOT: Preprocessed source(s) and associated run script(s) are located at:
Expand Down
34 changes: 34 additions & 0 deletions clang/test/Modules/home-is-cwd-search-paths.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// This test demonstrates how -fmodule-map-file-home-is-cwd with -fmodules-embed-all-files
// extend the importer search paths by relying on the side effects of pragma diagnostic
// mappings deserialization.

// RUN: rm -rf %t
// RUN: split-file %s %t

//--- dir1/a.modulemap
module a { header "a.h" }
//--- dir1/a.h
#include "search.h"
// The first compilation is configured such that -I search does contain the search.h header.
//--- dir1/search/search.h
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wparentheses"
#pragma clang diagnostic pop
// RUN: cd %t/dir1 && %clang_cc1 -fmodules -I search \
// RUN: -emit-module -fmodule-name=a a.modulemap -o %t/a.pcm \
// RUN: -fmodules-embed-all-files -fmodule-map-file-home-is-cwd

//--- dir2/b.modulemap
module b { header "b.h" }
//--- dir2/b.h
#include "search.h" // expected-error{{'search.h' file not found}}
// The second compilation is configured such that -I search is an empty directory.
// However, since b.pcm simply embeds the headers as "search/search.h", this compilation
// ends up seeing it too. This relies solely on ASTReader::ReadPragmaDiagnosticMappings()
// eagerly reading the corresponding INPUT_FILE record before header search happens.
// Removing the eager deserialization makes this header invisible and so does removing
// the pragma directives.
// RUN: mkdir %t/dir2/search
// RUN: cd %t/dir2 && %clang_cc1 -fmodules -I search \
// RUN: -emit-module -fmodule-name=b b.modulemap -o %t/b.pcm \
// RUN: -fmodule-file=%t/a.pcm -verify
48 changes: 39 additions & 9 deletions clang/test/OpenMP/nvptx_target_teams_generic_loop_codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,35 +320,44 @@ int bar(int n){
//
//
// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l33
// CHECK1-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR4:[0-9]+]] {
// CHECK1-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]], i64 noundef [[DOTCAPTURE_EXPR_:%.*]]) #[[ATTR4:[0-9]+]] {
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[B_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[DOTCAPTURE_EXPR__ADDR:%.*]] = alloca i64, align 8
// CHECK1-NEXT: [[DOTCAPTURE_EXPR__CASTED:%.*]] = alloca i64, align 8
// CHECK1-NEXT: [[DOTZERO_ADDR:%.*]] = alloca i32, align 4
// CHECK1-NEXT: [[DOTTHREADID_TEMP_:%.*]] = alloca i32, align 4
// CHECK1-NEXT: store ptr [[DYN_PTR]], ptr [[DYN_PTR_ADDR]], align 8
// CHECK1-NEXT: store ptr [[B]], ptr [[B_ADDR]], align 8
// CHECK1-NEXT: store i64 [[DOTCAPTURE_EXPR_]], ptr [[DOTCAPTURE_EXPR__ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[B_ADDR]], align 8
// CHECK1-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_target_init(ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l33_kernel_environment, ptr [[DYN_PTR]])
// CHECK1-NEXT: [[EXEC_USER_CODE:%.*]] = icmp eq i32 [[TMP1]], -1
// CHECK1-NEXT: br i1 [[EXEC_USER_CODE]], label [[USER_CODE_ENTRY:%.*]], label [[WORKER_EXIT:%.*]]
// CHECK1: user_code.entry:
// CHECK1-NEXT: [[TMP2:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1]])
// CHECK1-NEXT: [[TMP3:%.*]] = load i8, ptr [[DOTCAPTURE_EXPR__ADDR]], align 1
// CHECK1-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP3]] to i1
// CHECK1-NEXT: [[FROMBOOL:%.*]] = zext i1 [[TOBOOL]] to i8
// CHECK1-NEXT: store i8 [[FROMBOOL]], ptr [[DOTCAPTURE_EXPR__CASTED]], align 1
// CHECK1-NEXT: [[TMP4:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR__CASTED]], align 8
// CHECK1-NEXT: store i32 0, ptr [[DOTZERO_ADDR]], align 4
// CHECK1-NEXT: store i32 [[TMP2]], ptr [[DOTTHREADID_TEMP_]], align 4
// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l33_omp_outlined(ptr [[DOTTHREADID_TEMP_]], ptr [[DOTZERO_ADDR]], ptr [[TMP0]]) #[[ATTR2]]
// CHECK1-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l33_omp_outlined(ptr [[DOTTHREADID_TEMP_]], ptr [[DOTZERO_ADDR]], ptr [[TMP0]], i64 [[TMP4]]) #[[ATTR2]]
// CHECK1-NEXT: call void @__kmpc_target_deinit()
// CHECK1-NEXT: ret void
// CHECK1: worker.exit:
// CHECK1-NEXT: ret void
//
//
// CHECK1-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l33_omp_outlined
// CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR1]] {
// CHECK1-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]], i64 noundef [[DOTCAPTURE_EXPR_:%.*]]) #[[ATTR1]] {
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[B_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[DOTCAPTURE_EXPR__ADDR:%.*]] = alloca i64, align 8
// CHECK1-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4
// CHECK1-NEXT: [[TMP:%.*]] = alloca i32, align 4
// CHECK1-NEXT: [[DOTOMP_COMB_LB:%.*]] = alloca i32, align 4
Expand All @@ -360,6 +369,7 @@ int bar(int n){
// CHECK1-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8
// CHECK1-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8
// CHECK1-NEXT: store ptr [[B]], ptr [[B_ADDR]], align 8
// CHECK1-NEXT: store i64 [[DOTCAPTURE_EXPR_]], ptr [[DOTCAPTURE_EXPR__ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[B_ADDR]], align 8
// CHECK1-NEXT: store i32 0, ptr [[DOTOMP_COMB_LB]], align 4
// CHECK1-NEXT: store i32 9, ptr [[DOTOMP_COMB_UB]], align 4
Expand Down Expand Up @@ -1566,35 +1576,44 @@ int bar(int n){
//
//
// CHECK2-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l33
// CHECK2-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR4:[0-9]+]] {
// CHECK2-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]], i64 noundef [[DOTCAPTURE_EXPR_:%.*]]) #[[ATTR4:[0-9]+]] {
// CHECK2-NEXT: entry:
// CHECK2-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 8
// CHECK2-NEXT: [[B_ADDR:%.*]] = alloca ptr, align 8
// CHECK2-NEXT: [[DOTCAPTURE_EXPR__ADDR:%.*]] = alloca i64, align 8
// CHECK2-NEXT: [[DOTCAPTURE_EXPR__CASTED:%.*]] = alloca i64, align 8
// CHECK2-NEXT: [[DOTZERO_ADDR:%.*]] = alloca i32, align 4
// CHECK2-NEXT: [[DOTTHREADID_TEMP_:%.*]] = alloca i32, align 4
// CHECK2-NEXT: store ptr [[DYN_PTR]], ptr [[DYN_PTR_ADDR]], align 8
// CHECK2-NEXT: store ptr [[B]], ptr [[B_ADDR]], align 8
// CHECK2-NEXT: store i64 [[DOTCAPTURE_EXPR_]], ptr [[DOTCAPTURE_EXPR__ADDR]], align 8
// CHECK2-NEXT: [[TMP0:%.*]] = load ptr, ptr [[B_ADDR]], align 8
// CHECK2-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_target_init(ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l33_kernel_environment, ptr [[DYN_PTR]])
// CHECK2-NEXT: [[EXEC_USER_CODE:%.*]] = icmp eq i32 [[TMP1]], -1
// CHECK2-NEXT: br i1 [[EXEC_USER_CODE]], label [[USER_CODE_ENTRY:%.*]], label [[WORKER_EXIT:%.*]]
// CHECK2: user_code.entry:
// CHECK2-NEXT: [[TMP2:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1]])
// CHECK2-NEXT: [[TMP3:%.*]] = load i8, ptr [[DOTCAPTURE_EXPR__ADDR]], align 1
// CHECK2-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP3]] to i1
// CHECK2-NEXT: [[FROMBOOL:%.*]] = zext i1 [[TOBOOL]] to i8
// CHECK2-NEXT: store i8 [[FROMBOOL]], ptr [[DOTCAPTURE_EXPR__CASTED]], align 1
// CHECK2-NEXT: [[TMP4:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR__CASTED]], align 8
// CHECK2-NEXT: store i32 0, ptr [[DOTZERO_ADDR]], align 4
// CHECK2-NEXT: store i32 [[TMP2]], ptr [[DOTTHREADID_TEMP_]], align 4
// CHECK2-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l33_omp_outlined(ptr [[DOTTHREADID_TEMP_]], ptr [[DOTZERO_ADDR]], ptr [[TMP0]]) #[[ATTR2]]
// CHECK2-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l33_omp_outlined(ptr [[DOTTHREADID_TEMP_]], ptr [[DOTZERO_ADDR]], ptr [[TMP0]], i64 [[TMP4]]) #[[ATTR2]]
// CHECK2-NEXT: call void @__kmpc_target_deinit()
// CHECK2-NEXT: ret void
// CHECK2: worker.exit:
// CHECK2-NEXT: ret void
//
//
// CHECK2-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l33_omp_outlined
// CHECK2-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR1]] {
// CHECK2-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]], i64 noundef [[DOTCAPTURE_EXPR_:%.*]]) #[[ATTR1]] {
// CHECK2-NEXT: entry:
// CHECK2-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8
// CHECK2-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8
// CHECK2-NEXT: [[B_ADDR:%.*]] = alloca ptr, align 8
// CHECK2-NEXT: [[DOTCAPTURE_EXPR__ADDR:%.*]] = alloca i64, align 8
// CHECK2-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4
// CHECK2-NEXT: [[TMP:%.*]] = alloca i32, align 4
// CHECK2-NEXT: [[DOTOMP_COMB_LB:%.*]] = alloca i32, align 4
Expand All @@ -1606,6 +1625,7 @@ int bar(int n){
// CHECK2-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8
// CHECK2-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8
// CHECK2-NEXT: store ptr [[B]], ptr [[B_ADDR]], align 8
// CHECK2-NEXT: store i64 [[DOTCAPTURE_EXPR_]], ptr [[DOTCAPTURE_EXPR__ADDR]], align 8
// CHECK2-NEXT: [[TMP0:%.*]] = load ptr, ptr [[B_ADDR]], align 8
// CHECK2-NEXT: store i32 0, ptr [[DOTOMP_COMB_LB]], align 4
// CHECK2-NEXT: store i32 9, ptr [[DOTOMP_COMB_UB]], align 4
Expand Down Expand Up @@ -2801,35 +2821,44 @@ int bar(int n){
//
//
// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l33
// CHECK3-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR4:[0-9]+]] {
// CHECK3-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]], i32 noundef [[DOTCAPTURE_EXPR_:%.*]]) #[[ATTR4:[0-9]+]] {
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[DYN_PTR_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[B_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[DOTCAPTURE_EXPR__ADDR:%.*]] = alloca i32, align 4
// CHECK3-NEXT: [[DOTCAPTURE_EXPR__CASTED:%.*]] = alloca i32, align 4
// CHECK3-NEXT: [[DOTZERO_ADDR:%.*]] = alloca i32, align 4
// CHECK3-NEXT: [[DOTTHREADID_TEMP_:%.*]] = alloca i32, align 4
// CHECK3-NEXT: store ptr [[DYN_PTR]], ptr [[DYN_PTR_ADDR]], align 4
// CHECK3-NEXT: store ptr [[B]], ptr [[B_ADDR]], align 4
// CHECK3-NEXT: store i32 [[DOTCAPTURE_EXPR_]], ptr [[DOTCAPTURE_EXPR__ADDR]], align 4
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[B_ADDR]], align 4
// CHECK3-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_target_init(ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l33_kernel_environment, ptr [[DYN_PTR]])
// CHECK3-NEXT: [[EXEC_USER_CODE:%.*]] = icmp eq i32 [[TMP1]], -1
// CHECK3-NEXT: br i1 [[EXEC_USER_CODE]], label [[USER_CODE_ENTRY:%.*]], label [[WORKER_EXIT:%.*]]
// CHECK3: user_code.entry:
// CHECK3-NEXT: [[TMP2:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1]])
// CHECK3-NEXT: [[TMP3:%.*]] = load i8, ptr [[DOTCAPTURE_EXPR__ADDR]], align 1
// CHECK3-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP3]] to i1
// CHECK3-NEXT: [[FROMBOOL:%.*]] = zext i1 [[TOBOOL]] to i8
// CHECK3-NEXT: store i8 [[FROMBOOL]], ptr [[DOTCAPTURE_EXPR__CASTED]], align 1
// CHECK3-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR__CASTED]], align 4
// CHECK3-NEXT: store i32 0, ptr [[DOTZERO_ADDR]], align 4
// CHECK3-NEXT: store i32 [[TMP2]], ptr [[DOTTHREADID_TEMP_]], align 4
// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l33_omp_outlined(ptr [[DOTTHREADID_TEMP_]], ptr [[DOTZERO_ADDR]], ptr [[TMP0]]) #[[ATTR2]]
// CHECK3-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l33_omp_outlined(ptr [[DOTTHREADID_TEMP_]], ptr [[DOTZERO_ADDR]], ptr [[TMP0]], i32 [[TMP4]]) #[[ATTR2]]
// CHECK3-NEXT: call void @__kmpc_target_deinit()
// CHECK3-NEXT: ret void
// CHECK3: worker.exit:
// CHECK3-NEXT: ret void
//
//
// CHECK3-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z9ftemplateIiET_i_l33_omp_outlined
// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]]) #[[ATTR1]] {
// CHECK3-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]], ptr noundef nonnull align 4 dereferenceable(40) [[B:%.*]], i32 noundef [[DOTCAPTURE_EXPR_:%.*]]) #[[ATTR1]] {
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[B_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[DOTCAPTURE_EXPR__ADDR:%.*]] = alloca i32, align 4
// CHECK3-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4
// CHECK3-NEXT: [[TMP:%.*]] = alloca i32, align 4
// CHECK3-NEXT: [[DOTOMP_COMB_LB:%.*]] = alloca i32, align 4
Expand All @@ -2841,6 +2870,7 @@ int bar(int n){
// CHECK3-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 4
// CHECK3-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 4
// CHECK3-NEXT: store ptr [[B]], ptr [[B_ADDR]], align 4
// CHECK3-NEXT: store i32 [[DOTCAPTURE_EXPR_]], ptr [[DOTCAPTURE_EXPR__ADDR]], align 4
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[B_ADDR]], align 4
// CHECK3-NEXT: store i32 0, ptr [[DOTOMP_COMB_LB]], align 4
// CHECK3-NEXT: store i32 9, ptr [[DOTOMP_COMB_UB]], align 4
Expand Down

Large diffs are not rendered by default.

1,132 changes: 8 additions & 1,124 deletions clang/test/OpenMP/target_teams_generic_loop_codegen.cpp

Large diffs are not rendered by default.

587 changes: 587 additions & 0 deletions clang/test/OpenMP/target_teams_generic_loop_codegen_as_distribute.cpp

Large diffs are not rendered by default.

3,998 changes: 3,998 additions & 0 deletions clang/test/OpenMP/target_teams_generic_loop_codegen_as_parallel_for.cpp

Large diffs are not rendered by default.

710 changes: 114 additions & 596 deletions clang/test/OpenMP/target_teams_generic_loop_if_codegen.cpp

Large diffs are not rendered by default.

1,438 changes: 240 additions & 1,198 deletions clang/test/OpenMP/target_teams_generic_loop_private_codegen.cpp

Large diffs are not rendered by default.

1,360 changes: 148 additions & 1,212 deletions clang/test/OpenMP/teams_generic_loop_codegen-1.cpp

Large diffs are not rendered by default.

630 changes: 138 additions & 492 deletions clang/test/OpenMP/teams_generic_loop_codegen.cpp

Large diffs are not rendered by default.

808 changes: 136 additions & 672 deletions clang/test/OpenMP/teams_generic_loop_collapse_codegen.cpp

Large diffs are not rendered by default.

685 changes: 103 additions & 582 deletions clang/test/OpenMP/teams_generic_loop_private_codegen.cpp

Large diffs are not rendered by default.

785 changes: 109 additions & 676 deletions clang/test/OpenMP/teams_generic_loop_reduction_codegen.cpp

Large diffs are not rendered by default.

20 changes: 6 additions & 14 deletions clang/test/ParserOpenACC/parse-clauses.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,45 +173,37 @@ void DefaultClause() {
#pragma acc serial default), seq
for(;;){}

// expected-error@+2{{expected identifier}}
// expected-warning@+1{{OpenACC clause 'default' not yet implemented, clause ignored}}
// expected-error@+1{{expected identifier}}
#pragma acc serial default()
for(;;){}

// expected-error@+3{{expected identifier}}
// expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
// expected-error@+2{{expected identifier}}
// expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
#pragma acc serial default() seq
for(;;){}

// expected-error@+3{{expected identifier}}
// expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
// expected-error@+2{{expected identifier}}
// expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
#pragma acc serial default(), seq
for(;;){}

// expected-error@+2{{invalid value for 'default' clause; expected 'present' or 'none'}}
// expected-warning@+1{{OpenACC clause 'default' not yet implemented, clause ignored}}
// expected-error@+1{{invalid value for 'default' clause; expected 'present' or 'none'}}
#pragma acc serial default(invalid)
for(;;){}

// expected-error@+3{{invalid value for 'default' clause; expected 'present' or 'none'}}
// expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
// expected-error@+2{{invalid value for 'default' clause; expected 'present' or 'none'}}
// expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
#pragma acc serial default(auto) seq
for(;;){}

// expected-error@+3{{invalid value for 'default' clause; expected 'present' or 'none'}}
// expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
// expected-error@+2{{invalid value for 'default' clause; expected 'present' or 'none'}}
// expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
#pragma acc serial default(invalid), seq
for(;;){}

// expected-warning@+1{{OpenACC clause 'default' not yet implemented, clause ignored}}
#pragma acc serial default(none)
for(;;){}

// expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
// expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
#pragma acc serial default(present), seq
for(;;){}
Expand Down
6 changes: 5 additions & 1 deletion clang/test/Sema/aarch64-incompat-sm-builtin-calls.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve \
// RUN: -target-feature +sme2 -target-feature +sve2 -target-feature +neon -fsyntax-only -verify %s
// RUN: -target-feature +sme2 -target-feature +sve2 -target-feature +neon -Waarch64-sme-attributes -fsyntax-only -verify %s

// REQUIRES: aarch64-registered-target

Expand Down Expand Up @@ -33,6 +33,7 @@ svuint32_t incompat_sve_sm(svbool_t pg, svuint32_t a, int16_t b) __arm_streaming
return __builtin_sve_svld1_gather_u32base_index_u32(pg, a, b);
}

// expected-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}}
__arm_locally_streaming svuint32_t incompat_sve_ls(svbool_t pg, svuint32_t a, int64_t b) {
// expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}}
return __builtin_sve_svld1_gather_u32base_index_u32(pg, a, b);
Expand All @@ -48,6 +49,7 @@ svuint32_t incompat_sve2_sm(svbool_t pg, svuint32_t a, int64_t b) __arm_streamin
return __builtin_sve_svldnt1_gather_u32base_index_u32(pg, a, b);
}

// expected-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}}
__arm_locally_streaming svuint32_t incompat_sve2_ls(svbool_t pg, svuint32_t a, int64_t b) {
// expected-warning@+1 {{builtin call has undefined behaviour when called from a streaming function}}
return __builtin_sve_svldnt1_gather_u32base_index_u32(pg, a, b);
Expand All @@ -68,6 +70,7 @@ svfloat64_t streaming_caller_sve(svbool_t pg, svfloat64_t a, float64_t b) __arm_
return svadd_n_f64_m(pg, a, b);
}

// expected-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}}
__arm_locally_streaming svfloat64_t locally_streaming_caller_sve(svbool_t pg, svfloat64_t a, float64_t b) {
// expected-no-warning
return svadd_n_f64_m(pg, a, b);
Expand All @@ -83,6 +86,7 @@ svint16_t streaming_caller_sve2(svint16_t op1, svint16_t op2) __arm_streaming {
return svmul_lane_s16(op1, op2, 0);
}

// expected-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}}
__arm_locally_streaming svint16_t locally_streaming_caller_sve2(svint16_t op1, svint16_t op2) {
// expected-no-warning
return svmul_lane_s16(op1, op2, 0);
Expand Down
136 changes: 134 additions & 2 deletions clang/test/Sema/aarch64-sme-func-attrs.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -fsyntax-only -verify %s
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -fsyntax-only -verify=expected-cpp -x c++ %s
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -target-feature +sve -Waarch64-sme-attributes -fsyntax-only -verify %s
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme2 -target-feature +sve -Waarch64-sme-attributes -fsyntax-only -verify=expected-cpp -x c++ %s

// Valid attributes

Expand Down Expand Up @@ -496,3 +496,135 @@ void fmv_caller() {
just_fine();
incompatible_locally_streaming();
}

void sme_streaming_with_vl_arg(__SVInt8_t a) __arm_streaming { }

__SVInt8_t sme_streaming_returns_vl(void) __arm_streaming { __SVInt8_t r; return r; }

void sme_streaming_compatible_with_vl_arg(__SVInt8_t a) __arm_streaming_compatible { }

__SVInt8_t sme_streaming_compatible_returns_vl(void) __arm_streaming_compatible { __SVInt8_t r; return r; }

void sme_no_streaming_with_vl_arg(__SVInt8_t a) { }

__SVInt8_t sme_no_streaming_returns_vl(void) { __SVInt8_t r; return r; }

// expected-warning@+2 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}}
__arm_locally_streaming void sme_locally_streaming_with_vl_arg(__SVInt8_t a) { }

// expected-warning@+2 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing/returning a VL-dependent argument to/from a __arm_locally_streaming function. The streaming and non-streaming vector lengths may be different}}
__arm_locally_streaming __SVInt8_t sme_locally_streaming_returns_vl(void) { __SVInt8_t r; return r; }

void sme_no_streaming_calling_streaming_with_vl_args() {
__SVInt8_t a;
// expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
sme_streaming_with_vl_arg(a);
}

void sme_no_streaming_calling_streaming_with_return_vl() {
// expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
__SVInt8_t r = sme_streaming_returns_vl();
}

void sme_streaming_calling_non_streaming_with_vl_args(void) __arm_streaming {
__SVInt8_t a;
// expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
sme_no_streaming_with_vl_arg(a);
}

void sme_streaming_calling_non_streaming_with_return_vl(void) __arm_streaming {
// expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
__SVInt8_t r = sme_no_streaming_returns_vl();
}

void sme_no_streaming_calling_streaming_with_vl_args_param(__SVInt8_t arg, void (*sc)( __SVInt8_t arg) __arm_streaming) {
// expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
sc(arg);
}

__SVInt8_t sme_no_streaming_calling_streaming_return_vl_param(__SVInt8_t (*s)(void) __arm_streaming) {
// expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
return s();
}

void sme_streaming_compatible_calling_streaming_with_vl_args(__SVInt8_t arg) __arm_streaming_compatible {
// expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
sme_streaming_with_vl_arg(arg);
}

void sme_streaming_compatible_calling_sme_streaming_return_vl(void) __arm_streaming_compatible {
// expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
__SVInt8_t r = sme_streaming_returns_vl();
}

void sme_streaming_compatible_calling_no_streaming_with_vl_args(__SVInt8_t arg) __arm_streaming_compatible {
// expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
sme_no_streaming_with_vl_arg(arg);
}

void sme_streaming_compatible_calling_no_sme_streaming_return_vl(void) __arm_streaming_compatible {
// expected-warning@+2 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
// expected-cpp-warning@+1 {{passing a VL-dependent argument to/from a function that has a different streaming-mode. The streaming and non-streaming vector lengths may be different}}
__SVInt8_t r = sme_no_streaming_returns_vl();
}

void sme_streaming_calling_streaming(__SVInt8_t arg, void (*s)( __SVInt8_t arg) __arm_streaming) __arm_streaming {
s(arg);
}

__SVInt8_t sme_streaming_calling_streaming_return_vl(__SVInt8_t (*s)(void) __arm_streaming) __arm_streaming {
return s();
}

void sme_streaming_calling_streaming_with_vl_args(__SVInt8_t a) __arm_streaming {
sme_streaming_with_vl_arg(a);
}

void sme_streaming_calling_streaming_with_return_vl(void) __arm_streaming {
__SVInt8_t r = sme_streaming_returns_vl();
}

void sme_streaming_calling_streaming_compatible_with_vl_args(__SVInt8_t a) __arm_streaming {
sme_streaming_compatible_with_vl_arg(a);
}

void sme_streaming_calling_streaming_compatible_with_return_vl(void) __arm_streaming {
__SVInt8_t r = sme_streaming_compatible_returns_vl();
}

void sme_no_streaming_calling_streaming_compatible_with_vl_args() {
__SVInt8_t a;
sme_streaming_compatible_with_vl_arg(a);
}

void sme_no_streaming_calling_streaming_compatible_with_return_vl() {
__SVInt8_t r = sme_streaming_compatible_returns_vl();
}

void sme_no_streaming_calling_non_streaming_compatible_with_vl_args() {
__SVInt8_t a;
sme_no_streaming_with_vl_arg(a);
}

void sme_no_streaming_calling_non_streaming_compatible_with_return_vl() {
__SVInt8_t r = sme_no_streaming_returns_vl();
}

void sme_streaming_compatible_calling_streaming_compatible_with_vl_args(__SVInt8_t arg) __arm_streaming_compatible {
sme_streaming_compatible_with_vl_arg(arg);
}

void sme_streaming_compatible_calling_streaming_compatible_with_return_vl(void) __arm_streaming_compatible {
__SVInt8_t r = sme_streaming_compatible_returns_vl();
}
1 change: 1 addition & 0 deletions clang/test/SemaCXX/type-traits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1759,6 +1759,7 @@ void is_layout_compatible(int n)
// expected-error@-1 {{variable length arrays are not supported in '__is_layout_compatible'}}
static_assert(!__is_layout_compatible(int[n], int[n]));
// expected-error@-1 {{variable length arrays are not supported in '__is_layout_compatible'}}
// expected-error@-2 {{variable length arrays are not supported in '__is_layout_compatible'}}
static_assert(__is_layout_compatible(int&, int&));
static_assert(!__is_layout_compatible(int&, char&));
static_assert(__is_layout_compatible(void(int), void(int)));
Expand Down
14 changes: 10 additions & 4 deletions clang/test/SemaOpenACC/compute-construct-ast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ void NormalFunc() {
// CHECK-LABEL: NormalFunc
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: OpenACCComputeConstruct {{.*}}parallel
// CHECK-NEXT: default(none)
// CHECK-NEXT: CompoundStmt
#pragma acc parallel
#pragma acc parallel default(none)
{
#pragma acc parallel
// CHECK-NEXT: OpenACCComputeConstruct {{.*}}parallel
// CHECK-NEXT: OpenACCComputeConstruct {{.*}}parallel
// CHECK-NEXT: default(present)
// CHECK-NEXT: CompoundStmt
#pragma acc parallel
#pragma acc parallel default(present)
{}
}
// FIXME: Add a test once we have clauses for this.
Expand Down Expand Up @@ -50,12 +52,12 @@ void NormalFunc() {

template<typename T>
void TemplFunc() {
#pragma acc parallel
#pragma acc parallel default(none)
{
typename T::type I;
}

#pragma acc serial
#pragma acc serial default(present)
{
typename T::type I;
}
Expand All @@ -72,10 +74,12 @@ void TemplFunc() {
// CHECK-NEXT: FunctionDecl
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: OpenACCComputeConstruct {{.*}}parallel
// CHECK-NEXT: default(none)
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: DeclStmt
// CHECK-NEXT: VarDecl{{.*}} I 'typename T::type'
// CHECK-NEXT: OpenACCComputeConstruct {{.*}}serial
// CHECK-NEXT: default(present)
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: DeclStmt
// CHECK-NEXT: VarDecl{{.*}} I 'typename T::type'
Expand All @@ -91,10 +95,12 @@ void TemplFunc() {
// CHECK-NEXT: CXXRecord
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: OpenACCComputeConstruct {{.*}}parallel
// CHECK-NEXT: default(none)
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: DeclStmt
// CHECK-NEXT: VarDecl{{.*}} I 'typename S::type':'int'
// CHECK-NEXT: OpenACCComputeConstruct {{.*}}serial
// CHECK-NEXT: default(present)
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: DeclStmt
// CHECK-NEXT: VarDecl{{.*}} I 'typename S::type':'int'
Expand Down
74 changes: 74 additions & 0 deletions clang/test/SemaOpenACC/compute-construct-clause-ast.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s

// Test this with PCH.
// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s
// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s

#ifndef PCH_HELPER
#define PCH_HELPER
void NormalFunc() {
// CHECK: FunctionDecl{{.*}}NormalFunc
// CHECK-NEXT: CompoundStmt
#pragma acc parallel default(none)
while(true);
// CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel
// CHECK-NEXT: default(none)
// CHECK-NEXT: WhileStmt
// CHECK-NEXT: CXXBoolLiteralExpr
// CHECK-NEXT: NullStmt

#pragma acc serial default(present)
while(true);
// CHECK-NEXT: OpenACCComputeConstruct{{.*}}serial
// CHECK-NEXT: default(present)
// CHECK-NEXT: WhileStmt
// CHECK-NEXT: CXXBoolLiteralExpr
// CHECK-NEXT: NullStmt
}

template<typename T>
void TemplFunc() {
// CHECK: FunctionTemplateDecl{{.*}}TemplFunc
// CHECK-NEXT: TemplateTypeParmDecl

// Match the prototype:
// CHECK-NEXT: FunctionDecl{{.*}}TemplFunc
// CHECK-NEXT: CompoundStmt

#pragma acc kernels default(none)
while(true);
// CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels
// CHECK-NEXT: default(none)
// CHECK-NEXT: WhileStmt
// CHECK-NEXT: CXXBoolLiteralExpr
// CHECK-NEXT: NullStmt

#pragma acc parallel default(present)
while(true);
// CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel
// CHECK-NEXT: default(present)
// CHECK-NEXT: WhileStmt
// CHECK-NEXT: CXXBoolLiteralExpr
// CHECK-NEXT: NullStmt

// Match the instantiation:
// CHECK: FunctionDecl{{.*}}TemplFunc{{.*}}implicit_instantiation
// CHECK-NEXT: TemplateArgument type 'int'
// CHECK-NEXT: BuiltinType
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels
// CHECK-NEXT: default(none)
// CHECK-NEXT: WhileStmt
// CHECK-NEXT: CXXBoolLiteralExpr
// CHECK-NEXT: NullStmt
// CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel
// CHECK-NEXT: default(present)
// CHECK-NEXT: WhileStmt
// CHECK-NEXT: CXXBoolLiteralExpr
// CHECK-NEXT: NullStmt
}

void Instantiate() {
TemplFunc<int>();
}
#endif
55 changes: 55 additions & 0 deletions clang/test/SemaOpenACC/compute-construct-default-clause.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// RUN: %clang_cc1 %s -fopenacc -verify

void SingleOnly() {
#pragma acc parallel default(none)
while(0);

// expected-warning@+3{{OpenACC clause 'seq' not yet implemented}}
// expected-error@+2{{OpenACC 'default' clause cannot appear more than once on a 'serial' directive}}
// expected-note@+1{{previous clause is here}}
#pragma acc serial default(present) seq default(none)
while(0);

// expected-warning@+5{{OpenACC clause 'seq' not yet implemented}}
// expected-warning@+4{{OpenACC clause 'seq' not yet implemented}}
// expected-warning@+3{{OpenACC clause 'seq' not yet implemented}}
// expected-error@+2{{OpenACC 'default' clause cannot appear more than once on a 'kernels' directive}}
// expected-note@+1{{previous clause is here}}
#pragma acc kernels seq default(present) seq default(none) seq
while(0);

// expected-warning@+6{{OpenACC construct 'parallel loop' not yet implemented}}
// expected-warning@+5{{OpenACC clause 'seq' not yet implemented}}
// expected-warning@+4{{OpenACC clause 'seq' not yet implemented}}
// expected-warning@+3{{OpenACC clause 'seq' not yet implemented}}
// expected-warning@+2{{OpenACC clause 'default' not yet implemented}}
// expected-warning@+1{{OpenACC clause 'default' not yet implemented}}
#pragma acc parallel loop seq default(present) seq default(none) seq
while(0);

// expected-warning@+3{{OpenACC construct 'serial loop' not yet implemented}}
// expected-warning@+2{{OpenACC clause 'seq' not yet implemented}}
// expected-error@+1{{expected '('}}
#pragma acc serial loop seq default seq default(none) seq
while(0);

// expected-warning@+2{{OpenACC construct 'kernels loop' not yet implemented}}
// expected-warning@+1{{OpenACC clause 'default' not yet implemented}}
#pragma acc kernels loop default(none)
while(0);

// expected-warning@+2{{OpenACC construct 'data' not yet implemented}}
// expected-warning@+1{{OpenACC clause 'default' not yet implemented}}
#pragma acc data default(none)
while(0);

// expected-warning@+2{{OpenACC construct 'loop' not yet implemented}}
// expected-error@+1{{OpenACC 'default' clause is not valid on 'loop' directive}}
#pragma acc loop default(none)
while(0);

// expected-warning@+2{{OpenACC construct 'wait' not yet implemented}}
// expected-error@+1{{OpenACC 'default' clause is not valid on 'wait' directive}}
#pragma acc wait default(none)
while(0);
}
39 changes: 39 additions & 0 deletions clang/test/SemaOpenACC/compute-construct-default-clause.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// RUN: %clang_cc1 %s -fopenacc -verify

template<typename T>
void SingleOnly() {
#pragma acc parallel default(none)
while(false);

// expected-warning@+3{{OpenACC clause 'seq' not yet implemented}}
// expected-error@+2{{OpenACC 'default' clause cannot appear more than once on a 'parallel' directive}}
// expected-note@+1{{previous clause is here}}
#pragma acc parallel default(present) seq default(none)
while(false);

// expected-warning@+5{{OpenACC clause 'seq' not yet implemented}}
// expected-warning@+4{{OpenACC clause 'seq' not yet implemented}}
// expected-warning@+3{{OpenACC clause 'seq' not yet implemented}}
// expected-error@+2{{OpenACC 'default' clause cannot appear more than once on a 'serial' directive}}
// expected-note@+1{{previous clause is here}}
#pragma acc serial seq default(present) seq default(none) seq
while(false);

// expected-warning@+5{{OpenACC clause 'seq' not yet implemented}}
// expected-warning@+4{{OpenACC clause 'seq' not yet implemented}}
// expected-warning@+3{{OpenACC clause 'seq' not yet implemented}}
// expected-error@+2{{OpenACC 'default' clause cannot appear more than once on a 'kernels' directive}}
// expected-note@+1{{previous clause is here}}
#pragma acc kernels seq default(present) seq default(none) seq
while(false);

// expected-warning@+3{{OpenACC clause 'seq' not yet implemented}}
// expected-warning@+2{{OpenACC clause 'seq' not yet implemented}}
// expected-error@+1{{expected '('}}
#pragma acc parallel seq default(none) seq default seq
while(false);
}

void Instantiate() {
SingleOnly<int>();
}
23 changes: 23 additions & 0 deletions clang/test/SemaTemplate/alias-templates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,29 @@ namespace PR14858 {
void test_q(int (&a)[5]) { Q<B, B, B>().f<B, B>(&a); }
}

namespace PR84220 {

template <class...> class list {};

template <int> struct foo_impl {
template <class> using f = int;
};

template <class... xs>
using foo = typename foo_impl<sizeof...(xs)>::template f<xs...>;

// We call getFullyPackExpandedSize at the annotation stage
// before parsing the ellipsis next to the foo<xs>. This happens before
// a PackExpansionType is formed for foo<xs>.
// getFullyPackExpandedSize shouldn't determine the value here. Otherwise,
// foo_impl<sizeof...(xs)> would lose its dependency despite the template
// arguments being unsubstituted.
template <class... xs> using test = list<foo<xs>...>;

test<int> a;

}

namespace redecl {
template<typename> using A = int;
template<typename = void> using A = int;
Expand Down
44 changes: 3 additions & 41 deletions clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// RUN: %clang_cc1 -fms-extensions -fsyntax-only -Wno-unused-value -verify %s
// RUN: %clang_cc1 -fms-extensions -fdelayed-template-parsing -fsyntax-only -Wno-unused-value -verify %s
// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s
// RUN: %clang_cc1 -fms-extensions -fdelayed-template-parsing -fsyntax-only -verify %s

// expected-no-diagnostics
class A {
public:
template<class U> A(U p) {}
Expand Down Expand Up @@ -75,42 +76,3 @@ struct S {
int f<0>(int);
};
}

namespace UsesThis {
template<typename T>
struct A {
int x;

template<typename U>
static void f();

template<>
void f<int>() {
this->x; // expected-error {{invalid use of 'this' outside of a non-static member function}}
x; // expected-error {{invalid use of member 'x' in static member function}}
A::x; // expected-error {{invalid use of member 'x' in static member function}}
+x; // expected-error {{invalid use of member 'x' in static member function}}
+A::x; // expected-error {{invalid use of member 'x' in static member function}}
}

template<typename U>
void g();

template<>
void g<int>() {
this->x;
x;
A::x;
+x;
+A::x;
}

template<typename U>
static auto h() -> A*;

template<>
auto h<int>() -> decltype(this); // expected-error {{'this' cannot be used in a static member function declaration}}
};

template struct A<int>; // expected-note 2{{in instantiation of}}
}
Loading