17 changes: 7 additions & 10 deletions clang/lib/Sema/SemaExprMember.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -789,9 +789,6 @@ ExprResult Sema::BuildMemberReferenceExpr(
ActOnMemberAccessExtraArgs *ExtraArgs) {
LookupResult R(*this, NameInfo, LookupMemberName);

if (SS.isInvalid())
return ExprError();

// Implicit member accesses.
if (!Base) {
TypoExpr *TE = nullptr;
Expand Down Expand Up @@ -826,6 +823,11 @@ ExprResult Sema::BuildMemberReferenceExpr(
BaseType = Base->getType();
}

// BuildMemberReferenceExpr expects the nested-name-specifier, if any, to be
// valid.
if (SS.isInvalid())
return ExprError();

return BuildMemberReferenceExpr(Base, BaseType,
OpLoc, IsArrow, SS, TemplateKWLoc,
FirstQualifierInScope, R, TemplateArgs, S,
Expand Down Expand Up @@ -1745,14 +1747,9 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,

ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
CXXScopeSpec &SS,
tok::TokenKind OpKind, CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
UnqualifiedId &Id,
Decl *ObjCImpDecl) {
if (SS.isSet() && SS.isInvalid())
return ExprError();

UnqualifiedId &Id, Decl *ObjCImpDecl) {
// Warn about the explicit constructor calls Microsoft extension.
if (getLangOpts().MicrosoftExt &&
Id.getKind() == UnqualifiedIdKind::IK_ConstructorName)
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5576,6 +5576,10 @@ static void TryOrBuildParenListInitialization(
ExprResult ER;
ER = IS.Perform(S, SubEntity, SubKind,
Arg ? MultiExprArg(Arg) : std::nullopt);

if (ER.isInvalid())
return false;

if (InitExpr)
*InitExpr = ER.get();
else
Expand Down
998 changes: 83 additions & 915 deletions clang/lib/Sema/SemaOpenMP.cpp

Large diffs are not rendered by default.

172 changes: 156 additions & 16 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2178,23 +2178,110 @@ namespace {
class ExtractTypeForDeductionGuide
: public TreeTransform<ExtractTypeForDeductionGuide> {
llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs;
ClassTemplateDecl *NestedPattern;
const MultiLevelTemplateArgumentList *OuterInstantiationArgs;
std::optional<TemplateDeclInstantiator> TypedefNameInstantiator;

public:
typedef TreeTransform<ExtractTypeForDeductionGuide> Base;
ExtractTypeForDeductionGuide(
Sema &SemaRef,
llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs)
: Base(SemaRef), MaterializedTypedefs(MaterializedTypedefs) {}
llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs,
ClassTemplateDecl *NestedPattern,
const MultiLevelTemplateArgumentList *OuterInstantiationArgs)
: Base(SemaRef), MaterializedTypedefs(MaterializedTypedefs),
NestedPattern(NestedPattern),
OuterInstantiationArgs(OuterInstantiationArgs) {
if (OuterInstantiationArgs)
TypedefNameInstantiator.emplace(
SemaRef, SemaRef.getASTContext().getTranslationUnitDecl(),
*OuterInstantiationArgs);
}

TypeSourceInfo *transform(TypeSourceInfo *TSI) { return TransformType(TSI); }

/// Returns true if it's safe to substitute \p Typedef with
/// \p OuterInstantiationArgs.
bool mightReferToOuterTemplateParameters(TypedefNameDecl *Typedef) {
if (!NestedPattern)
return false;

static auto WalkUp = [](DeclContext *DC, DeclContext *TargetDC) {
if (DC->Equals(TargetDC))
return true;
while (DC->isRecord()) {
if (DC->Equals(TargetDC))
return true;
DC = DC->getParent();
}
return false;
};

if (WalkUp(Typedef->getDeclContext(), NestedPattern->getTemplatedDecl()))
return true;
if (WalkUp(NestedPattern->getTemplatedDecl(), Typedef->getDeclContext()))
return true;
return false;
}

QualType
RebuildTemplateSpecializationType(TemplateName Template,
SourceLocation TemplateNameLoc,
TemplateArgumentListInfo &TemplateArgs) {
if (!OuterInstantiationArgs ||
!isa_and_present<TypeAliasTemplateDecl>(Template.getAsTemplateDecl()))
return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc,
TemplateArgs);

auto *TATD = cast<TypeAliasTemplateDecl>(Template.getAsTemplateDecl());
auto *Pattern = TATD;
while (Pattern->getInstantiatedFromMemberTemplate())
Pattern = Pattern->getInstantiatedFromMemberTemplate();
if (!mightReferToOuterTemplateParameters(Pattern->getTemplatedDecl()))
return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc,
TemplateArgs);

Decl *NewD =
TypedefNameInstantiator->InstantiateTypeAliasTemplateDecl(TATD);
if (!NewD)
return QualType();

auto *NewTATD = cast<TypeAliasTemplateDecl>(NewD);
MaterializedTypedefs.push_back(NewTATD->getTemplatedDecl());

return Base::RebuildTemplateSpecializationType(
TemplateName(NewTATD), TemplateNameLoc, TemplateArgs);
}

QualType TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) {
ASTContext &Context = SemaRef.getASTContext();
TypedefNameDecl *OrigDecl = TL.getTypedefNameDecl();
TypedefNameDecl *Decl = OrigDecl;
// Transform the underlying type of the typedef and clone the Decl only if
// the typedef has a dependent context.
if (OrigDecl->getDeclContext()->isDependentContext()) {
bool InDependentContext = OrigDecl->getDeclContext()->isDependentContext();

// A typedef/alias Decl within the NestedPattern may reference the outer
// template parameters. They're substituted with corresponding instantiation
// arguments here and in RebuildTemplateSpecializationType() above.
// Otherwise, we would have a CTAD guide with "dangling" template
// parameters.
// For example,
// template <class T> struct Outer {
// using Alias = S<T>;
// template <class U> struct Inner {
// Inner(Alias);
// };
// };
if (OuterInstantiationArgs && InDependentContext &&
TL.getTypePtr()->isInstantiationDependentType()) {
Decl = cast_if_present<TypedefNameDecl>(
TypedefNameInstantiator->InstantiateTypedefNameDecl(
OrigDecl, /*IsTypeAlias=*/isa<TypeAliasDecl>(OrigDecl)));
if (!Decl)
return QualType();
MaterializedTypedefs.push_back(Decl);
} else if (InDependentContext) {
TypeLocBuilder InnerTLB;
QualType Transformed =
TransformType(InnerTLB, OrigDecl->getTypeSourceInfo()->getTypeLoc());
Expand All @@ -2220,8 +2307,12 @@ class ExtractTypeForDeductionGuide
}
};

// Build a deduction guide with the specified parameter types.
FunctionTemplateDecl *buildDeductionGuide(
// Build a deduction guide using the provided information.
//
// A deduction guide can be either a template or a non-template function
// declaration. If \p TemplateParams is null, a non-template function
// declaration will be created.
NamedDecl *buildDeductionGuide(
Sema &SemaRef, TemplateDecl *OriginalTemplate,
TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
Expand All @@ -2247,16 +2338,21 @@ FunctionTemplateDecl *buildDeductionGuide(
Param->setDeclContext(Guide);
for (auto *TD : MaterializedTypedefs)
TD->setDeclContext(Guide);
if (isa<CXXRecordDecl>(DC))
Guide->setAccess(AS_public);

if (!TemplateParams) {
DC->addDecl(Guide);
return Guide;
}

auto *GuideTemplate = FunctionTemplateDecl::Create(
SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
GuideTemplate->setImplicit(IsImplicit);
Guide->setDescribedFunctionTemplate(GuideTemplate);

if (isa<CXXRecordDecl>(DC)) {
Guide->setAccess(AS_public);
if (isa<CXXRecordDecl>(DC))
GuideTemplate->setAccess(AS_public);
}

DC->addDecl(GuideTemplate);
return GuideTemplate;
Expand Down Expand Up @@ -2541,16 +2637,18 @@ struct ConvertConstructorToDeductionGuideTransform {
// defined outside of the surrounding class template. That is T in the
// above example.
if (NestedPattern) {
NewParam = transformFunctionTypeParam(NewParam, OuterInstantiationArgs,
MaterializedTypedefs);
NewParam = transformFunctionTypeParam(
NewParam, OuterInstantiationArgs, MaterializedTypedefs,
/*TransformingOuterPatterns=*/true);
if (!NewParam)
return QualType();
}
// Then, transform all the references to template parameters that are
// defined at the class template and the constructor. In this example,
// they're U and V, respectively.
NewParam =
transformFunctionTypeParam(NewParam, Args, MaterializedTypedefs);
transformFunctionTypeParam(NewParam, Args, MaterializedTypedefs,
/*TransformingOuterPatterns=*/false);
if (!NewParam)
return QualType();
ParamTypes.push_back(NewParam->getType());
Expand Down Expand Up @@ -2594,7 +2692,8 @@ struct ConvertConstructorToDeductionGuideTransform {

ParmVarDecl *transformFunctionTypeParam(
ParmVarDecl *OldParam, MultiLevelTemplateArgumentList &Args,
llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs) {
llvm::SmallVectorImpl<TypedefNameDecl *> &MaterializedTypedefs,
bool TransformingOuterPatterns) {
TypeSourceInfo *OldDI = OldParam->getTypeSourceInfo();
TypeSourceInfo *NewDI;
if (auto PackTL = OldDI->getTypeLoc().getAs<PackExpansionTypeLoc>()) {
Expand All @@ -2617,7 +2716,9 @@ struct ConvertConstructorToDeductionGuideTransform {
// members of the current instantiations with the definitions of those
// typedefs, avoiding triggering instantiation of the deduced type during
// deduction.
NewDI = ExtractTypeForDeductionGuide(SemaRef, MaterializedTypedefs)
NewDI = ExtractTypeForDeductionGuide(
SemaRef, MaterializedTypedefs, NestedPattern,
TransformingOuterPatterns ? &Args : nullptr)
.transform(NewDI);

// Resolving a wording defect, we also inherit default arguments from the
Expand Down Expand Up @@ -2898,7 +2999,8 @@ Expr *buildIsDeducibleConstraint(Sema &SemaRef,
ASTContext &Context = SemaRef.Context;
// Constraint AST nodes must use uninstantiated depth.
if (auto *PrimaryTemplate =
AliasTemplate->getInstantiatedFromMemberTemplate()) {
AliasTemplate->getInstantiatedFromMemberTemplate();
PrimaryTemplate && TemplateParams.size() > 0) {
LocalInstantiationScope Scope(SemaRef);

// Adjust the depth for TemplateParams.
Expand Down Expand Up @@ -3162,12 +3264,12 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef,
FPrimeTemplateParams,
AliasTemplate->getTemplateParameters()->getRAngleLoc(),
/*RequiresClause=*/RequiresClause);
FunctionTemplateDecl *Result = buildDeductionGuide(
auto *Result = cast<FunctionTemplateDecl>(buildDeductionGuide(
SemaRef, AliasTemplate, FPrimeTemplateParamList,
GG->getCorrespondingConstructor(), GG->getExplicitSpecifier(),
GG->getTypeSourceInfo(), AliasTemplate->getBeginLoc(),
AliasTemplate->getLocation(), AliasTemplate->getEndLoc(),
F->isImplicit());
F->isImplicit()));
cast<CXXDeductionGuideDecl>(Result->getTemplatedDecl())
->setDeductionCandidateKind(GG->getDeductionCandidateKind());
return Result;
Expand Down Expand Up @@ -3198,6 +3300,44 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
Guides.suppressDiagnostics();

for (auto *G : Guides) {
if (auto *DG = dyn_cast<CXXDeductionGuideDecl>(G)) {
// The deduction guide is a non-template function decl, we just clone it.
auto *FunctionType =
SemaRef.Context.getTrivialTypeSourceInfo(DG->getType());
FunctionProtoTypeLoc FPTL =
FunctionType->getTypeLoc().castAs<FunctionProtoTypeLoc>();

// Clone the parameters.
for (unsigned I = 0, N = DG->getNumParams(); I != N; ++I) {
const auto *P = DG->getParamDecl(I);
auto *TSI = SemaRef.Context.getTrivialTypeSourceInfo(P->getType());
ParmVarDecl *NewParam = ParmVarDecl::Create(
SemaRef.Context, G->getDeclContext(),
DG->getParamDecl(I)->getBeginLoc(), P->getLocation(), nullptr,
TSI->getType(), TSI, SC_None, nullptr);
NewParam->setScopeInfo(0, I);
FPTL.setParam(I, NewParam);
}
auto *Transformed = cast<FunctionDecl>(buildDeductionGuide(
SemaRef, AliasTemplate, /*TemplateParams=*/nullptr,
/*Constructor=*/nullptr, DG->getExplicitSpecifier(), FunctionType,
AliasTemplate->getBeginLoc(), AliasTemplate->getLocation(),
AliasTemplate->getEndLoc(), DG->isImplicit()));

// FIXME: Here the synthesized deduction guide is not a templated
// function. Per [dcl.decl]p4, the requires-clause shall be present only
// if the declarator declares a templated function, a bug in standard?
auto *Constraint = buildIsDeducibleConstraint(
SemaRef, AliasTemplate, Transformed->getReturnType(), {});
if (auto *RC = DG->getTrailingRequiresClause()) {
auto Conjunction =
SemaRef.BuildBinOp(SemaRef.getCurScope(), SourceLocation{},
BinaryOperatorKind::BO_LAnd, RC, Constraint);
if (!Conjunction.isInvalid())
Constraint = Conjunction.getAs<Expr>();
}
Transformed->setTrailingRequiresClause(Constraint);
}
FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(G);
if (!F)
continue;
Expand Down
17 changes: 14 additions & 3 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1096,8 +1096,8 @@ Decl *TemplateDeclInstantiator::VisitTypeAliasDecl(TypeAliasDecl *D) {
return Typedef;
}

Decl *
TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
Decl *TemplateDeclInstantiator::InstantiateTypeAliasTemplateDecl(
TypeAliasTemplateDecl *D) {
// Create a local instantiation scope for this type alias template, which
// will contain the instantiations of the template parameters.
LocalInstantiationScope Scope(SemaRef);
Expand Down Expand Up @@ -1143,7 +1143,14 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
if (!PrevAliasTemplate)
Inst->setInstantiatedFromMemberTemplate(D);

Owner->addDecl(Inst);
return Inst;
}

Decl *
TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
Decl *Inst = InstantiateTypeAliasTemplateDecl(D);
if (Inst)
Owner->addDecl(Inst);

return Inst;
}
Expand Down Expand Up @@ -3413,6 +3420,10 @@ Decl *TemplateDeclInstantiator::VisitUsingEnumDecl(UsingEnumDecl *D) {

TypeSourceInfo *TSI = SemaRef.SubstType(D->getEnumType(), TemplateArgs,
D->getLocation(), D->getDeclName());

if (!TSI)
return nullptr;

UsingEnumDecl *NewUD =
UsingEnumDecl::Create(SemaRef.Context, Owner, D->getUsingLoc(),
D->getEnumLoc(), D->getLocation(), TSI);
Expand Down
8 changes: 5 additions & 3 deletions clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9324,15 +9324,17 @@ BuildTypeCoupledDecls(Expr *E,
}

QualType Sema::BuildCountAttributedArrayOrPointerType(QualType WrappedTy,
Expr *CountExpr) {
Expr *CountExpr,
bool CountInBytes,
bool OrNull) {
assert(WrappedTy->isIncompleteArrayType() || WrappedTy->isPointerType());

llvm::SmallVector<TypeCoupledDeclRefInfo, 1> Decls;
BuildTypeCoupledDecls(CountExpr, Decls);
/// When the resulting expression is invalid, we still create the AST using
/// the original count expression for the sake of AST dump.
return Context.getCountAttributedType(
WrappedTy, CountExpr, /*CountInBytes*/ false, /*OrNull*/ false, Decls);
return Context.getCountAttributedType(WrappedTy, CountExpr, CountInBytes,
OrNull, Decls);
}

/// getDecltypeForExpr - Given an expr, will return the decltype for
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -7397,7 +7397,8 @@ QualType TreeTransform<Derived>::TransformCountAttributedType(
if (getDerived().AlwaysRebuild() || InnerTy != OldTy->desugar() ||
OldCount != NewCount) {
// Currently, CountAttributedType can only wrap incomplete array types.
Result = SemaRef.BuildCountAttributedArrayOrPointerType(InnerTy, NewCount);
Result = SemaRef.BuildCountAttributedArrayOrPointerType(
InnerTy, NewCount, OldTy->isCountInBytes(), OldTy->isOrNull());
}

TLB.push<CountAttributedTypeLoc>(Result);
Expand Down
11 changes: 0 additions & 11 deletions clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3921,13 +3921,6 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
}
break;

case VTABLES_TO_EMIT:
if (F.Kind == MK_MainFile ||
getContext().getLangOpts().BuildingPCHWithObjectFile)
for (unsigned I = 0, N = Record.size(); I != N; /*in loop*/)
VTablesToEmit.push_back(ReadDeclID(F, Record, I));
break;

case IMPORTED_MODULES:
if (!F.isModule()) {
// If we aren't loading a module (which has its own exports), make
Expand Down Expand Up @@ -8117,10 +8110,6 @@ void ASTReader::PassInterestingDeclToConsumer(Decl *D) {
Consumer->HandleInterestingDecl(DeclGroupRef(D));
}

void ASTReader::PassVTableToConsumer(CXXRecordDecl *RD) {
Consumer->HandleVTable(RD);
}

void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) {
this->Consumer = Consumer;

Expand Down
7 changes: 0 additions & 7 deletions clang/lib/Serialization/ASTReaderDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4235,13 +4235,6 @@ void ASTReader::PassInterestingDeclsToConsumer() {

// If we add any new potential interesting decl in the last call, consume it.
ConsumingPotentialInterestingDecls();

for (GlobalDeclID ID : VTablesToEmit) {
auto *RD = cast<CXXRecordDecl>(GetDecl(ID));
assert(!RD->shouldEmitInExternalSource());
PassVTableToConsumer(RD);
}
VTablesToEmit.clear();
}

void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
Expand Down
33 changes: 4 additions & 29 deletions clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -927,7 +927,6 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS);
RECORD(PP_ASSUME_NONNULL_LOC);
RECORD(PP_UNSAFE_BUFFER_USAGE);
RECORD(VTABLES_TO_EMIT);

// SourceManager Block.
BLOCK(SOURCE_MANAGER_BLOCK);
Expand Down Expand Up @@ -3962,10 +3961,6 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
Stream.EmitRecord(INTERESTING_IDENTIFIERS, InterestingIdents);
}

void ASTWriter::handleVTable(CXXRecordDecl *RD) {
PendingEmittingVTables.push_back(RD);
}

//===----------------------------------------------------------------------===//
// DeclContext's Name Lookup Table Serialization
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -5168,13 +5163,6 @@ void ASTWriter::PrepareWritingSpecialDecls(Sema &SemaRef) {
// Write all of the DeclsToCheckForDeferredDiags.
for (auto *D : SemaRef.DeclsToCheckForDeferredDiags)
GetDeclRef(D);

// Write all classes need to emit the vtable definitions if required.
if (isWritingStdCXXNamedModules())
for (CXXRecordDecl *RD : PendingEmittingVTables)
GetDeclRef(RD);
else
PendingEmittingVTables.clear();
}

void ASTWriter::WriteSpecialDeclRecords(Sema &SemaRef) {
Expand Down Expand Up @@ -5329,17 +5317,6 @@ void ASTWriter::WriteSpecialDeclRecords(Sema &SemaRef) {
}
if (!DeleteExprsToAnalyze.empty())
Stream.EmitRecord(DELETE_EXPRS_TO_ANALYZE, DeleteExprsToAnalyze);

RecordData VTablesToEmit;
for (CXXRecordDecl *RD : PendingEmittingVTables) {
if (!wasDeclEmitted(RD))
continue;

AddDeclRef(RD, VTablesToEmit);
}

if (!VTablesToEmit.empty())
Stream.EmitRecord(VTABLES_TO_EMIT, VTablesToEmit);
}

ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
Expand Down Expand Up @@ -6587,12 +6564,10 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {
// computed.
Record->push_back(D->getODRHash());

bool ModulesCodegen =
!D->isDependentType() &&
(Writer->Context->getLangOpts().ModulesDebugInfo ||
D->isInNamedModule());
Record->push_back(ModulesCodegen);
if (ModulesCodegen)
bool ModulesDebugInfo =
Writer->Context->getLangOpts().ModulesDebugInfo && !D->isDependentType();
Record->push_back(ModulesDebugInfo);
if (ModulesDebugInfo)
Writer->AddDeclRef(D, Writer->ModularCodegenDecls);

// IsLambda bit is already saved.
Expand Down
6 changes: 0 additions & 6 deletions clang/lib/Serialization/ASTWriterDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1537,14 +1537,8 @@ void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
if (D->isThisDeclarationADefinition())
Record.AddCXXDefinitionData(D);

if (D->isCompleteDefinition() && D->isInNamedModule())
Writer.AddDeclRef(D, Writer.ModularCodegenDecls);

// Store (what we currently believe to be) the key function to avoid
// deserializing every method so we can compute it.
//
// FIXME: Avoid adding the key function if the class is defined in
// module purview since the key function is meaningless in module purview.
if (D->isCompleteDefinition())
Record.AddDeclRef(Context.getCurrentKeyFunction(D));

Expand Down
28 changes: 22 additions & 6 deletions clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/YAMLTraits.h"

#include <limits>
Expand Down Expand Up @@ -391,9 +392,10 @@ class GenericTaintChecker : public Checker<check::PreCall, check::PostCall> {
bool generateReportIfTainted(const Expr *E, StringRef Msg,
CheckerContext &C) const;

private:
const BugType BT{this, "Use of Untrusted Data", categories::TaintedData};
bool isTaintReporterCheckerEnabled = false;
std::optional<BugType> BT;

private:
bool checkUncontrolledFormatString(const CallEvent &Call,
CheckerContext &C) const;

Expand Down Expand Up @@ -1033,20 +1035,23 @@ bool GenericTaintRule::UntrustedEnv(CheckerContext &C) {
bool GenericTaintChecker::generateReportIfTainted(const Expr *E, StringRef Msg,
CheckerContext &C) const {
assert(E);
if (!isTaintReporterCheckerEnabled)
return false;
std::optional<SVal> TaintedSVal =
getTaintedPointeeOrPointer(C.getState(), C.getSVal(E));

if (!TaintedSVal)
return false;

// Generate diagnostic.
if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
auto report = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
assert(BT);
static CheckerProgramPointTag Tag(BT->getCheckerName(), Msg);
if (ExplodedNode *N = C.generateNonFatalErrorNode(C.getState(), &Tag)) {
auto report = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
report->addRange(E->getSourceRange());
for (auto TaintedSym : getTaintedSymbols(C.getState(), *TaintedSVal)) {
report->markInteresting(TaintedSym);
}

C.emitReport(std::move(report));
return true;
}
Expand Down Expand Up @@ -1122,10 +1127,21 @@ void GenericTaintChecker::taintUnsafeSocketProtocol(const CallEvent &Call,
}

/// Checker registration
void ento::registerGenericTaintChecker(CheckerManager &Mgr) {
void ento::registerTaintPropagationChecker(CheckerManager &Mgr) {
Mgr.registerChecker<GenericTaintChecker>();
}

bool ento::shouldRegisterTaintPropagationChecker(const CheckerManager &mgr) {
return true;
}

void ento::registerGenericTaintChecker(CheckerManager &Mgr) {
GenericTaintChecker *checker = Mgr.getChecker<GenericTaintChecker>();
checker->isTaintReporterCheckerEnabled = true;
checker->BT.emplace(Mgr.getCurrentCheckerName(), "Use of Untrusted Data",
categories::TaintedData);
}

bool ento::shouldRegisterGenericTaintChecker(const CheckerManager &mgr) {
return true;
}
10 changes: 8 additions & 2 deletions clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2057,11 +2057,17 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
llvm_unreachable("Support for MatrixSubscriptExpr is not implemented.");
break;

case Stmt::GCCAsmStmtClass:
case Stmt::GCCAsmStmtClass: {
Bldr.takeNodes(Pred);
VisitGCCAsmStmt(cast<GCCAsmStmt>(S), Pred, Dst);
ExplodedNodeSet PreVisit;
getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
ExplodedNodeSet PostVisit;
for (ExplodedNode *const N : PreVisit)
VisitGCCAsmStmt(cast<GCCAsmStmt>(S), N, PostVisit);
getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
Bldr.addNodes(Dst);
break;
}

case Stmt::MSAsmStmtClass:
Bldr.takeNodes(Pred);
Expand Down
45 changes: 45 additions & 0 deletions clang/test/AST/attr-counted-by-or-null-late-parsed-struct-ptrs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// RUN: %clang_cc1 -fexperimental-late-parse-attributes %s -ast-dump | FileCheck %s

#define __counted_by_or_null(f) __attribute__((counted_by_or_null(f)))

struct size_known {
int field;
};

//==============================================================================
// __counted_by_or_null on struct member pointer in decl attribute position
//==============================================================================

struct on_member_pointer_complete_ty {
struct size_known *buf __counted_by_or_null(count);
int count;
};
// CHECK-LABEL: struct on_member_pointer_complete_ty definition
// CHECK-NEXT: |-FieldDecl {{.*}} buf 'struct size_known * __counted_by_or_null(count)':'struct size_known *'
// CHECK-NEXT: `-FieldDecl {{.*}} referenced count 'int'

struct on_pointer_anon_count {
struct size_known *buf __counted_by_or_null(count);
struct {
int count;
};
};

// CHECK-LABEL: struct on_pointer_anon_count definition
// CHECK-NEXT: |-FieldDecl {{.*}} buf 'struct size_known * __counted_by_or_null(count)':'struct size_known *'
// CHECK-NEXT: |-RecordDecl {{.*}} struct definition
// CHECK-NEXT: | `-FieldDecl {{.*}} count 'int'
// CHECK-NEXT: |-FieldDecl {{.*}} implicit 'struct on_pointer_anon_count::(anonymous at {{.*}})'
// CHECK-NEXT: `-IndirectFieldDecl {{.*}} implicit referenced count 'int'
// CHECK-NEXT: |-Field {{.*}} '' 'struct on_pointer_anon_count::(anonymous at {{.*}})'
// CHECK-NEXT: `-Field {{.*}} 'count' 'int'

//==============================================================================
// __counted_by_or_null on struct member pointer in type attribute position
//==============================================================================
// TODO: Correctly parse counted_by_or_null as a type attribute. Currently it is parsed
// as a declaration attribute and is **not** late parsed resulting in the `count`
// field being unavailable.
//
// See `clang/test/Sema/attr-counted-by-late-parsed-struct-ptrs.c` for test
// cases.
117 changes: 117 additions & 0 deletions clang/test/AST/attr-counted-by-or-null-struct-ptrs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// RUN: %clang_cc1 %s -ast-dump | FileCheck %s

#define __counted_by_or_null(f) __attribute__((counted_by_or_null(f)))

struct size_unknown;
struct size_known {
int field;
};

//==============================================================================
// __counted_by_or_null on struct member pointer in decl attribute position
//==============================================================================

// CHECK-LABEL: RecordDecl {{.+}} struct on_member_pointer_complete_ty definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: `-FieldDecl {{.+}} buf 'struct size_known * __counted_by_or_null(count)':'struct size_known *'
struct on_member_pointer_complete_ty {
int count;
struct size_known * buf __counted_by_or_null(count);
};

// CHECK-LABEL: RecordDecl {{.+}} struct on_pointer_anon_buf definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: |-RecordDecl {{.+}} struct definition
// CHECK-NEXT: | `-FieldDecl {{.+}} buf 'struct size_known * __counted_by_or_null(count)':'struct size_known *'
// CHECK-NEXT: |-FieldDecl {{.+}} implicit 'struct on_pointer_anon_buf::(anonymous at [[ANON_STRUCT_PATH:.+]])'
// CHECK-NEXT: `-IndirectFieldDecl {{.+}} implicit buf 'struct size_known * __counted_by_or_null(count)':'struct size_known *'
// CHECK-NEXT: |-Field {{.+}} '' 'struct on_pointer_anon_buf::(anonymous at [[ANON_STRUCT_PATH]])'
// CHECK-NEXT: `-Field {{.+}} 'buf' 'struct size_known * __counted_by_or_null(count)':'struct size_known *'
struct on_pointer_anon_buf {
int count;
struct {
struct size_known *buf __counted_by_or_null(count);
};
};

struct on_pointer_anon_count {
struct {
int count;
};
struct size_known *buf __counted_by_or_null(count);
};

//==============================================================================
// __counted_by_or_null on struct member pointer in type attribute position
//==============================================================================
// TODO: Correctly parse counted_by_or_null as a type attribute. Currently it is parsed
// as a declaration attribute

// CHECK-LABEL: RecordDecl {{.+}} struct on_member_pointer_complete_ty_ty_pos definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: `-FieldDecl {{.+}} buf 'struct size_known * __counted_by_or_null(count)':'struct size_known *'
struct on_member_pointer_complete_ty_ty_pos {
int count;
struct size_known *__counted_by_or_null(count) buf;
};

// TODO: This should be forbidden but isn't due to counted_by_or_null being treated as a
// declaration attribute. The attribute ends up on the outer most pointer
// (allowed by sema) even though syntactically its supposed to be on the inner
// pointer (would not allowed by sema due to pointee being a function type).
// CHECK-LABEL: RecordDecl {{.+}} struct on_member_pointer_fn_ptr_ty_ty_pos_inner definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: `-FieldDecl {{.+}} fn_ptr 'void (** __counted_by_or_null(count))(void)':'void (**)(void)'
struct on_member_pointer_fn_ptr_ty_ty_pos_inner {
int count;
void (* __counted_by_or_null(count) * fn_ptr)(void);
};

// FIXME: The generated AST here is wrong. The attribute should be on the inner
// pointer.
// CHECK-LABEL: RecordDecl {{.+}} struct on_nested_pointer_inner definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: `-FieldDecl {{.+}} buf 'struct size_known ** __counted_by_or_null(count)':'struct size_known **'
struct on_nested_pointer_inner {
int count;
// TODO: This should be disallowed because in the `-fbounds-safety` model
// `__counted_by_or_null` can only be nested when used in function parameters.
struct size_known *__counted_by_or_null(count) *buf;
};

// CHECK-LABEL: RecordDecl {{.+}} struct on_nested_pointer_outer definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: `-FieldDecl {{.+}} buf 'struct size_known ** __counted_by_or_null(count)':'struct size_known **'
struct on_nested_pointer_outer {
int count;
struct size_known **__counted_by_or_null(count) buf;
};

// CHECK-LABEL: RecordDecl {{.+}} struct on_pointer_anon_buf_ty_pos definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: |-RecordDecl {{.+}} struct definition
// CHECK-NEXT: | `-FieldDecl {{.+}} buf 'struct size_known * __counted_by_or_null(count)':'struct size_known *'
// CHECK-NEXT: |-FieldDecl {{.+}} implicit 'struct on_pointer_anon_buf_ty_pos::(anonymous at [[ANON_STRUCT_PATH2:.+]])'
// CHECK-NEXT: `-IndirectFieldDecl {{.+}} implicit buf 'struct size_known * __counted_by_or_null(count)':'struct size_known *'
// CHECK-NEXT: |-Field {{.+}} '' 'struct on_pointer_anon_buf_ty_pos::(anonymous at [[ANON_STRUCT_PATH2]])'
// CHECK-NEXT: `-Field {{.+}} 'buf' 'struct size_known * __counted_by_or_null(count)':'struct size_known *'
struct on_pointer_anon_buf_ty_pos {
int count;
struct {
struct size_known * __counted_by_or_null(count) buf;
};
};

// CHECK-LABEL: RecordDecl {{.+}} struct on_pointer_anon_count_ty_pos definition
// CHECK-NEXT: |-RecordDecl {{.+}} struct definition
// CHECK-NEXT: | `-FieldDecl {{.+}} count 'int'
// CHECK-NEXT: |-FieldDecl {{.+}} implicit 'struct on_pointer_anon_count_ty_pos::(anonymous at [[ANON_STRUCT_PATH3:.+]])'
// CHECK-NEXT: |-IndirectFieldDecl {{.+}} implicit referenced count 'int'
// CHECK-NEXT: | |-Field {{.+}} '' 'struct on_pointer_anon_count_ty_pos::(anonymous at [[ANON_STRUCT_PATH3]])'
// CHECK-NEXT: | `-Field {{.+}} 'count' 'int'
struct on_pointer_anon_count_ty_pos {
struct {
int count;
};
struct size_known *__counted_by_or_null(count) buf;
};
45 changes: 45 additions & 0 deletions clang/test/AST/attr-sized-by-late-parsed-struct-ptrs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// RUN: %clang_cc1 -fexperimental-late-parse-attributes %s -ast-dump | FileCheck %s

#define __sized_by(f) __attribute__((sized_by(f)))

struct size_known {
int field;
};

//==============================================================================
// __sized_by on struct member pointer in decl attribute position
//==============================================================================

struct on_member_pointer_complete_ty {
struct size_known *buf __sized_by(count);
int count;
};
// CHECK-LABEL: struct on_member_pointer_complete_ty definition
// CHECK-NEXT: |-FieldDecl {{.*}} buf 'struct size_known * __sized_by(count)':'struct size_known *'
// CHECK-NEXT: `-FieldDecl {{.*}} referenced count 'int'

struct on_pointer_anon_count {
struct size_known *buf __sized_by(count);
struct {
int count;
};
};

// CHECK-LABEL: struct on_pointer_anon_count definition
// CHECK-NEXT: |-FieldDecl {{.*}} buf 'struct size_known * __sized_by(count)':'struct size_known *'
// CHECK-NEXT: |-RecordDecl {{.*}} struct definition
// CHECK-NEXT: | `-FieldDecl {{.*}} count 'int'
// CHECK-NEXT: |-FieldDecl {{.*}} implicit 'struct on_pointer_anon_count::(anonymous at {{.*}})'
// CHECK-NEXT: `-IndirectFieldDecl {{.*}} implicit referenced count 'int'
// CHECK-NEXT: |-Field {{.*}} '' 'struct on_pointer_anon_count::(anonymous at {{.*}})'
// CHECK-NEXT: `-Field {{.*}} 'count' 'int'

//==============================================================================
// __sized_by on struct member pointer in type attribute position
//==============================================================================
// TODO: Correctly parse sized_by as a type attribute. Currently it is parsed
// as a declaration attribute and is **not** late parsed resulting in the `count`
// field being unavailable.
//
// See `clang/test/Sema/attr-counted-by-late-parsed-struct-ptrs.c` for test
// cases.
45 changes: 45 additions & 0 deletions clang/test/AST/attr-sized-by-or-null-late-parsed-struct-ptrs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// RUN: %clang_cc1 -fexperimental-late-parse-attributes %s -ast-dump | FileCheck %s

#define __sized_by_or_null(f) __attribute__((sized_by_or_null(f)))

struct size_known {
int field;
};

//==============================================================================
// __sized_by_or_null on struct member pointer in decl attribute position
//==============================================================================

struct on_member_pointer_complete_ty {
struct size_known *buf __sized_by_or_null(count);
int count;
};
// CHECK-LABEL: struct on_member_pointer_complete_ty definition
// CHECK-NEXT: |-FieldDecl {{.*}} buf 'struct size_known * __sized_by_or_null(count)':'struct size_known *'
// CHECK-NEXT: `-FieldDecl {{.*}} referenced count 'int'

struct on_pointer_anon_count {
struct size_known *buf __sized_by_or_null(count);
struct {
int count;
};
};

// CHECK-LABEL: struct on_pointer_anon_count definition
// CHECK-NEXT: |-FieldDecl {{.*}} buf 'struct size_known * __sized_by_or_null(count)':'struct size_known *'
// CHECK-NEXT: |-RecordDecl {{.*}} struct definition
// CHECK-NEXT: | `-FieldDecl {{.*}} count 'int'
// CHECK-NEXT: |-FieldDecl {{.*}} implicit 'struct on_pointer_anon_count::(anonymous at {{.*}})'
// CHECK-NEXT: `-IndirectFieldDecl {{.*}} implicit referenced count 'int'
// CHECK-NEXT: |-Field {{.*}} '' 'struct on_pointer_anon_count::(anonymous at {{.*}})'
// CHECK-NEXT: `-Field {{.*}} 'count' 'int'

//==============================================================================
// __sized_by_or_null on struct member pointer in type attribute position
//==============================================================================
// TODO: Correctly parse sized_by_or_null as a type attribute. Currently it is parsed
// as a declaration attribute and is **not** late parsed resulting in the `count`
// field being unavailable.
//
// See `clang/test/Sema/attr-counted-by-late-parsed-struct-ptrs.c` for test
// cases.
117 changes: 117 additions & 0 deletions clang/test/AST/attr-sized-by-or-null-struct-ptrs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// RUN: %clang_cc1 %s -ast-dump | FileCheck %s

#define __sized_by_or_null(f) __attribute__((sized_by_or_null(f)))

struct size_unknown;
struct size_known {
int field;
};

//==============================================================================
// __sized_by_or_null on struct member pointer in decl attribute position
//==============================================================================

// CHECK-LABEL: RecordDecl {{.+}} struct on_member_pointer_complete_ty definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: `-FieldDecl {{.+}} buf 'struct size_known * __sized_by_or_null(count)':'struct size_known *'
struct on_member_pointer_complete_ty {
int count;
struct size_known * buf __sized_by_or_null(count);
};

// CHECK-LABEL: RecordDecl {{.+}} struct on_pointer_anon_buf definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: |-RecordDecl {{.+}} struct definition
// CHECK-NEXT: | `-FieldDecl {{.+}} buf 'struct size_known * __sized_by_or_null(count)':'struct size_known *'
// CHECK-NEXT: |-FieldDecl {{.+}} implicit 'struct on_pointer_anon_buf::(anonymous at [[ANON_STRUCT_PATH:.+]])'
// CHECK-NEXT: `-IndirectFieldDecl {{.+}} implicit buf 'struct size_known * __sized_by_or_null(count)':'struct size_known *'
// CHECK-NEXT: |-Field {{.+}} '' 'struct on_pointer_anon_buf::(anonymous at [[ANON_STRUCT_PATH]])'
// CHECK-NEXT: `-Field {{.+}} 'buf' 'struct size_known * __sized_by_or_null(count)':'struct size_known *'
struct on_pointer_anon_buf {
int count;
struct {
struct size_known *buf __sized_by_or_null(count);
};
};

struct on_pointer_anon_count {
struct {
int count;
};
struct size_known *buf __sized_by_or_null(count);
};

//==============================================================================
// __sized_by_or_null on struct member pointer in type attribute position
//==============================================================================
// TODO: Correctly parse sized_by_or_null as a type attribute. Currently it is parsed
// as a declaration attribute

// CHECK-LABEL: RecordDecl {{.+}} struct on_member_pointer_complete_ty_ty_pos definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: `-FieldDecl {{.+}} buf 'struct size_known * __sized_by_or_null(count)':'struct size_known *'
struct on_member_pointer_complete_ty_ty_pos {
int count;
struct size_known *__sized_by_or_null(count) buf;
};

// TODO: This should be forbidden but isn't due to sized_by_or_null being treated as a
// declaration attribute. The attribute ends up on the outer most pointer
// (allowed by sema) even though syntactically its supposed to be on the inner
// pointer (would not allowed by sema due to pointee being a function type).
// CHECK-LABEL: RecordDecl {{.+}} struct on_member_pointer_fn_ptr_ty_ty_pos_inner definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: `-FieldDecl {{.+}} fn_ptr 'void (** __sized_by_or_null(count))(void)':'void (**)(void)'
struct on_member_pointer_fn_ptr_ty_ty_pos_inner {
int count;
void (* __sized_by_or_null(count) * fn_ptr)(void);
};

// FIXME: The generated AST here is wrong. The attribute should be on the inner
// pointer.
// CHECK-LABEL: RecordDecl {{.+}} struct on_nested_pointer_inner definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: `-FieldDecl {{.+}} buf 'struct size_known ** __sized_by_or_null(count)':'struct size_known **'
struct on_nested_pointer_inner {
int count;
// TODO: This should be disallowed because in the `-fbounds-safety` model
// `__sized_by_or_null` can only be nested when used in function parameters.
struct size_known *__sized_by_or_null(count) *buf;
};

// CHECK-LABEL: RecordDecl {{.+}} struct on_nested_pointer_outer definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: `-FieldDecl {{.+}} buf 'struct size_known ** __sized_by_or_null(count)':'struct size_known **'
struct on_nested_pointer_outer {
int count;
struct size_known **__sized_by_or_null(count) buf;
};

// CHECK-LABEL: RecordDecl {{.+}} struct on_pointer_anon_buf_ty_pos definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: |-RecordDecl {{.+}} struct definition
// CHECK-NEXT: | `-FieldDecl {{.+}} buf 'struct size_known * __sized_by_or_null(count)':'struct size_known *'
// CHECK-NEXT: |-FieldDecl {{.+}} implicit 'struct on_pointer_anon_buf_ty_pos::(anonymous at [[ANON_STRUCT_PATH2:.+]])'
// CHECK-NEXT: `-IndirectFieldDecl {{.+}} implicit buf 'struct size_known * __sized_by_or_null(count)':'struct size_known *'
// CHECK-NEXT: |-Field {{.+}} '' 'struct on_pointer_anon_buf_ty_pos::(anonymous at [[ANON_STRUCT_PATH2]])'
// CHECK-NEXT: `-Field {{.+}} 'buf' 'struct size_known * __sized_by_or_null(count)':'struct size_known *'
struct on_pointer_anon_buf_ty_pos {
int count;
struct {
struct size_known * __sized_by_or_null(count) buf;
};
};

// CHECK-LABEL: RecordDecl {{.+}} struct on_pointer_anon_count_ty_pos definition
// CHECK-NEXT: |-RecordDecl {{.+}} struct definition
// CHECK-NEXT: | `-FieldDecl {{.+}} count 'int'
// CHECK-NEXT: |-FieldDecl {{.+}} implicit 'struct on_pointer_anon_count_ty_pos::(anonymous at [[ANON_STRUCT_PATH3:.+]])'
// CHECK-NEXT: |-IndirectFieldDecl {{.+}} implicit referenced count 'int'
// CHECK-NEXT: | |-Field {{.+}} '' 'struct on_pointer_anon_count_ty_pos::(anonymous at [[ANON_STRUCT_PATH3]])'
// CHECK-NEXT: | `-Field {{.+}} 'count' 'int'
struct on_pointer_anon_count_ty_pos {
struct {
int count;
};
struct size_known *__sized_by_or_null(count) buf;
};
117 changes: 117 additions & 0 deletions clang/test/AST/attr-sized-by-struct-ptrs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// RUN: %clang_cc1 %s -ast-dump | FileCheck %s

#define __sized_by(f) __attribute__((sized_by(f)))

struct size_unknown;
struct size_known {
int field;
};

//==============================================================================
// __sized_by on struct member pointer in decl attribute position
//==============================================================================

// CHECK-LABEL: RecordDecl {{.+}} struct on_member_pointer_complete_ty definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: `-FieldDecl {{.+}} buf 'struct size_known * __sized_by(count)':'struct size_known *'
struct on_member_pointer_complete_ty {
int count;
struct size_known * buf __sized_by(count);
};

// CHECK-LABEL: RecordDecl {{.+}} struct on_pointer_anon_buf definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: |-RecordDecl {{.+}} struct definition
// CHECK-NEXT: | `-FieldDecl {{.+}} buf 'struct size_known * __sized_by(count)':'struct size_known *'
// CHECK-NEXT: |-FieldDecl {{.+}} implicit 'struct on_pointer_anon_buf::(anonymous at [[ANON_STRUCT_PATH:.+]])'
// CHECK-NEXT: `-IndirectFieldDecl {{.+}} implicit buf 'struct size_known * __sized_by(count)':'struct size_known *'
// CHECK-NEXT: |-Field {{.+}} '' 'struct on_pointer_anon_buf::(anonymous at [[ANON_STRUCT_PATH]])'
// CHECK-NEXT: `-Field {{.+}} 'buf' 'struct size_known * __sized_by(count)':'struct size_known *'
struct on_pointer_anon_buf {
int count;
struct {
struct size_known *buf __sized_by(count);
};
};

struct on_pointer_anon_count {
struct {
int count;
};
struct size_known *buf __sized_by(count);
};

//==============================================================================
// __sized_by on struct member pointer in type attribute position
//==============================================================================
// TODO: Correctly parse sized_by as a type attribute. Currently it is parsed
// as a declaration attribute

// CHECK-LABEL: RecordDecl {{.+}} struct on_member_pointer_complete_ty_ty_pos definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: `-FieldDecl {{.+}} buf 'struct size_known * __sized_by(count)':'struct size_known *'
struct on_member_pointer_complete_ty_ty_pos {
int count;
struct size_known *__sized_by(count) buf;
};

// TODO: This should be forbidden but isn't due to sized_by being treated as a
// declaration attribute. The attribute ends up on the outer most pointer
// (allowed by sema) even though syntactically its supposed to be on the inner
// pointer (would not allowed by sema due to pointee being a function type).
// CHECK-LABEL: RecordDecl {{.+}} struct on_member_pointer_fn_ptr_ty_ty_pos_inner definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: `-FieldDecl {{.+}} fn_ptr 'void (** __sized_by(count))(void)':'void (**)(void)'
struct on_member_pointer_fn_ptr_ty_ty_pos_inner {
int count;
void (* __sized_by(count) * fn_ptr)(void);
};

// FIXME: The generated AST here is wrong. The attribute should be on the inner
// pointer.
// CHECK-LABEL: RecordDecl {{.+}} struct on_nested_pointer_inner definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: `-FieldDecl {{.+}} buf 'struct size_known ** __sized_by(count)':'struct size_known **'
struct on_nested_pointer_inner {
int count;
// TODO: This should be disallowed because in the `-fbounds-safety` model
// `__sized_by` can only be nested when used in function parameters.
struct size_known *__sized_by(count) *buf;
};

// CHECK-LABEL: RecordDecl {{.+}} struct on_nested_pointer_outer definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: `-FieldDecl {{.+}} buf 'struct size_known ** __sized_by(count)':'struct size_known **'
struct on_nested_pointer_outer {
int count;
struct size_known **__sized_by(count) buf;
};

// CHECK-LABEL: RecordDecl {{.+}} struct on_pointer_anon_buf_ty_pos definition
// CHECK-NEXT: |-FieldDecl {{.+}} referenced count 'int'
// CHECK-NEXT: |-RecordDecl {{.+}} struct definition
// CHECK-NEXT: | `-FieldDecl {{.+}} buf 'struct size_known * __sized_by(count)':'struct size_known *'
// CHECK-NEXT: |-FieldDecl {{.+}} implicit 'struct on_pointer_anon_buf_ty_pos::(anonymous at [[ANON_STRUCT_PATH2:.+]])'
// CHECK-NEXT: `-IndirectFieldDecl {{.+}} implicit buf 'struct size_known * __sized_by(count)':'struct size_known *'
// CHECK-NEXT: |-Field {{.+}} '' 'struct on_pointer_anon_buf_ty_pos::(anonymous at [[ANON_STRUCT_PATH2]])'
// CHECK-NEXT: `-Field {{.+}} 'buf' 'struct size_known * __sized_by(count)':'struct size_known *'
struct on_pointer_anon_buf_ty_pos {
int count;
struct {
struct size_known * __sized_by(count) buf;
};
};

// CHECK-LABEL: RecordDecl {{.+}} struct on_pointer_anon_count_ty_pos definition
// CHECK-NEXT: |-RecordDecl {{.+}} struct definition
// CHECK-NEXT: | `-FieldDecl {{.+}} count 'int'
// CHECK-NEXT: |-FieldDecl {{.+}} implicit 'struct on_pointer_anon_count_ty_pos::(anonymous at [[ANON_STRUCT_PATH3:.+]])'
// CHECK-NEXT: |-IndirectFieldDecl {{.+}} implicit referenced count 'int'
// CHECK-NEXT: | |-Field {{.+}} '' 'struct on_pointer_anon_count_ty_pos::(anonymous at [[ANON_STRUCT_PATH3]])'
// CHECK-NEXT: | `-Field {{.+}} 'count' 'int'
struct on_pointer_anon_count_ty_pos {
struct {
int count;
};
struct size_known *__sized_by(count) buf;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// RUN: %clang_cc1 -verify -Wno-unused %s

struct A {
int y;
};

struct B; // expected-note 4{{forward declaration of 'B'}}

void f(A *a, B *b) {
a->B::x; // expected-error {{incomplete type 'B' named in nested name specifier}}
a->A::x; // expected-error {{no member named 'x' in 'A'}}
a->A::y;
b->B::x; // expected-error {{member access into incomplete type 'B'}}
b->A::x; // expected-error {{member access into incomplete type 'B'}}
b->A::y; // expected-error {{member access into incomplete type 'B'}}
}
26 changes: 13 additions & 13 deletions clang/test/CodeGen/aarch64-branch-protection-attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,29 +67,29 @@ __attribute__ ((target("branch-protection=gcs")))
void gcs() {}
// CHECK: define{{.*}} void @gcs() #[[#GCS:]]

// CHECK-DAG: attributes #[[#NONE]] = { {{.*}} "branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}} "sign-return-address"="none"
// CHECK-DAG: attributes #[[#NONE]] = { {{.*}}

// CHECK-DAG: attributes #[[#STD]] = { {{.*}} "branch-target-enforcement"="true" "guarded-control-stack"="true" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key"
// CHECK-DAG: attributes #[[#STD]] = { {{.*}} "branch-target-enforcement" "guarded-control-stack" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key"

// CHECK-DAG: attributes #[[#BTI]] = { {{.*}} "branch-target-enforcement"="true" "guarded-control-stack"="false" {{.*}} "sign-return-address"="none"
// CHECK-DAG: attributes #[[#BTI]] = { {{.*}} "branch-target-enforcement"

// CHECK-DAG: attributes #[[#PAC]] = { {{.*}} "branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key"
// CHECK-DAG: attributes #[[#PAC]] = { {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key"

// CHECK-DAG: attributes #[[#PACLEAF]] = { {{.*}} "branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key"
// CHECK-DAG: attributes #[[#PACLEAF]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key"

// CHECK-DAG: attributes #[[#PACBKEY]] = { {{.*}}"branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="b_key"
// CHECK-DAG: attributes #[[#PACBKEY]] = { {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="b_key"

// CHECK-DAG: attributes #[[#PACBKEYLEAF]] = { {{.*}} "branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}}"sign-return-address"="all" "sign-return-address-key"="b_key"
// CHECK-DAG: attributes #[[#PACBKEYLEAF]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="b_key"

// CHECK-DAG: attributes #[[#BTIPACLEAF]] = { {{.*}}"branch-target-enforcement"="true" "guarded-control-stack"="false" {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key"
// CHECK-DAG: attributes #[[#BTIPACLEAF]] = { {{.*}} "branch-target-enforcement" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key"


// CHECK-DAG: attributes #[[#PAUTHLR]] = { {{.*}}"branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="a_key"
// CHECK-DAG: attributes #[[#PAUTHLR]] = { {{.*}} "branch-protection-pauth-lr" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="a_key"

// CHECK-DAG: attributes #[[#PAUTHLR_BKEY]] = { {{.*}}"branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="b_key"
// CHECK-DAG: attributes #[[#PAUTHLR_BKEY]] = { {{.*}} "branch-protection-pauth-lr" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="b_key"

// CHECK-DAG: attributes #[[#PAUTHLR_LEAF]] = { {{.*}}"branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="false" "guarded-control-stack"="false" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key"
// CHECK-DAG: attributes #[[#PAUTHLR_LEAF]] = { {{.*}} "branch-protection-pauth-lr" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key"

// CHECK-DAG: attributes #[[#PAUTHLR_BTI]] = { {{.*}}"branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="true" "guarded-control-stack"="false" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="a_key"
// CHECK-DAG: attributes #[[#PAUTHLR_BTI]] = { {{.*}} "branch-protection-pauth-lr" {{.*}}"branch-target-enforcement" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="a_key"

// CHECK-DAG: attributes #[[#GCS]] = { {{.*}}"branch-target-enforcement"="false" "guarded-control-stack"="true" {{.*}} "sign-return-address"="none"
// CHECK-DAG: attributes #[[#GCS]] = { {{.*}} "guarded-control-stack"
23 changes: 23 additions & 0 deletions clang/test/CodeGen/aarch64-inlineasm-ios.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// REQUIRES: aarch64-registered-target
// RUN: %clang_cc1 -triple arm64-apple-ios -S -o - %s | FileCheck %s

// CHECK: _restartable_function:
// CHECK-NEXT: ldr x11, [x0]
// CHECK-NEXT: add x11, x11, #1
// CHECK-NEXT: str x11, [x0]
// CHECK-NEXT: Ltmp0:
// CHECK-NEXT: b Ltmp0
// CHECK-NEXT: LExit_restartable_function:
// CHECK-NEXT: ret
asm(".align 4\n"
" .text\n"
" .private_extern _restartable_function\n"
"_restartable_function:\n"
" ldr x11, [x0]\n"
" add x11, x11, #1\n"
" str x11, [x0]\n"
"1:\n"
" b 1b\n"
"LExit_restartable_function:\n"
" ret\n"
);
12 changes: 9 additions & 3 deletions clang/test/CodeGen/aarch64-sign-return-address.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,15 @@

// CHECK-LABEL: @foo() #[[#ATTR:]]

// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address"
// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address-key"
// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "branch-target-enforcement"
// NONE-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address"
// NONE-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address-key"
// NONE-NOT: attributes #[[#ATTR]] = { {{.*}} "branch-target-enforcement"

// ALL: attributes #[[#ATTR]] = { {{.*}} "sign-return-address"
// PART: attributes #[[#ATTR]] = { {{.*}} "sign-return-address-key"="a_key"
// B-KEY: attributes #[[#ATTR]] = { {{.*}} "sign-return-address-key"="b_key"
// BTE: attributes #[[#ATTR]] = { {{.*}} "branch-target-enforcement"


// Check module attributes

Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/aarch64-targetattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ void minusarch() {}
// CHECK: attributes #[[ATTR12]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+sve" }
// CHECK: attributes #[[ATTR13]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16" }
// CHECK: attributes #[[ATTR14]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-n1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" }
// CHECK: attributes #[[ATTR15]] = { noinline nounwind optnone "branch-protection-pauth-lr"="false" "branch-target-enforcement"="true" "guarded-control-stack"="true" "no-trapping-math"="true" "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-n1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" }
// CHECK: attributes #[[ATTR15]] = { noinline nounwind optnone "branch-target-enforcement" "guarded-control-stack" "no-trapping-math"="true" "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-n1" "target-features"="+aes,+bf16,+complxnum,+crc,+dotprod,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" }
// CHECK: attributes #[[ATTR16]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
// CHECK: attributes #[[ATTR17]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-v9.3a" }
//.
Expand Down
12 changes: 6 additions & 6 deletions clang/test/CodeGen/arm-branch-protection-attr-1.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ __attribute__((target("branch-protection=pac-ret+leaf"))) void leaf() {}
__attribute__((target("branch-protection=pac-ret+leaf+bti"))) void btileaf() {}
// CHECK: define{{.*}} void @btileaf() #[[#BTIPACLEAF:]]

// CHECK-DAG: attributes #[[#NONE]] = { {{.*}} "branch-target-enforcement"="false" {{.*}} "sign-return-address"="none"
// CHECK-DAG: attributes #[[#NONE]] = { {{.*}}

// CHECK-DAG: attributes #[[#STD]] = { {{.*}} "branch-target-enforcement"="true" {{.*}} "sign-return-address"="non-leaf"
// CHECK-DAG: attributes #[[#STD]] = { {{.*}} "branch-target-enforcement" {{.*}} "sign-return-address"="non-leaf"

// CHECK-DAG: attributes #[[#BTI]] = { {{.*}} "branch-target-enforcement"="true" {{.*}} "sign-return-address"="none"
// CHECK-DAG: attributes #[[#BTI]] = { {{.*}} "branch-target-enforcement"

// CHECK-DAG: attributes #[[#PAC]] = { {{.*}} "branch-target-enforcement"="false" {{.*}} "sign-return-address"="non-leaf"
// CHECK-DAG: attributes #[[#PAC]] = { {{.*}} "sign-return-address"="non-leaf"

// CHECK-DAG: attributes #[[#PACLEAF]] = { {{.*}} "branch-target-enforcement"="false" {{.*}}"sign-return-address"="all"
// CHECK-DAG: attributes #[[#PACLEAF]] = { {{.*}} "sign-return-address"="all"

// CHECK-DAG: attributes #[[#BTIPACLEAF]] = { {{.*}}"branch-target-enforcement"="true" {{.*}} "sign-return-address"="all"
// CHECK-DAG: attributes #[[#BTIPACLEAF]] = { {{.*}} "branch-target-enforcement" {{.*}} "sign-return-address"="all"
13 changes: 9 additions & 4 deletions clang/test/CodeGen/arm-branch-protection-attr-2.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@
// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key %s | FileCheck %s --check-prefix=CHECK --check-prefix=PART
// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -S -emit-llvm -o - -mbranch-protection=bti %s | FileCheck %s --check-prefix=CHECK --check-prefix=BTE

// Check there are no branch protection function attributes
// Check there are branch protection function attributes

// CHECK-LABEL: @foo() #[[#ATTR:]]

// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address"
// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address-key"
// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "branch-target-enforcement"
// NONE-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address"
// NONE-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address-key"
// NONE-NOT: attributes #[[#ATTR]] = { {{.*}} "branch-target-enforcement"

// ALL: attributes #[[#ATTR]] = { {{.*}} "sign-return-address"="all"
// PART: attributes #[[#ATTR]] = { {{.*}} "sign-return-address"="non-leaf"
// BTE: attributes #[[#ATTR]] = { {{.*}} "branch-target-enforcement"


// Check module attributes

Expand Down
119 changes: 0 additions & 119 deletions clang/test/CodeGen/builtins-nvptx-native-half-type-err.c

This file was deleted.

117 changes: 117 additions & 0 deletions clang/test/CodeGen/builtins-nvptx-native-half-type-native.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// REQUIRES: nvptx-registered-target
//
// RUN: %clang_cc1 -ffp-contract=off -triple nvptx-unknown-unknown -target-cpu \
// RUN: sm_86 -target-feature +ptx72 -fcuda-is-device -x cuda -emit-llvm -o - %s \
// RUN: | FileCheck %s

#define __device__ __attribute__((device))
typedef __fp16 __fp16v2 __attribute__((ext_vector_type(2)));

// CHECK: call half @llvm.nvvm.ex2.approx.f16(half {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.ex2.approx.f16x2(<2 x half> {{.*}})
// CHECK: call half @llvm.nvvm.fma.rn.relu.f16(half {{.*}}, half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fma.rn.ftz.relu.f16(half {{.*}}, half {{.*}}, half {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fma.rn.relu.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fma.rn.ftz.relu.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call half @llvm.nvvm.fma.rn.ftz.f16(half {{.*}}, half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fma.rn.sat.f16(half {{.*}}, half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fma.rn.ftz.sat.f16(half {{.*}}, half {{.*}}, half {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fma.rn.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fma.rn.ftz.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fma.rn.sat.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fma.rn.ftz.sat.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call half @llvm.nvvm.fmin.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmin.ftz.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmin.nan.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmin.ftz.nan.f16(half {{.*}}, half {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmin.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmin.ftz.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmin.nan.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmin.ftz.nan.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call half @llvm.nvvm.fmin.xorsign.abs.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmin.ftz.xorsign.abs.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmin.nan.xorsign.abs.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmin.ftz.nan.xorsign.abs.f16(half {{.*}}, half {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmin.xorsign.abs.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmin.ftz.xorsign.abs.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmin.nan.xorsign.abs.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmin.ftz.nan.xorsign.abs.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call half @llvm.nvvm.fmax.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmax.ftz.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmax.nan.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmax.ftz.nan.f16(half {{.*}}, half {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmax.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmax.ftz.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmax.nan.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmax.ftz.nan.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call half @llvm.nvvm.fmax.xorsign.abs.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmax.ftz.xorsign.abs.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmax.nan.xorsign.abs.f16(half {{.*}}, half {{.*}})
// CHECK: call half @llvm.nvvm.fmax.ftz.nan.xorsign.abs.f16(half {{.*}}, half {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmax.xorsign.abs.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmax.ftz.xorsign.abs.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmax.nan.xorsign.abs.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call <2 x half> @llvm.nvvm.fmax.ftz.nan.xorsign.abs.f16x2(<2 x half> {{.*}}, <2 x half> {{.*}})
// CHECK: call half @llvm.nvvm.ldg.global.f.f16.p0(ptr {{.*}}, i32 2)
// CHECK: call <2 x half> @llvm.nvvm.ldg.global.f.v2f16.p0(ptr {{.*}}, i32 4)
// CHECK: call half @llvm.nvvm.ldu.global.f.f16.p0(ptr {{.*}}, i32 2)
// CHECK: call <2 x half> @llvm.nvvm.ldu.global.f.v2f16.p0(ptr {{.*}}, i32 4)
__device__ void nvvm_native_half_types(void *a, void*b, void*c, __fp16* out) {
__fp16v2 resv2 = {0, 0};
*out += __nvvm_ex2_approx_f16(*(__fp16 *)a);
resv2 = __nvvm_ex2_approx_f16x2(*(__fp16v2*)a);

*out += __nvvm_fma_rn_relu_f16(*(__fp16*)a, *(__fp16*)b, *(__fp16*)c);
*out += __nvvm_fma_rn_ftz_relu_f16(*(__fp16*)a, *(__fp16*)b, *(__fp16 *)c);
resv2 += __nvvm_fma_rn_relu_f16x2(*(__fp16v2*)a, *(__fp16v2*)b, *(__fp16v2*)c);
resv2 += __nvvm_fma_rn_ftz_relu_f16x2(*(__fp16v2*)a, *(__fp16v2*)b, *(__fp16v2*)c);
*out += __nvvm_fma_rn_ftz_f16(*(__fp16*)a, *(__fp16*)b, *(__fp16*)c);
*out += __nvvm_fma_rn_sat_f16(*(__fp16*)a, *(__fp16*)b, *(__fp16*)c);
*out += __nvvm_fma_rn_ftz_sat_f16(*(__fp16*)a, *(__fp16*)b, *(__fp16*)c);
resv2 += __nvvm_fma_rn_f16x2(*(__fp16v2*)a, *(__fp16v2*)b, *(__fp16v2*)c);
resv2 += __nvvm_fma_rn_ftz_f16x2(*(__fp16v2*)a, *(__fp16v2*)b, *(__fp16v2*)c);
resv2 += __nvvm_fma_rn_sat_f16x2(*(__fp16v2*)a, *(__fp16v2*)b, *(__fp16v2*)c);
resv2 += __nvvm_fma_rn_ftz_sat_f16x2(*(__fp16v2*)a, *(__fp16v2*)b, *(__fp16v2*)c);

*out += __nvvm_fmin_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmin_ftz_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmin_nan_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmin_ftz_nan_f16(*(__fp16*)a, *(__fp16*)b);
resv2 += __nvvm_fmin_f16x2(*(__fp16v2*)a , *(__fp16v2*)b);
resv2 += __nvvm_fmin_ftz_f16x2(*(__fp16v2*)a , *(__fp16v2*)b);
resv2 += __nvvm_fmin_nan_f16x2(*(__fp16v2*)a , *(__fp16v2*)b);
resv2 += __nvvm_fmin_ftz_nan_f16x2(*(__fp16v2*)a , *(__fp16v2*)b);
*out += __nvvm_fmin_xorsign_abs_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmin_ftz_xorsign_abs_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmin_nan_xorsign_abs_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmin_ftz_nan_xorsign_abs_f16(*(__fp16*)a, *(__fp16*)b);
resv2 += __nvvm_fmin_xorsign_abs_f16x2(*(__fp16v2*)a, *(__fp16v2*)b);
resv2 += __nvvm_fmin_ftz_xorsign_abs_f16x2(*(__fp16v2*)a, *(__fp16v2*)b);
resv2 += __nvvm_fmin_nan_xorsign_abs_f16x2(*(__fp16v2*)a, *(__fp16v2*)b);
resv2 += __nvvm_fmin_ftz_nan_xorsign_abs_f16x2(*(__fp16v2*)a, *(__fp16v2*)b);

*out += __nvvm_fmax_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmax_ftz_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmax_nan_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmax_ftz_nan_f16(*(__fp16*)a, *(__fp16*)b);
resv2 += __nvvm_fmax_f16x2(*(__fp16v2*)a , *(__fp16v2*)b);
resv2 += __nvvm_fmax_ftz_f16x2(*(__fp16v2*)a , *(__fp16v2*)b);
resv2 += __nvvm_fmax_nan_f16x2(*(__fp16v2*)a , *(__fp16v2*)b);
resv2 += __nvvm_fmax_ftz_nan_f16x2(*(__fp16v2*)a , *(__fp16v2*)b);
*out += __nvvm_fmax_xorsign_abs_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmax_ftz_xorsign_abs_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmax_nan_xorsign_abs_f16(*(__fp16*)a, *(__fp16*)b);
*out += __nvvm_fmax_ftz_nan_xorsign_abs_f16(*(__fp16*)a, *(__fp16*)b);
resv2 += __nvvm_fmax_xorsign_abs_f16x2(*(__fp16v2*)a, *(__fp16v2*)b);
resv2 += __nvvm_fmax_ftz_xorsign_abs_f16x2(*(__fp16v2*)a, *(__fp16v2*)b);
resv2 += __nvvm_fmax_nan_xorsign_abs_f16x2(*(__fp16v2*)a, *(__fp16v2*)b);
resv2 += __nvvm_fmax_ftz_nan_xorsign_abs_f16x2(*(__fp16v2*)a, *(__fp16v2*)b);

*out += __nvvm_ldg_h((__fp16 *)a);
resv2 += __nvvm_ldg_h2((__fp16v2 *)a);

*out += __nvvm_ldu_h((__fp16 *)a);
resv2 += __nvvm_ldu_h2((__fp16v2 *)a);

*out += resv2[0] + resv2[1];
}
31 changes: 12 additions & 19 deletions clang/test/CodeGenCXX/modules-vtable.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
// RUN: %t/M-A.cppm -o %t/M-A.pcm
// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -fmodule-file=M:A=%t/M-A.pcm \
// RUN: %t/M-B.cppm -emit-llvm -o - | FileCheck %t/M-B.cppm
// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 \
// RUN: %t/M-A.pcm -emit-llvm -o - | FileCheck %t/M-A.cppm

//--- Mod.cppm
export module Mod;
Expand All @@ -43,10 +41,9 @@ Base::~Base() {}
// CHECK: @_ZTSW3Mod4Base = constant
// CHECK: @_ZTIW3Mod4Base = constant

// With the new Itanium C++ ABI, the linkage of vtables in modules don't need to be linkonce ODR.
// CHECK-INLINE: @_ZTVW3Mod4Base = {{.*}}unnamed_addr constant
// CHECK-INLINE: @_ZTSW3Mod4Base = {{.*}}constant
// CHECK-INLINE: @_ZTIW3Mod4Base = {{.*}}constant
// CHECK-INLINE: @_ZTVW3Mod4Base = linkonce_odr {{.*}}unnamed_addr constant
// CHECK-INLINE: @_ZTSW3Mod4Base = linkonce_odr {{.*}}constant
// CHECK-INLINE: @_ZTIW3Mod4Base = linkonce_odr {{.*}}constant

module :private;
int private_use() {
Expand All @@ -61,13 +58,13 @@ int use() {
return 43;
}

// CHECK-NOT: @_ZTSW3Mod4Base
// CHECK-NOT: @_ZTIW3Mod4Base
// CHECK: @_ZTVW3Mod4Base = external
// CHECK-NOT: @_ZTSW3Mod4Base = constant
// CHECK-NOT: @_ZTIW3Mod4Base = constant
// CHECK: @_ZTVW3Mod4Base = external unnamed_addr

// CHECK-INLINE-NOT: @_ZTSW3Mod4Base
// CHECK-INLINE-NOT: @_ZTIW3Mod4Base
// CHECK-INLINE: @_ZTVW3Mod4Base = external
// CHECK-INLINE: @_ZTVW3Mod4Base = linkonce_odr {{.*}}unnamed_addr constant
// CHECK-INLINE: @_ZTSW3Mod4Base = linkonce_odr {{.*}}constant
// CHECK-INLINE: @_ZTIW3Mod4Base = linkonce_odr {{.*}}constant

// Check the case that the declaration of the key function comes from another
// module unit but the definition of the key function comes from the current
Expand All @@ -85,10 +82,6 @@ int a_use() {
return 43;
}

// CHECK: @_ZTVW1M1C = unnamed_addr constant
// CHECK: @_ZTSW1M1C = constant
// CHECK: @_ZTIW1M1C = constant

//--- M-B.cppm
export module M:B;
import :A;
Expand All @@ -100,6 +93,6 @@ int b_use() {
return 43;
}

// CHECK: @_ZTVW1M1C = external
// CHECK-NOT: @_ZTSW1M1C
// CHECK-NOT: @_ZTIW1M1C
// CHECK: @_ZTVW1M1C = unnamed_addr constant
// CHECK: @_ZTSW1M1C = constant
// CHECK: @_ZTIW1M1C = constant
47 changes: 0 additions & 47 deletions clang/test/CodeGenCXX/pr70585.cppm

This file was deleted.

2 changes: 2 additions & 0 deletions clang/test/CodeGenOpenCL/amdgpu-features-illegal.cl
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// RUN: not %clang_cc1 -triple amdgcn -target-feature +wavefrontsize32 -target-feature +wavefrontsize64 -o /dev/null %s 2>&1 | FileCheck %s
// RUN: not %clang_cc1 -triple amdgcn -target-cpu gfx1103 -target-feature +wavefrontsize32 -target-feature +wavefrontsize64 -o /dev/null %s 2>&1 | FileCheck %s
// RUN: not %clang_cc1 -triple amdgcn -target-cpu gfx900 -target-feature +wavefrontsize32 -o /dev/null %s 2>&1 | FileCheck %s --check-prefix=GFX9

// CHECK: error: invalid feature combination: 'wavefrontsize32' and 'wavefrontsize64' are mutually exclusive
// GFX9: error: option 'wavefrontsize32' cannot be specified on this target

kernel void test() {}
5 changes: 2 additions & 3 deletions clang/test/CoverageMapping/system_macro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@

// LL_CHECK: @__covrec_
// LL_W_SYS: [[PROFC:@.*__profc_.*SysTmpl.*]] =
// LL_WOSYS: [[PROFC:@.*__profc_.*SysTmpl.*]] =
// LL_W_SYS: @{{.*}}__profd_{{.*}}SysTmpl{{.*}} =
// LL_WOSYS: @{{.*}}__profd_{{.*}}SysTmpl{{.*}} =
// LL_WOSYS-NOT: SysTmpl

// LL_CHECK: @llvm.used =

Expand All @@ -21,7 +20,7 @@
template <bool f> bool SysTmpl() { return f; }
// Check SysTmpl() is instrumented or not.
// LL_W_SYS: load i64, ptr [[PROFC]],
// LL_WOSYS: load i64, ptr [[PROFC]],
// LL_WOSYS-NOT: load i64, ptr @__profc_

#else

Expand Down
17 changes: 17 additions & 0 deletions clang/test/Driver/fraw-string-literals-cxx.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: %clang -fraw-string-literals -fsyntax-only -std=c++03 %s 2>&1 | FileCheck --check-prefix=CHECK-PRE-CXX11 --allow-empty %s
// RUN: %clang -fraw-string-literals -fsyntax-only -std=gnu++03 %s 2>&1 | FileCheck --check-prefix=CHECK-PRE-CXX11 --allow-empty %s
// RUN: %clang -fno-raw-string-literals -fsyntax-only -std=c++03 %s 2>&1 | FileCheck --check-prefix=CHECK-PRE-CXX11 --allow-empty %s
// RUN: %clang -fno-raw-string-literals -fsyntax-only -std=gnu++03 %s 2>&1 | FileCheck --check-prefix=CHECK-PRE-CXX11 --allow-empty %s
// RUN: %clang -fraw-string-literals -fsyntax-only -std=c++11 %s 2>&1 | FileCheck --check-prefix=CHECK-POS %s
// RUN: %clang -fraw-string-literals -fsyntax-only -std=gnu++11 %s 2>&1 | FileCheck --check-prefix=CHECK-POS %s
// RUN: %clang -fno-raw-string-literals -fsyntax-only -std=c++11 %s 2>&1 | FileCheck --check-prefix=CHECK-NEG %s
// RUN: %clang -fno-raw-string-literals -fsyntax-only -std=gnu++11 %s 2>&1 | FileCheck --check-prefix=CHECK-NEG %s
// RUN: %clang -fraw-string-literals -fsyntax-only -std=c++20 %s 2>&1 | FileCheck --check-prefix=CHECK-POS %s
// RUN: %clang -fraw-string-literals -fsyntax-only -std=gnu++20 %s 2>&1 | FileCheck --check-prefix=CHECK-POS %s
// RUN: %clang -fno-raw-string-literals -fsyntax-only -std=c++20 %s 2>&1 | FileCheck --check-prefix=CHECK-NEG %s
// RUN: %clang -fno-raw-string-literals -fsyntax-only -std=gnu++20 %s 2>&1 | FileCheck --check-prefix=CHECK-NEG %s

// CHECK-PRE-CXX11-NOT: ignoring '-fraw-string-literals'
// CHECK-PRE-CXX11-NOT: ignoring '-fno-raw-string-literals'
// CHECK-POS: ignoring '-fraw-string-literals', which is only valid for C and C++ standards before C++11
// CHECK-NEG: ignoring '-fno-raw-string-literals', which is only valid for C and C++ standards before C++11
11 changes: 11 additions & 0 deletions clang/test/Driver/ftime-trace-sections.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ def is_before(range1, range2):

log_contents = json.loads(sys.stdin.read())
events = log_contents["traceEvents"]

instants = [event for event in events if event["name"] == "InstantiateFunction"]
codegens = [event for event in events if event["name"] == "CodeGen Function"]
opts = [event for event in events if event["name"] == "OptFunction"]
frontends = [event for event in events if event["name"] == "Frontend"]
backends = [event for event in events if event["name"] == "Backend"]

Expand Down Expand Up @@ -48,3 +51,11 @@ def is_before(range1, range2):
]
):
sys.exit("Not all Frontend section are before all Backend sections!")

# Check that entries for foo exist and are in a demangled form.
if not any(e for e in instants if "foo<int>" in e["args"]["detail"]):
sys.exit("Missing Instantiate entry for foo!")
if not any(e for e in codegens if "foo<int>" in e["args"]["detail"]):
sys.exit("Missing CodeGen entry for foo!")
if not any(e for e in opts if "foo<int>" in e["args"]["detail"]):
sys.exit("Missing Optimize entry for foo!")
4 changes: 2 additions & 2 deletions clang/test/Driver/print-supported-extensions-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@
// CHECK-NEXT: zce 1.0 'Zce' (Compressed extensions for microcontrollers)
// CHECK-NEXT: zcf 1.0 'Zcf' (Compressed Single-Precision Floating-Point Instructions)
// CHECK-NEXT: zcmop 1.0 'Zcmop' (Compressed May-Be-Operations)
// CHECK-NEXT: zcmp 1.0 'Zcmp' (sequenced instuctions for code-size reduction)
// CHECK-NEXT: zcmt 1.0 'Zcmt' (table jump instuctions for code-size reduction)
// CHECK-NEXT: zcmp 1.0 'Zcmp' (sequenced instructions for code-size reduction)
// CHECK-NEXT: zcmt 1.0 'Zcmt' (table jump instructions for code-size reduction)
// CHECK-NEXT: zba 1.0 'Zba' (Address Generation Instructions)
// CHECK-NEXT: zbb 1.0 'Zbb' (Basic Bit-Manipulation)
// CHECK-NEXT: zbc 1.0 'Zbc' (Carry-Less Multiplication)
Expand Down
7 changes: 7 additions & 0 deletions clang/test/Driver/sanitizer-ld.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,13 @@
// RUN: -static-libsan \
// RUN: | FileCheck --check-prefix=CHECK-ASAN-ANDROID-STATICLIBASAN %s
//
// RUN: %clang -### %s 2>&1 \
// RUN: --target=arm-linux-androideabi -fuse-ld=ld -fsanitize=address \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -resource-dir=%S/Inputs/resource_dir \
// RUN: -static-libasan \
// RUN: | FileCheck --check-prefix=CHECK-ASAN-ANDROID-STATICLIBASAN %s
//
// CHECK-ASAN-ANDROID-STATICLIBASAN: "{{(.*[^.0-9A-Z_a-z])?}}ld.lld{{(.exe)?}}"
// CHECK-ASAN-ANDROID-STATICLIBASAN: libclang_rt.asan.a"
// CHECK-ASAN-ANDROID-STATICLIBASAN-NOT: "-lpthread"
Expand Down
24 changes: 24 additions & 0 deletions clang/test/Frontend/arm-branch-protection-lto.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// REQUIRES: arm-registered-target

// RUN: %clang_cc1 -triple=thumbv7m-unknown-unknown-eabi -msign-return-address=non-leaf %s -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=SIGN
// RUN: %clang_cc1 -triple=thumbv7m-unknown-unknown-eabi -mbranch-target-enforce %s -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=BTE
// RUN: %clang_cc1 -triple=thumbv7m-unknown-unknown-eabi -mbranch-target-enforce -msign-return-address=all %s -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=ALL

// RUN: %clang_cc1 -flto -triple=thumbv7m-unknown-unknown-eabi -msign-return-address=non-leaf %s -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=SIGN
// RUN: %clang_cc1 -flto -triple=thumbv7m-unknown-unknown-eabi -mbranch-target-enforce %s -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=BTE
// RUN: %clang_cc1 -flto -triple=thumbv7m-unknown-unknown-eabi -mbranch-target-enforce -msign-return-address=all %s -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=ALL

// RUN: %clang_cc1 -flto=thin -triple=thumbv7m-unknown-unknown-eabi -msign-return-address=non-leaf %s -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=SIGN
// RUN: %clang_cc1 -flto=thin -triple=thumbv7m-unknown-unknown-eabi -mbranch-target-enforce %s -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=BTE
// RUN: %clang_cc1 -flto=thin -triple=thumbv7m-unknown-unknown-eabi -mbranch-target-enforce -msign-return-address=all %s -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=ALL

void foo() {}

// Check there are branch protection function attributes.
// CHECK-LABEL: @foo() #[[#ATTR:]]

// SIGN-NOT: attributes #[[#ATTR]] = { {{.*}} "branch-target-enforcement"
// SIGN: attributes #[[#ATTR]] = { {{.*}} "sign-return-address"="non-leaf"
// BTE-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address"
// BTE: attributes #[[#ATTR]] = { {{.*}} "branch-target-enforcement"
// ALL: attributes #[[#ATTR]] = { {{.*}} "branch-target-enforcement"{{.*}} "sign-return-address"="all"
26 changes: 25 additions & 1 deletion clang/test/Headers/float.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
// expected-no-diagnostics

/* Basic floating point conformance checks against:
- C23 Final Std.
- N1570 draft of C11 Std.
- N1256 draft of C99 Std.
- http://port70.net/~nsz/c/c89/c89-draft.html draft of C89/C90 Std.
*/
/*
C23, 5.2.5.3.3p21, pp. 25
C11, 5.2.4.2.2p11, pp. 30
C99, 5.2.4.2.2p9, pp. 25
C89, 2.2.4.2
Expand Down Expand Up @@ -225,6 +227,22 @@
_Static_assert(_Generic(INFINITY, float : 1, default : 0), ""); // finite-warning {{use of infinity via a macro is undefined behavior due to the currently enabled floating-point options}}
_Static_assert(_Generic(NAN, float : 1, default : 0), ""); // finite-warning {{use of NaN is undefined behavior due to the currently enabled floating-point options}} \
finite-warning {{use of NaN via a macro is undefined behavior due to the currently enabled floating-point options}}

#ifndef FLT_NORM_MAX
#error "Mandatory macro FLT_NORM_MAX is missing."
#else
_Static_assert(FLT_NORM_MAX >= 1.0E+37F, "Mandatory macro FLT_NORM_MAX is invalid.");
#endif
#ifndef DBL_NORM_MAX
#error "Mandatory macro DBL_NORM_MAX is missing."
#else
_Static_assert(DBL_NORM_MAX >= 1.0E+37, "Mandatory macro DBL_NORM_MAX is invalid.");
#endif
#ifndef LDBL_NORM_MAX
#error "Mandatory macro LDBL_NORM_MAX is missing."
#else
_Static_assert(LDBL_NORM_MAX >= 1.0E+37L, "Mandatory macro LDBL_NORM_MAX is invalid.");
#endif
#else
#ifdef INFINITY
#error "Macro INFINITY should not be defined."
Expand Down Expand Up @@ -271,8 +289,14 @@ _Static_assert(FLT_MAX_10_EXP == __FLT_MAX_10_EXP__, "");
_Static_assert(DBL_MAX_10_EXP == __DBL_MAX_10_EXP__, "");
_Static_assert(LDBL_MAX_10_EXP == __LDBL_MAX_10_EXP__, "");

#if (__STDC_VERSION__ >= 202311L || !defined(__STRICT_ANSI__)) && __FINITE_MATH_ONLY__ == 0
#if __STDC_VERSION__ >= 202311L || !defined(__STRICT_ANSI__)
_Static_assert(FLT_NORM_MAX == __FLT_NORM_MAX__, "");
_Static_assert(DBL_NORM_MAX == __DBL_NORM_MAX__, "");
_Static_assert(LDBL_NORM_MAX == __LDBL_NORM_MAX__, "");

#if __FINITE_MATH_ONLY__ == 0
// Ensure INFINITY and NAN are suitable for use in a constant expression.
float f1 = INFINITY;
float f2 = NAN;
#endif
#endif
304 changes: 304 additions & 0 deletions clang/test/InstallAPI/reexport-with-linker-symbols.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,304 @@
; RUN: rm -rf %t
; RUN: split-file %s %t

; RUN: yaml2obj %t/umbrella.yaml -o %t/System/Library/Frameworks/Umbrella.framework/Umbrella

; RUN: clang-installapi -target arm64-apple-macosx14 -install_name \
; RUN: /System/Library/Frameworks/Umbrella.framework/Versions/A/Umbrella \
; RUN: --verify-against=%t/System/Library/Frameworks/Umbrella.framework/Umbrella \
; RUN: -L%t/usr/lib -F%t/System/Library/Frameworks \
; RUN: %t/System/Library/Frameworks/Umbrella.framework --verify-mode=Pedantic -reexport-lBar \
; RUN: -o %t/Umbrella.tbd 2>&1 | FileCheck -allow-empty %s
; RUN: llvm-readtapi -compare %t/Umbrella.tbd %t/expected.tbd 2>&1 | FileCheck -allow-empty %s

; CHECK-NOT: error
; CHECK-NOT: warning

;--- System/Library/Frameworks/Umbrella.framework/Headers/Umbrella.h
extern const char ld_previous __asm("$ld$previous$/usr/lib/libLdPreviousBindPrevious.1.dylib$$1$11.0$16.0$_function$");
extern void function();

;--- umbrella.yaml
--- !mach-o
FileHeader:
magic: 0xFEEDFACF
cputype: 0x100000C
cpusubtype: 0x0
filetype: 0x6
ncmds: 16
sizeofcmds: 856
flags: 0x85
reserved: 0x0
LoadCommands:
- cmd: LC_SEGMENT_64
cmdsize: 312
segname: __TEXT
vmaddr: 0
vmsize: 16384
fileoff: 0
filesize: 16384
maxprot: 5
initprot: 5
nsects: 3
flags: 0
Sections:
- sectname: __text
segname: __TEXT
addr: 0x3FB0
size: 4
offset: 0x3FB0
align: 2
reloff: 0x0
nreloc: 0
flags: 0x80000400
reserved1: 0x0
reserved2: 0x0
reserved3: 0x0
content: C0035FD6
- sectname: __const
segname: __TEXT
addr: 0x3FB4
size: 1
offset: 0x3FB4
align: 0
reloff: 0x0
nreloc: 0
flags: 0x0
reserved1: 0x0
reserved2: 0x0
reserved3: 0x0
content: '00'
- sectname: __unwind_info
segname: __TEXT
addr: 0x3FB8
size: 72
offset: 0x3FB8
align: 2
reloff: 0x0
nreloc: 0
flags: 0x0
reserved1: 0x0
reserved2: 0x0
reserved3: 0x0
content: 010000001C000000000000001C000000000000001C00000002000000B03F00003400000034000000B53F00000000000034000000030000000C000100100001000000000000000002
- cmd: LC_SEGMENT_64
cmdsize: 72
segname: __LINKEDIT
vmaddr: 16384
vmsize: 16384
fileoff: 16384
filesize: 584
maxprot: 1
initprot: 1
nsects: 0
flags: 0
- cmd: LC_ID_DYLIB
cmdsize: 96
dylib:
name: 24
timestamp: 1
current_version: 0
compatibility_version: 0
Content: '/System/Library/Frameworks/Umbrella.framework/Versions/A/Umbrella'
ZeroPadBytes: 7
- cmd: LC_DYLD_CHAINED_FIXUPS
cmdsize: 16
dataoff: 16384
datasize: 48
- cmd: LC_DYLD_EXPORTS_TRIE
cmdsize: 16
dataoff: 16432
datasize: 104
- cmd: LC_SYMTAB
cmdsize: 24
symoff: 16560
nsyms: 2
stroff: 16592
strsize: 96
- cmd: LC_DYSYMTAB
cmdsize: 80
ilocalsym: 0
nlocalsym: 0
iextdefsym: 0
nextdefsym: 2
iundefsym: 2
nundefsym: 0
tocoff: 0
ntoc: 0
modtaboff: 0
nmodtab: 0
extrefsymoff: 0
nextrefsyms: 0
indirectsymoff: 0
nindirectsyms: 0
extreloff: 0
nextrel: 0
locreloff: 0
nlocrel: 0
- cmd: LC_UUID
cmdsize: 24
uuid: CCD7F304-D97B-3521-A980-CC936CCD34E8
- cmd: LC_BUILD_VERSION
cmdsize: 32
platform: 1
minos: 917504
sdk: 983040
ntools: 1
Tools:
- tool: 3
version: 62525440
- cmd: LC_SOURCE_VERSION
cmdsize: 16
version: 0
- cmd: LC_SEGMENT_SPLIT_INFO
cmdsize: 16
dataoff: 16536
datasize: 16
- cmd: LC_REEXPORT_DYLIB
cmdsize: 48
dylib:
name: 24
timestamp: 2
current_version: 65536
compatibility_version: 65536
Content: '/usr/lib/libBar.dylib'
ZeroPadBytes: 3
- cmd: LC_LOAD_DYLIB
cmdsize: 56
dylib:
name: 24
timestamp: 2
current_version: 88539136
compatibility_version: 65536
Content: '/usr/lib/libSystem.B.dylib'
ZeroPadBytes: 6
- cmd: LC_FUNCTION_STARTS
cmdsize: 16
dataoff: 16552
datasize: 8
- cmd: LC_DATA_IN_CODE
cmdsize: 16
dataoff: 16560
datasize: 0
- cmd: LC_CODE_SIGNATURE
cmdsize: 16
dataoff: 16688
datasize: 280
LinkEditData:
ExportTrie:
TerminalSize: 0
NodeOffset: 0
Name: ''
Flags: 0x0
Address: 0x0
Other: 0x0
ImportName: ''
Children:
- TerminalSize: 3
NodeOffset: 94
Name: '$ld$previous$/usr/lib/libLdPreviousBindPrevious.1.dylib$$1$11.0$16.0$_function$'
Flags: 0x0
Address: 0x3FB4
Other: 0x0
ImportName: ''
- TerminalSize: 3
NodeOffset: 99
Name: _function
Flags: 0x0
Address: 0x3FB0
Other: 0x0
ImportName: ''
NameList:
- n_strx: 2
n_type: 0xF
n_sect: 2
n_desc: 0
n_value: 16308
- n_strx: 82
n_type: 0xF
n_sect: 1
n_desc: 0
n_value: 16304
StringTable:
- ' '
- '$ld$previous$/usr/lib/libLdPreviousBindPrevious.1.dylib$$1$11.0$16.0$_function$'
- _function
- ''
- ''
- ''
- ''
FunctionStarts: [ 0x3FB0 ]
ChainedFixups: [ 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x2C, 0x0,
0x0, 0x0, 0x2C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
...

;--- /usr/lib/libBar.dylib
{
"main_library": {
"exported_symbols": [
{
"text": {
"global": [
"$ld$previous$/usr/lib/libLdPreviousBindPrevious.1.dylib$$1$11.0$16.0$_function$"
]
}
}
],
"flags": [
{
"attributes": [
"not_app_extension_safe"
]
}
],
"install_names": [
{
"name": "/usr/lib/libBar.dylib"
}
],
"target_info": [
{
"min_deployment": "13",
"target": "arm64-macos"
}
]
},
"tapi_tbd_version": 5
}

;--- expected.tbd
{
"main_library": {
"compatibility_versions": [ { "version": "0" } ],
"current_versions": [ { "version": "0" } ],
"exported_symbols": [
{
"data": {
"global": [
"$ld$previous$/usr/lib/libLdPreviousBindPrevious.1.dylib$$1$11.0$16.0$_function$"
]
},
"text": { "global": [ "_function" ] }
}
],
"flags": [
{ "attributes": [ "not_app_extension_safe" ] }
],
"install_names": [
{ "name": "/System/Library/Frameworks/Umbrella.framework/Versions/A/Umbrella" }
],
"reexported_libraries": [
{ "names": [ "/usr/lib/libBar.dylib" ] }
],
"target_info": [
{
"min_deployment": "14",
"target": "arm64-macos"
}
]
},
"tapi_tbd_version": 5
}
44 changes: 44 additions & 0 deletions clang/test/Lexer/raw-string-ext.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// RUN: %clang_cc1 -fsyntax-only -std=gnu11 -verify=supported %s
// RUN: %clang_cc1 -fsyntax-only -std=c11 -DUNICODE -fraw-string-literals -verify=supported %s
// RUN: %clang_cc1 -fsyntax-only -std=gnu89 -verify=unsupported %s
// RUN: %clang_cc1 -fsyntax-only -std=c11 -DUNICODE -verify=unsupported %s
// RUN: %clang_cc1 -fsyntax-only -std=gnu11 -DUNICODE -fno-raw-string-literals -verify=unsupported %s

// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++03 -verify=unsupported,cxx-unsupported %s
// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=gnu++03 -verify=unsupported,cxx-unsupported %s
// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++03 -fraw-string-literals -verify=supported %s
// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=gnu++03 -fraw-string-literals -verify=supported %s
// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++11 -DUNICODE -verify=supported,cxx %s
// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=gnu++11 -DUNICODE -verify=supported,cxx %s
// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++11 -DUNICODE -fraw-string-literals -verify=supported,yes %s
// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=gnu++11 -DUNICODE -fraw-string-literals -verify=supported,yes %s
// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=c++11 -DUNICODE -fno-raw-string-literals -verify=supported,no %s
// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unused -std=gnu++11 -DUNICODE -fno-raw-string-literals -verify=supported,no %s

// GCC supports raw string literals in C99 and later in '-std=gnuXY' mode; we
// additionally provide '-f[no-]raw-string-literals' to enable/disable them
// explicitly in C.
//
// We do not allow disabling raw string literals in C++ mode if they’re enabled
// by the language standard, i.e. in C++11 or later.

// Driver warnings.
// yes-warning@* {{ignoring '-fraw-string-literals'}}
// no-warning@* {{ignoring '-fno-raw-string-literals'}}

void f() {
(void) R"foo()foo"; // unsupported-error {{use of undeclared identifier 'R'}} cxx-unsupported-error {{expected ';' after expression}}
(void) LR"foo()foo"; // unsupported-error {{use of undeclared identifier 'LR'}} cxx-unsupported-error {{expected ';' after expression}}

#ifdef UNICODE
(void) uR"foo()foo"; // unsupported-error {{use of undeclared identifier 'uR'}} cxx-unsupported-error {{expected ';' after expression}}
(void) u8R"foo()foo"; // unsupported-error {{use of undeclared identifier 'u8R'}} cxx-unsupported-error {{expected ';' after expression}}
(void) UR"foo()foo"; // unsupported-error {{use of undeclared identifier 'UR'}} cxx-unsupported-error {{expected ';' after expression}}
#endif
}

// supported-error@* {{missing terminating delimiter}}
// supported-error@* {{expected expression}}
// supported-error@* {{expected ';' after top level declarator}}
#define R "bar"
const char* s = R"foo(";
Loading