18 changes: 3 additions & 15 deletions clang/include/clang/Serialization/ModuleFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -454,23 +454,11 @@ class ModuleFile {
/// by the declaration ID (-1).
const DeclOffset *DeclOffsets = nullptr;

/// Base declaration ID for declarations local to this module.
serialization::DeclID BaseDeclID = 0;

/// Remapping table for declaration IDs in this module.
ContinuousRangeMap<serialization::DeclID, int, 2> DeclRemap;

/// Mapping from the module files that this module file depends on
/// to the base declaration ID for that module as it is understood within this
/// module.
///
/// This is effectively a reverse global-to-local mapping for declaration
/// IDs, so that we can interpret a true global ID (for this translation unit)
/// as a local ID (for this module file).
llvm::DenseMap<ModuleFile *, serialization::DeclID> GlobalToLocalDeclIDs;
/// Base declaration index in ASTReader for declarations local to this module.
unsigned BaseDeclIndex = 0;

/// Array of file-level DeclIDs sorted by file.
const LocalDeclID *FileSortedDecls = nullptr;
const serialization::unaligned_decl_id_t *FileSortedDecls = nullptr;
unsigned NumFileSortedDecls = 0;

/// Array of category list location information within this
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Serialization/ModuleManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ namespace serialization {
/// Manages the set of modules loaded by an AST reader.
class ModuleManager {
/// The chain of AST files, in the order in which we started to load
/// them (this order isn't really useful for anything).
/// them.
SmallVector<std::unique_ptr<ModuleFile>, 2> Chain;

/// The chain of non-module PCH files. The first entry is the one named
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -781,7 +781,7 @@ class SymbolicRegion : public SubRegion {
: SubRegion(sreg, SymbolicRegionKind), sym(s) {
// Because pointer arithmetic is represented by ElementRegion layers,
// the base symbol here should not contain any arithmetic.
assert(s && isa<SymbolData>(s));
assert(isa_and_nonnull<SymbolData>(s));
assert(s->getType()->isAnyPointerType() ||
s->getType()->isReferenceType() ||
s->getType()->isBlockPointerType());
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Tooling/Syntax/Tokens.h
Original file line number Diff line number Diff line change
Expand Up @@ -292,9 +292,9 @@ class TokenBuffer {
/// "DECL", "(", "a", ")", ";"}
llvm::ArrayRef<syntax::Token> spelledTokens(FileID FID) const;

/// Returns the spelled Token starting at Loc, if there are no such tokens
/// Returns the spelled Token containing the Loc, if there are no such tokens
/// returns nullptr.
const syntax::Token *spelledTokenAt(SourceLocation Loc) const;
const syntax::Token *spelledTokenContaining(SourceLocation Loc) const;

/// Get all tokens that expand a macro in \p FID. For the following input
/// #define FOO B
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/ARCMigrate/TransUnbridgedCasts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ class UnbridgedCastRewriter : public RecursiveASTVisitor<UnbridgedCastRewriter>{
Stmt *parent = E;
do {
parent = StmtMap->getParentIgnoreParenImpCasts(parent);
} while (parent && isa<FullExpr>(parent));
} while (isa_and_nonnull<FullExpr>(parent));

if (ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) {
std::string note = "remove the cast and change return type of function "
Expand Down
34 changes: 34 additions & 0 deletions clang/lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,3 +360,37 @@ LLVM_DUMP_METHOD void ConceptReference::dump(raw_ostream &OS) const {
ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
P.Visit(this);
}

//===----------------------------------------------------------------------===//
// TemplateName method implementations
//===----------------------------------------------------------------------===//

// FIXME: These are actually using the TemplateArgument dumper, through
// an implicit conversion. The dump will claim this is a template argument,
// which is misleading.

LLVM_DUMP_METHOD void TemplateName::dump() const {
ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
Dumper.Visit(*this);
}

LLVM_DUMP_METHOD void TemplateName::dump(llvm::raw_ostream &OS,
const ASTContext &Context) const {
ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
Dumper.Visit(*this);
}

//===----------------------------------------------------------------------===//
// TemplateArgument method implementations
//===----------------------------------------------------------------------===//

LLVM_DUMP_METHOD void TemplateArgument::dump() const {
ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
Dumper.Visit(*this);
}

LLVM_DUMP_METHOD void TemplateArgument::dump(llvm::raw_ostream &OS,
const ASTContext &Context) const {
ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
Dumper.Visit(*this);
}
2 changes: 1 addition & 1 deletion clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1505,7 +1505,7 @@ ExpectedType ASTNodeImporter::VisitInjectedClassNameType(
// The InjectedClassNameType is created in VisitRecordDecl when the
// T->getDecl() is imported. Here we can return the existing type.
const Type *Ty = (*ToDeclOrErr)->getTypeForDecl();
assert(Ty && isa<InjectedClassNameType>(Ty));
assert(isa_and_nonnull<InjectedClassNameType>(Ty));
return QualType(Ty, 0);
}

Expand Down
93 changes: 93 additions & 0 deletions clang/lib/AST/CommentParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,31 @@ class TextTokenRetokenizer {
}
}

/// Extract a template type
bool lexTemplate(SmallString<32> &WordText) {
unsigned BracketCount = 0;
while (!isEnd()) {
const char C = peek();
WordText.push_back(C);
consumeChar();
switch (C) {
case '<': {
BracketCount++;
break;
}
case '>': {
BracketCount--;
if (!BracketCount)
return true;
break;
}
default:
break;
}
}
return false;
}

/// Add a token.
/// Returns true on success, false if there are no interesting tokens to
/// fetch from lexer.
Expand Down Expand Up @@ -149,6 +174,54 @@ class TextTokenRetokenizer {
addToken();
}

/// Extract a type argument
bool lexType(Token &Tok) {
if (isEnd())
return false;

// Save current position in case we need to rollback because the type is
// empty.
Position SavedPos = Pos;

// Consume any leading whitespace.
consumeWhitespace();
SmallString<32> WordText;
const char *WordBegin = Pos.BufferPtr;
SourceLocation Loc = getSourceLocation();

while (!isEnd()) {
const char C = peek();
// For non-whitespace characters we check if it's a template or otherwise
// continue reading the text into a word.
if (!isWhitespace(C)) {
if (C == '<') {
if (!lexTemplate(WordText))
return false;
} else {
WordText.push_back(C);
consumeChar();
}
} else {
consumeChar();
break;
}
}

const unsigned Length = WordText.size();
if (Length == 0) {
Pos = SavedPos;
return false;
}

char *TextPtr = Allocator.Allocate<char>(Length + 1);

memcpy(TextPtr, WordText.c_str(), Length + 1);
StringRef Text = StringRef(TextPtr, Length);

formTokenWithChars(Tok, Loc, WordBegin, Length, Text);
return true;
}

/// Extract a word -- sequence of non-whitespace characters.
bool lexWord(Token &Tok) {
if (isEnd())
Expand Down Expand Up @@ -304,6 +377,23 @@ Parser::parseCommandArgs(TextTokenRetokenizer &Retokenizer, unsigned NumArgs) {
return llvm::ArrayRef(Args, ParsedArgs);
}

ArrayRef<Comment::Argument>
Parser::parseThrowCommandArgs(TextTokenRetokenizer &Retokenizer,
unsigned NumArgs) {
auto *Args = new (Allocator.Allocate<Comment::Argument>(NumArgs))
Comment::Argument[NumArgs];
unsigned ParsedArgs = 0;
Token Arg;

while (ParsedArgs < NumArgs && Retokenizer.lexType(Arg)) {
Args[ParsedArgs] = Comment::Argument{
SourceRange(Arg.getLocation(), Arg.getEndLocation()), Arg.getText()};
ParsedArgs++;
}

return llvm::ArrayRef(Args, ParsedArgs);
}

BlockCommandComment *Parser::parseBlockCommand() {
assert(Tok.is(tok::backslash_command) || Tok.is(tok::at_command));

Expand Down Expand Up @@ -356,6 +446,9 @@ BlockCommandComment *Parser::parseBlockCommand() {
parseParamCommandArgs(PC, Retokenizer);
else if (TPC)
parseTParamCommandArgs(TPC, Retokenizer);
else if (Info->IsThrowsCommand)
S.actOnBlockCommandArgs(
BC, parseThrowCommandArgs(Retokenizer, Info->NumArgs));
else
S.actOnBlockCommandArgs(BC, parseCommandArgs(Retokenizer, Info->NumArgs));

Expand Down
42 changes: 34 additions & 8 deletions clang/lib/AST/DeclBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,17 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Context,
GlobalDeclID ID, std::size_t Extra) {
// Allocate an extra 8 bytes worth of storage, which ensures that the
// resulting pointer will still be 8-byte aligned.
static_assert(sizeof(unsigned) * 2 >= alignof(Decl),
"Decl won't be misaligned");
static_assert(sizeof(uint64_t) >= alignof(Decl), "Decl won't be misaligned");
void *Start = Context.Allocate(Size + Extra + 8);
void *Result = (char*)Start + 8;

unsigned *PrefixPtr = (unsigned *)Result - 2;
uint64_t *PrefixPtr = (uint64_t *)Result - 1;

// Zero out the first 4 bytes; this is used to store the owning module ID.
PrefixPtr[0] = 0;
*PrefixPtr = ID.get();

// Store the global declaration ID in the second 4 bytes.
PrefixPtr[1] = ID.get();
// We leave the upper 16 bits to store the module IDs. 48 bits should be
// sufficient to store a declaration ID.
assert(*PrefixPtr < llvm::maskTrailingOnes<uint64_t>(48));

return Result;
}
Expand All @@ -111,6 +110,29 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Ctx,
return ::operator new(Size + Extra, Ctx);
}

GlobalDeclID Decl::getGlobalID() const {
if (!isFromASTFile())
return GlobalDeclID();
// See the comments in `Decl::operator new` for details.
uint64_t ID = *((const uint64_t *)this - 1);
return GlobalDeclID(ID & llvm::maskTrailingOnes<uint64_t>(48));
}

unsigned Decl::getOwningModuleID() const {
if (!isFromASTFile())
return 0;

uint64_t ID = *((const uint64_t *)this - 1);
return ID >> 48;
}

void Decl::setOwningModuleID(unsigned ID) {
assert(isFromASTFile() && "Only works on a deserialized declaration");
uint64_t *IDAddress = (uint64_t *)this - 1;
*IDAddress &= llvm::maskTrailingOnes<uint64_t>(48);
*IDAddress |= (uint64_t)ID << 48;
}

Module *Decl::getOwningModuleSlow() const {
assert(isFromASTFile() && "Not from AST file?");
return getASTContext().getExternalSource()->getModule(getOwningModuleID());
Expand Down Expand Up @@ -1094,7 +1116,7 @@ bool Decl::isInExportDeclContext() const {
while (DC && !isa<ExportDecl>(DC))
DC = DC->getLexicalParent();

return DC && isa<ExportDecl>(DC);
return isa_and_nonnull<ExportDecl>(DC);
}

bool Decl::isInAnotherModuleUnit() const {
Expand Down Expand Up @@ -2163,3 +2185,7 @@ DependentDiagnostic *DependentDiagnostic::Create(ASTContext &C,

return DD;
}

unsigned DeclIDBase::getLocalDeclIndex() const {
return ID & llvm::maskTrailingOnes<DeclID>(32);
}
4 changes: 2 additions & 2 deletions clang/lib/AST/DeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ void LazyASTUnresolvedSet::getFromExternalSource(ASTContext &C) const {
assert(Source && "getFromExternalSource with no external source");

for (ASTUnresolvedSet::iterator I = Impl.begin(); I != Impl.end(); ++I)
I.setDecl(cast<NamedDecl>(Source->GetExternalDecl(
GlobalDeclID(reinterpret_cast<uintptr_t>(I.getDecl()) >> 2))));
I.setDecl(
cast<NamedDecl>(Source->GetExternalDecl(GlobalDeclID(I.getDeclID()))));
Impl.Decls.setLazy(false);
}

Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,7 @@ std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK,
typedef SmallVector<const ClassTemplateSpecializationDecl *, 8> SpecsTy;
SpecsTy Specs;
const DeclContext *Ctx = FD->getDeclContext();
while (Ctx && isa<NamedDecl>(Ctx)) {
while (isa_and_nonnull<NamedDecl>(Ctx)) {
const ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Ctx);
if (Spec && !Spec->isExplicitSpecialization())
Expand Down Expand Up @@ -3067,7 +3067,7 @@ Expr *Expr::IgnoreParenCasts() {

Expr *Expr::IgnoreConversionOperatorSingleStep() {
if (auto *MCE = dyn_cast<CXXMemberCallExpr>(this)) {
if (MCE->getMethodDecl() && isa<CXXConversionDecl>(MCE->getMethodDecl()))
if (isa_and_nonnull<CXXConversionDecl>(MCE->getMethodDecl()))
return MCE->getImplicitObjectArgument();
}
return this;
Expand Down
29 changes: 22 additions & 7 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2130,7 +2130,7 @@ static bool IsWeakLValue(const LValue &Value) {

static bool isZeroSized(const LValue &Value) {
const ValueDecl *Decl = GetLValueBaseDecl(Value);
if (Decl && isa<VarDecl>(Decl)) {
if (isa_and_nonnull<VarDecl>(Decl)) {
QualType Ty = Decl->getType();
if (Ty->isArrayType())
return Ty->isIncompleteType() ||
Expand Down Expand Up @@ -15209,11 +15209,21 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
APFloat &ResI = Result.getComplexFloatImag();
if (LHSReal) {
assert(!RHSReal && "Cannot have two real operands for a complex op!");
ResR = A * C;
ResI = A * D;
ResR = A;
ResI = A;
// ResR = A * C;
// ResI = A * D;
if (!handleFloatFloatBinOp(Info, E, ResR, BO_Mul, C) ||
!handleFloatFloatBinOp(Info, E, ResI, BO_Mul, D))
return false;
} else if (RHSReal) {
ResR = C * A;
ResI = C * B;
// ResR = C * A;
// ResI = C * B;
ResR = C;
ResI = C;
if (!handleFloatFloatBinOp(Info, E, ResR, BO_Mul, A) ||
!handleFloatFloatBinOp(Info, E, ResI, BO_Mul, B))
return false;
} else {
// In the fully general case, we need to handle NaNs and infinities
// robustly.
Expand Down Expand Up @@ -15289,8 +15299,13 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
APFloat &ResR = Result.getComplexFloatReal();
APFloat &ResI = Result.getComplexFloatImag();
if (RHSReal) {
ResR = A / C;
ResI = B / C;
ResR = A;
ResI = B;
// ResR = A / C;
// ResI = B / C;
if (!handleFloatFloatBinOp(Info, E, ResR, BO_Div, C) ||
!handleFloatFloatBinOp(Info, E, ResI, BO_Div, C))
return false;
} else {
if (LHSReal) {
// No real optimizations we can do here, stub out with zero.
Expand Down
119 changes: 83 additions & 36 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,15 +318,24 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
if (DiscardResult)
return this->discard(SubExpr);

std::optional<PrimType> FromT = classify(SubExpr->getType());
QualType SubExprTy = SubExpr->getType();
std::optional<PrimType> FromT = classify(SubExprTy);
std::optional<PrimType> ToT = classify(CE->getType());
if (!FromT || !ToT)
return false;

assert(isPtrType(*FromT));
assert(isPtrType(*ToT));
if (FromT == ToT)
return this->delegate(SubExpr);
if (FromT == ToT) {
if (CE->getType()->isVoidPointerType())
return this->delegate(SubExpr);

if (!this->visit(SubExpr))
return false;
if (FromT == PT_Ptr)
return this->emitPtrPtrCast(SubExprTy->isVoidPointerType(), CE);
return true;
}

if (!this->visit(SubExpr))
return false;
Expand Down Expand Up @@ -1104,14 +1113,9 @@ bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
if (!this->visit(Init))
return false;

if (FieldToInit->isBitField()) {
if (!this->emitInitBitField(T, FieldToInit, E))
return false;
} else {
if (!this->emitInitField(T, FieldToInit->Offset, E))
return false;
}
return this->emitPopPtr(E);
if (FieldToInit->isBitField())
return this->emitInitBitField(T, FieldToInit, E);
return this->emitInitField(T, FieldToInit->Offset, E);
};

auto initCompositeField = [=](const Record::Field *FieldToInit,
Expand Down Expand Up @@ -1147,9 +1151,6 @@ bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
else
FToInit = cast<CXXParenListInitExpr>(E)->getInitializedFieldInUnion();

if (!this->emitDupPtr(E))
return false;

const Record::Field *FieldToInit = R->getField(FToInit);
if (std::optional<PrimType> T = classify(Init)) {
if (!initPrimitiveField(FieldToInit, Init, *T))
Expand All @@ -1169,8 +1170,6 @@ bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
while (InitIndex < R->getNumFields() &&
R->getField(InitIndex)->Decl->isUnnamedBitField())
++InitIndex;
if (!this->emitDupPtr(E))
return false;

if (std::optional<PrimType> T = classify(Init)) {
const Record::Field *FieldToInit = R->getField(InitIndex);
Expand All @@ -1180,7 +1179,7 @@ bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
} else {
// Initializer for a direct base class.
if (const Record::Base *B = R->getBase(Init->getType())) {
if (!this->emitGetPtrBasePop(B->Offset, Init))
if (!this->emitGetPtrBase(B->Offset, Init))
return false;

if (!this->visitInitializer(Init))
Expand Down Expand Up @@ -1513,7 +1512,7 @@ bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) {
// Leave a pointer to the field on the stack.
if (F->Decl->getType()->isReferenceType())
return this->emitGetFieldPop(PT_Ptr, F->Offset, E) && maybeLoadValue();
return this->emitGetPtrField(F->Offset, E) && maybeLoadValue();
return this->emitGetPtrFieldPop(F->Offset, E) && maybeLoadValue();
}

return false;
Expand Down Expand Up @@ -1844,6 +1843,9 @@ bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator(
std::optional<PrimType> RT = classify(RHS->getType());
std::optional<PrimType> ResultT = classify(E->getType());

if (!Ctx.getLangOpts().CPlusPlus14)
return this->visit(RHS) && this->visit(LHS) && this->emitError(E);

if (!LT || !RT || !ResultT || !LHSComputationT)
return false;

Expand Down Expand Up @@ -2147,9 +2149,6 @@ bool ByteCodeExprGen<Emitter>::VisitLambdaExpr(const LambdaExpr *E) {
if (!this->emitInitField(*T, F.Offset, E))
return false;
} else {
if (!this->emitDupPtr(E))
return false;

if (!this->emitGetPtrField(F.Offset, E))
return false;

Expand Down Expand Up @@ -2846,9 +2845,6 @@ bool ByteCodeExprGen<Emitter>::visitZeroRecordInitializer(const Record *R,
continue;
}

// TODO: Add GetPtrFieldPop and get rid of this dup.
if (!this->emitDupPtr(E))
return false;
if (!this->emitGetPtrField(Field.Offset, E))
return false;

Expand Down Expand Up @@ -3218,9 +3214,18 @@ bool ByteCodeExprGen<Emitter>::visitAPValue(const APValue &Val,
return this->emitConst(Val.getInt(), ValType, E);

if (Val.isLValue()) {
if (Val.isNullPointer())
return this->emitNull(ValType, nullptr, E);
APValue::LValueBase Base = Val.getLValueBase();
if (const Expr *BaseExpr = Base.dyn_cast<const Expr *>())
return this->visit(BaseExpr);
else if (const auto *VD = Base.dyn_cast<const ValueDecl *>()) {
return this->visitDeclRef(VD, E);
}
} else if (Val.isMemberPointer()) {
if (const ValueDecl *MemberDecl = Val.getMemberPointerDecl())
return this->emitGetMemberPtr(MemberDecl, E);
return this->emitNullMemberPtr(nullptr, E);
}

return false;
Expand All @@ -3229,15 +3234,15 @@ bool ByteCodeExprGen<Emitter>::visitAPValue(const APValue &Val,
template <class Emitter>
bool ByteCodeExprGen<Emitter>::visitAPValueInitializer(const APValue &Val,
const Expr *E) {

if (Val.isStruct()) {
const Record *R = this->getRecord(E->getType());
assert(R);

for (unsigned I = 0, N = Val.getStructNumFields(); I != N; ++I) {
const APValue &F = Val.getStructField(I);
const Record::Field *RF = R->getField(I);

if (F.isInt() || F.isLValue()) {
if (F.isInt() || F.isLValue() || F.isMemberPointer()) {
PrimType T = classifyPrim(RF->Decl->getType());
if (!this->visitAPValue(F, T, E))
return false;
Expand All @@ -3249,8 +3254,6 @@ bool ByteCodeExprGen<Emitter>::visitAPValueInitializer(const APValue &Val,
PrimType ElemT = classifyPrim(ArrType->getElementType());
assert(ArrType);

if (!this->emitDupPtr(E))
return false;
if (!this->emitGetPtrField(RF->Offset, E))
return false;

Expand All @@ -3263,11 +3266,28 @@ bool ByteCodeExprGen<Emitter>::visitAPValueInitializer(const APValue &Val,

if (!this->emitPopPtr(E))
return false;
} else if (F.isStruct() || F.isUnion()) {
if (!this->emitGetPtrField(RF->Offset, E))
return false;
if (!this->visitAPValueInitializer(F, E))
return false;
if (!this->emitPopPtr(E))
return false;
} else {
assert(false && "I don't think this should be possible");
}
}
return true;
} else if (Val.isUnion()) {
const FieldDecl *UnionField = Val.getUnionField();
const Record *R = this->getRecord(UnionField->getParent());
assert(R);
const APValue &F = Val.getUnionValue();
const Record::Field *RF = R->getField(UnionField);
PrimType T = classifyPrim(RF->Decl->getType());
if (!this->visitAPValue(F, T, E))
return false;
return this->emitInitElem(T, 0, E);
}
// TODO: Other types.

Expand Down Expand Up @@ -3819,6 +3839,21 @@ bool ByteCodeExprGen<Emitter>::VisitComplexUnaryOperator(
// we sometimes have to do the lvalue-to-rvalue conversion here manually.
return this->emitArrayElemPop(classifyPrim(E->getType()), 1, E);

case UO_Not: // ~x
if (!this->visit(SubExpr))
return false;
// Negate the imaginary component.
if (!this->emitArrayElem(ElemT, 1, E))
return false;
if (!this->emitNeg(ElemT, E))
return false;
if (!this->emitInitElem(ElemT, 1, E))
return false;
return DiscardResult ? this->emitPopPtr(E) : true;

case UO_Extension:
return this->delegate(SubExpr);

default:
return this->emitInvalid(E);
}
Expand All @@ -3827,12 +3862,10 @@ bool ByteCodeExprGen<Emitter>::VisitComplexUnaryOperator(
}

template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
bool ByteCodeExprGen<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
if (DiscardResult)
return true;

const auto *D = E->getDecl();

if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
return this->emitConst(ECD->getInitVal(), E);
} else if (const auto *BD = dyn_cast<BindingDecl>(D)) {
Expand Down Expand Up @@ -3888,6 +3921,14 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
if (IsPtr)
return this->emitGetThisFieldPtr(Offset, E);
return this->emitGetPtrThisField(Offset, E);
} else if (const auto *DRE = dyn_cast<DeclRefExpr>(E);
DRE && DRE->refersToEnclosingVariableOrCapture()) {
if (const auto *VD = dyn_cast<VarDecl>(D); VD && VD->isInitCapture()) {
if (!this->visitVarDecl(cast<VarDecl>(D)))
return false;
// Retry.
return this->visitDeclRef(D, E);
}
}

// Try to lazily visit (or emit dummy pointers for) declarations
Expand All @@ -3900,7 +3941,7 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
if (!this->visitVarDecl(VD))
return false;
// Retry.
return this->VisitDeclRefExpr(E);
return this->visitDeclRef(VD, E);
}
}
} else {
Expand All @@ -3910,7 +3951,7 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
if (!this->visitVarDecl(VD))
return false;
// Retry.
return this->VisitDeclRefExpr(E);
return this->visitDeclRef(VD, E);
}
}

Expand All @@ -3927,7 +3968,15 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
return true;
}

return this->emitInvalidDeclRef(E, E);
if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
return this->emitInvalidDeclRef(DRE, E);
return false;
}

template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
const auto *D = E->getDecl();
return this->visitDeclRef(D, E);
}

template <class Emitter>
Expand Down Expand Up @@ -4167,8 +4216,6 @@ bool ByteCodeExprGen<Emitter>::emitRecordDestruction(const Record *R) {
for (const Record::Field &Field : llvm::reverse(R->fields())) {
const Descriptor *D = Field.Desc;
if (!D->isPrimitive() && !D->isPrimitiveArray()) {
if (!this->emitDupPtr(SourceInfo{}))
return false;
if (!this->emitGetPtrField(Field.Offset, SourceInfo{}))
return false;
if (!this->emitDestruction(D))
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/Interp/ByteCodeExprGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
/// Visit an APValue.
bool visitAPValue(const APValue &Val, PrimType ValType, const Expr *E);
bool visitAPValueInitializer(const APValue &Val, const Expr *E);
/// Visit the given decl as if we have a reference to it.
bool visitDeclRef(const ValueDecl *D, const Expr *E);

/// Visits an expression and converts it to a boolean.
bool visitBool(const Expr *E);
Expand Down
35 changes: 19 additions & 16 deletions clang/lib/AST/Interp/EvalEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ void EvalEmitter::cleanup() { S.cleanup(); }
EvaluationResult EvalEmitter::interpretExpr(const Expr *E,
bool ConvertResultToRValue) {
S.setEvalLocation(E->getExprLoc());
this->ConvertResultToRValue = ConvertResultToRValue;
this->ConvertResultToRValue = ConvertResultToRValue && !isa<ConstantExpr>(E);
this->CheckFullyInitialized = isa<ConstantExpr>(E);
EvalResult.setSource(E);

if (!this->visitExpr(E)) {
Expand All @@ -55,10 +56,14 @@ EvaluationResult EvalEmitter::interpretExpr(const Expr *E,
EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD,
bool CheckFullyInitialized) {
this->CheckFullyInitialized = CheckFullyInitialized;
this->ConvertResultToRValue =
VD->getAnyInitializer() &&
(VD->getAnyInitializer()->getType()->isAnyComplexType() ||
VD->getAnyInitializer()->getType()->isVectorType());

if (const Expr *Init = VD->getAnyInitializer()) {
QualType T = VD->getType();
this->ConvertResultToRValue = !Init->isGLValue() && !T->isPointerType() &&
!T->isObjCObjectPointerType();
} else
this->ConvertResultToRValue = false;

EvalResult.setSource(VD);

if (!this->visitDecl(VD) && EvalResult.empty())
Expand Down Expand Up @@ -137,6 +142,10 @@ template <> bool EvalEmitter::emitRet<PT_Ptr>(const SourceInfo &Info) {
return true;

const Pointer &Ptr = S.Stk.pop<Pointer>();

if (CheckFullyInitialized && !EvalResult.checkFullyInitialized(S, Ptr))
return false;

// Implicitly convert lvalue to rvalue, if requested.
if (ConvertResultToRValue) {
if (std::optional<APValue> V = Ptr.toRValue(Ctx)) {
Expand All @@ -145,17 +154,7 @@ template <> bool EvalEmitter::emitRet<PT_Ptr>(const SourceInfo &Info) {
return false;
}
} else {
if (CheckFullyInitialized) {
if (!EvalResult.checkFullyInitialized(S, Ptr))
return false;

std::optional<APValue> RValueResult = Ptr.toRValue(Ctx);
if (!RValueResult)
return false;
EvalResult.setValue(*RValueResult);
} else {
EvalResult.setValue(Ptr.toAPValue());
}
EvalResult.setValue(Ptr.toAPValue());
}

return true;
Expand All @@ -175,6 +174,10 @@ bool EvalEmitter::emitRetVoid(const SourceInfo &Info) {

bool EvalEmitter::emitRetValue(const SourceInfo &Info) {
const auto &Ptr = S.Stk.pop<Pointer>();

if (CheckFullyInitialized && !EvalResult.checkFullyInitialized(S, Ptr))
return false;

if (std::optional<APValue> APV = Ptr.toRValue(S.getCtx())) {
EvalResult.setValue(*APV);
return true;
Expand Down
23 changes: 12 additions & 11 deletions clang/lib/AST/Interp/EvaluationResult.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,21 +141,22 @@ bool EvaluationResult::checkFullyInitialized(InterpState &S,
const Pointer &Ptr) const {
assert(Source);
assert(empty());

// Our Source must be a VarDecl.
const Decl *SourceDecl = Source.dyn_cast<const Decl *>();
assert(SourceDecl);
const auto *VD = cast<VarDecl>(SourceDecl);
assert(VD->getType()->isRecordType() || VD->getType()->isArrayType());
SourceLocation InitLoc = VD->getAnyInitializer()->getExprLoc();

assert(!Ptr.isZero());

SourceLocation InitLoc;
if (const auto *D = Source.dyn_cast<const Decl *>())
InitLoc = cast<VarDecl>(D)->getAnyInitializer()->getExprLoc();
else if (const auto *E = Source.dyn_cast<const Expr *>())
InitLoc = E->getExprLoc();

if (const Record *R = Ptr.getRecord())
return CheckFieldsInitialized(S, InitLoc, Ptr, R);
const auto *CAT =
cast<ConstantArrayType>(Ptr.getType()->getAsArrayTypeUnsafe());
return CheckArrayInitialized(S, InitLoc, Ptr, CAT);

if (const auto *CAT = dyn_cast_if_present<ConstantArrayType>(
Ptr.getType()->getAsArrayTypeUnsafe()))
return CheckArrayInitialized(S, InitLoc, Ptr, CAT);

return true;
}

} // namespace interp
Expand Down
56 changes: 55 additions & 1 deletion clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1283,9 +1283,32 @@ inline bool GetPtrGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
return true;
}

/// 1) Pops a Pointer from the stack
/// 1) Peeks a Pointer
/// 2) Pushes Pointer.atField(Off) on the stack
inline bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off) {
const Pointer &Ptr = S.Stk.peek<Pointer>();

if (S.getLangOpts().CPlusPlus && S.inConstantContext() &&
!CheckNull(S, OpPC, Ptr, CSK_Field))
return false;

if (!CheckExtern(S, OpPC, Ptr))
return false;
if (!CheckRange(S, OpPC, Ptr, CSK_Field))
return false;
if (!CheckArray(S, OpPC, Ptr))
return false;
if (!CheckSubobject(S, OpPC, Ptr, CSK_Field))
return false;

if (Ptr.isBlockPointer() && Off > Ptr.block()->getSize())
return false;

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

inline bool GetPtrFieldPop(InterpState &S, CodePtr OpPC, uint32_t Off) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (S.getLangOpts().CPlusPlus && S.inConstantContext() &&
Expand Down Expand Up @@ -1914,6 +1937,9 @@ template <PrimType Name, class T = typename PrimConv<Name>::T>
bool CastPointerIntegral(InterpState &S, CodePtr OpPC) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (Ptr.isDummy())
return false;

const SourceInfo &E = S.Current->getSource(OpPC);
S.CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
Expand All @@ -1926,6 +1952,9 @@ static inline bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC,
uint32_t BitWidth) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (Ptr.isDummy())
return false;

const SourceInfo &E = S.Current->getSource(OpPC);
S.CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
Expand All @@ -1939,6 +1968,9 @@ static inline bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC,
uint32_t BitWidth) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (Ptr.isDummy())
return false;

const SourceInfo &E = S.Current->getSource(OpPC);
S.CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
Expand All @@ -1948,6 +1980,28 @@ static inline bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC,
return true;
}

static inline bool PtrPtrCast(InterpState &S, CodePtr OpPC, bool SrcIsVoidPtr) {
const auto &Ptr = S.Stk.peek<Pointer>();

if (SrcIsVoidPtr && S.getLangOpts().CPlusPlus) {
bool HasValidResult = !Ptr.isZero();

if (HasValidResult) {
// FIXME: note_constexpr_invalid_void_star_cast
} else if (!S.getLangOpts().CPlusPlus26) {
const SourceInfo &E = S.Current->getSource(OpPC);
S.CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 3 << "'void *'" << S.Current->getRange(OpPC);
}
} else {
const SourceInfo &E = S.Current->getSource(OpPC);
S.CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
}

return true;
}

//===----------------------------------------------------------------------===//
// Zero, Nullptr
//===----------------------------------------------------------------------===//
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/MemberPointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class MemberPointer final {
bool hasBase() const { return !Base.isZero(); }

void print(llvm::raw_ostream &OS) const {
OS << "MemberPtr(" << Base << " " << (void *)Dcl << " + " << PtrOffset
OS << "MemberPtr(" << Base << " " << (const void *)Dcl << " + " << PtrOffset
<< ")";
}

Expand Down
52 changes: 17 additions & 35 deletions clang/lib/AST/Interp/Opcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -281,53 +281,31 @@ def Null : Opcode {
//===----------------------------------------------------------------------===//
// Pointer generation
//===----------------------------------------------------------------------===//
class OffsetOpcode : Opcode {
let Args = [ArgUint32];
}

// [] -> [Pointer]
def GetPtrLocal : Opcode {
// Offset of local.
let Args = [ArgUint32];
def GetPtrLocal : OffsetOpcode {
bit HasCustomEval = 1;
}
// [] -> [Pointer]
def GetPtrParam : Opcode {
// Offset of parameter.
let Args = [ArgUint32];
}
def GetPtrParam : OffsetOpcode;
// [] -> [Pointer]
def GetPtrGlobal : Opcode {
// Index of global.
let Args = [ArgUint32];
}
def GetPtrGlobal : OffsetOpcode;
// [Pointer] -> [Pointer]
def GetPtrField : Opcode {
// Offset of field.
let Args = [ArgUint32];
}
def GetPtrField : OffsetOpcode;
def GetPtrFieldPop : OffsetOpcode;
// [Pointer] -> [Pointer]
def GetPtrActiveField : Opcode {
// Offset of field.
let Args = [ArgUint32];
}
def GetPtrActiveField : OffsetOpcode;
// [] -> [Pointer]
def GetPtrActiveThisField : Opcode {
// Offset of field.
let Args = [ArgUint32];
}
def GetPtrActiveThisField : OffsetOpcode;
// [] -> [Pointer]
def GetPtrThisField : Opcode {
// Offset of field.
let Args = [ArgUint32];
}
def GetPtrThisField : OffsetOpcode;
// [Pointer] -> [Pointer]
def GetPtrBase : Opcode {
// Offset of field, which is a base.
let Args = [ArgUint32];
}
def GetPtrBase : OffsetOpcode;
// [Pointer] -> [Pointer]
def GetPtrBasePop : Opcode {
// Offset of field, which is a base.
let Args = [ArgUint32];
}
def GetPtrBasePop : OffsetOpcode;
def GetMemberPtrBasePop : Opcode {
// Offset of field, which is a base.
let Args = [ArgSint32];
Expand Down Expand Up @@ -687,6 +665,10 @@ def CastPointerIntegralAPS : Opcode {
let HasGroup = 0;
let Args = [ArgUint32];
}
def PtrPtrCast : Opcode {
let Args = [ArgBool];

}

def DecayPtr : Opcode {
let Types = [PtrTypeClass, PtrTypeClass];
Expand Down
46 changes: 24 additions & 22 deletions clang/lib/AST/Interp/Pointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,53 +64,55 @@ Pointer::~Pointer() {
}

void Pointer::operator=(const Pointer &P) {
if (!this->isIntegralPointer() || !P.isBlockPointer())
assert(P.StorageKind == StorageKind || (this->isZero() && P.isZero()));

// If the current storage type is Block, we need to remove
// this pointer from the block.
bool WasBlockPointer = isBlockPointer();
StorageKind = P.StorageKind;
if (StorageKind == Storage::Block) {
Block *Old = PointeeStorage.BS.Pointee;
if (WasBlockPointer && PointeeStorage.BS.Pointee)
if (WasBlockPointer && Old) {
PointeeStorage.BS.Pointee->removePointer(this);
Old->cleanup();
}
}

Offset = P.Offset;
StorageKind = P.StorageKind;
Offset = P.Offset;

if (P.isBlockPointer()) {
PointeeStorage.BS = P.PointeeStorage.BS;
PointeeStorage.BS.Pointee = P.PointeeStorage.BS.Pointee;

if (PointeeStorage.BS.Pointee)
PointeeStorage.BS.Pointee->addPointer(this);

if (WasBlockPointer && Old)
Old->cleanup();

} else if (StorageKind == Storage::Int) {
} else if (P.isIntegralPointer()) {
PointeeStorage.Int = P.PointeeStorage.Int;
} else {
assert(false && "Unhandled storage kind");
}
}

void Pointer::operator=(Pointer &&P) {
if (!this->isIntegralPointer() || !P.isBlockPointer())
assert(P.StorageKind == StorageKind || (this->isZero() && P.isZero()));

// If the current storage type is Block, we need to remove
// this pointer from the block.
bool WasBlockPointer = isBlockPointer();
StorageKind = P.StorageKind;
if (StorageKind == Storage::Block) {
Block *Old = PointeeStorage.BS.Pointee;
if (WasBlockPointer && PointeeStorage.BS.Pointee)
if (WasBlockPointer && Old) {
PointeeStorage.BS.Pointee->removePointer(this);
Old->cleanup();
}
}

Offset = P.Offset;
StorageKind = P.StorageKind;
Offset = P.Offset;

if (P.isBlockPointer()) {
PointeeStorage.BS = P.PointeeStorage.BS;
PointeeStorage.BS.Pointee = P.PointeeStorage.BS.Pointee;

if (PointeeStorage.BS.Pointee)
PointeeStorage.BS.Pointee->addPointer(this);

if (WasBlockPointer && Old)
Old->cleanup();

} else if (StorageKind == Storage::Int) {
} else if (P.isIntegralPointer()) {
PointeeStorage.Int = P.PointeeStorage.Int;
} else {
assert(false && "Unhandled storage kind");
Expand Down
5 changes: 2 additions & 3 deletions clang/lib/AST/Mangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,9 +301,8 @@ void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD,
} else {
assert((isa<NamedDecl>(DC) || isa<BlockDecl>(DC)) &&
"expected a NamedDecl or BlockDecl");
if (isa<BlockDecl>(DC))
for (; DC && isa<BlockDecl>(DC); DC = DC->getParent())
(void) getBlockId(cast<BlockDecl>(DC), true);
for (; isa_and_nonnull<BlockDecl>(DC); DC = DC->getParent())
(void)getBlockId(cast<BlockDecl>(DC), true);
assert((isa<TranslationUnitDecl>(DC) || isa<NamedDecl>(DC)) &&
"expected a TranslationUnitDecl or a NamedDecl");
if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC))
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/AST/MicrosoftMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,8 @@ void MicrosoftCXXNameMangler::mangleFloat(llvm::APFloat Number) {
case APFloat::S_Float8E4M3FNUZ:
case APFloat::S_Float8E4M3B11FNUZ:
case APFloat::S_FloatTF32:
case APFloat::S_Float6E3M2FN:
case APFloat::S_Float6E2M3FN:
llvm_unreachable("Tried to mangle unexpected APFloat semantics");
}

Expand Down Expand Up @@ -2748,7 +2750,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
return;
}
Out << '@';
} else if (IsInLambda && D && isa<CXXConversionDecl>(D)) {
} else if (IsInLambda && isa_and_nonnull<CXXConversionDecl>(D)) {
// The only lambda conversion operators are to function pointers, which
// can differ by their calling convention and are typically deduced. So
// we make sure that this type gets mangled properly.
Expand Down
7 changes: 5 additions & 2 deletions clang/lib/AST/ParentMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,9 @@ Stmt* ParentMap::getParent(Stmt* S) const {
}

Stmt *ParentMap::getParentIgnoreParens(Stmt *S) const {
do { S = getParent(S); } while (S && isa<ParenExpr>(S));
do {
S = getParent(S);
} while (isa_and_nonnull<ParenExpr>(S));
return S;
}

Expand All @@ -155,7 +157,8 @@ Stmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const {
Stmt *ParentMap::getParentIgnoreParenImpCasts(Stmt *S) const {
do {
S = getParent(S);
} while (S && isa<Expr>(S) && cast<Expr>(S)->IgnoreParenImpCasts() != S);
} while (isa_and_nonnull<Expr>(S) &&
cast<Expr>(S)->IgnoreParenImpCasts() != S);

return S;
}
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/StmtPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ namespace {

void PrintStmt(Stmt *S, int SubIndent) {
IndentLevel += SubIndent;
if (S && isa<Expr>(S)) {
if (isa_and_nonnull<Expr>(S)) {
// If this is an expr used in a stmt context, indent and newline it.
Indent();
Visit(S);
Expand Down Expand Up @@ -1939,7 +1939,7 @@ void StmtPrinter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) {
void StmtPrinter::VisitCXXMemberCallExpr(CXXMemberCallExpr *Node) {
// If we have a conversion operator call only print the argument.
CXXMethodDecl *MD = Node->getMethodDecl();
if (MD && isa<CXXConversionDecl>(MD)) {
if (isa_and_nonnull<CXXConversionDecl>(MD)) {
PrintExpr(Node->getImplicitObjectArgument());
return;
}
Expand Down
9 changes: 0 additions & 9 deletions clang/lib/AST/TemplateBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -577,15 +577,6 @@ void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out,
}
}

void TemplateArgument::dump(raw_ostream &Out) const {
LangOptions LO; // FIXME! see also TemplateName::dump().
LO.CPlusPlus = true;
LO.Bool = true;
print(PrintingPolicy(LO), Out, /*IncludeType*/ true);
}

LLVM_DUMP_METHOD void TemplateArgument::dump() const { dump(llvm::errs()); }

//===----------------------------------------------------------------------===//
// TemplateArgumentLoc Implementation
//===----------------------------------------------------------------------===//
Expand Down
11 changes: 0 additions & 11 deletions clang/lib/AST/TemplateName.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,14 +360,3 @@ const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
OS.flush();
return DB << NameStr;
}

void TemplateName::dump(raw_ostream &OS) const {
LangOptions LO; // FIXME!
LO.CPlusPlus = true;
LO.Bool = true;
print(OS, PrintingPolicy(LO));
}

LLVM_DUMP_METHOD void TemplateName::dump() const {
dump(llvm::errs());
}
11 changes: 7 additions & 4 deletions clang/lib/Analysis/FlowSensitive/ASTOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ getFieldsForInitListExpr(const InitListT *InitList) {
std::vector<const FieldDecl *> Fields;

if (InitList->getType()->isUnionType()) {
Fields.push_back(InitList->getInitializedFieldInUnion());
if (const FieldDecl *Field = InitList->getInitializedFieldInUnion())
Fields.push_back(Field);
return Fields;
}

Expand Down Expand Up @@ -137,9 +138,11 @@ RecordInitListHelper::RecordInitListHelper(
// it doesn't do this -- so we create an `ImplicitValueInitExpr` ourselves.
SmallVector<Expr *> InitsForUnion;
if (Ty->isUnionType() && Inits.empty()) {
assert(Fields.size() == 1);
ImplicitValueInitForUnion.emplace(Fields.front()->getType());
InitsForUnion.push_back(&*ImplicitValueInitForUnion);
assert(Fields.size() <= 1);
if (!Fields.empty()) {
ImplicitValueInitForUnion.emplace(Fields.front()->getType());
InitsForUnion.push_back(&*ImplicitValueInitForUnion);
}
Inits = InitsForUnion;
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ class ResultObjectVisitor : public AnalysisASTVisitor<ResultObjectVisitor> {
// below them can initialize the same object (or part of it).
if (isa<CXXConstructExpr>(E) || isa<CallExpr>(E) || isa<LambdaExpr>(E) ||
isa<CXXDefaultArgExpr>(E) || isa<CXXDefaultInitExpr>(E) ||
isa<CXXStdInitializerListExpr>(E) ||
isa<CXXStdInitializerListExpr>(E) || isa<AtomicExpr>(E) ||
// We treat `BuiltinBitCastExpr` as an "original initializer" too as
// it may not even be casting from a record type -- and even if it is,
// the two objects are in general of unrelated type.
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Basic/Targets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -673,8 +673,11 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
}
case llvm::Triple::spirv64: {
if (os != llvm::Triple::UnknownOS ||
Triple.getEnvironment() != llvm::Triple::UnknownEnvironment)
Triple.getEnvironment() != llvm::Triple::UnknownEnvironment) {
if (os == llvm::Triple::OSType::AMDHSA)
return std::make_unique<SPIRV64AMDGCNTargetInfo>(Triple, Opts);
return nullptr;
}
return std::make_unique<SPIRV64TargetInfo>(Triple, Opts);
}
case llvm::Triple::wasm32:
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,6 @@ void AArch64TargetInfo::getTargetDefinesARMV84A(const LangOptions &Opts,
void AArch64TargetInfo::getTargetDefinesARMV85A(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__ARM_FEATURE_FRINT", "1");
Builder.defineMacro("__ARM_FEATURE_BTI", "1");
// Also include the Armv8.4 defines
getTargetDefinesARMV84A(Opts, Builder);
}
Expand Down Expand Up @@ -499,6 +498,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
if (HasPAuthLR)
Builder.defineMacro("__ARM_FEATURE_PAUTH_LR", "1");

if (HasBTI)
Builder.defineMacro("__ARM_FEATURE_BTI", "1");

if (HasUnalignedAccess)
Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");

Expand Down Expand Up @@ -1085,7 +1087,7 @@ bool AArch64TargetInfo::initFeatureMap(
std::string UpdatedFeature = Feature;
if (Feature[0] == '+') {
std::optional<llvm::AArch64::ExtensionInfo> Extension =
llvm::AArch64::parseArchExtension(Feature.substr(1));
llvm::AArch64::parseArchExtension(Feature.substr(1));
if (Extension)
UpdatedFeature = Extension->Feature.str();
}
Expand Down
75 changes: 75 additions & 0 deletions clang/lib/Basic/Targets/SPIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
//===----------------------------------------------------------------------===//

#include "SPIR.h"
#include "AMDGPU.h"
#include "Targets.h"
#include "llvm/TargetParser/TargetParser.h"

using namespace clang;
using namespace clang::targets;
Expand Down Expand Up @@ -54,3 +56,76 @@ void SPIRV64TargetInfo::getTargetDefines(const LangOptions &Opts,
BaseSPIRVTargetInfo::getTargetDefines(Opts, Builder);
DefineStd(Builder, "SPIRV64", Opts);
}

static const AMDGPUTargetInfo AMDGPUTI(llvm::Triple("amdgcn-amd-amdhsa"), {});

ArrayRef<const char *> SPIRV64AMDGCNTargetInfo::getGCCRegNames() const {
return AMDGPUTI.getGCCRegNames();
}

bool SPIRV64AMDGCNTargetInfo::initFeatureMap(
llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef,
const std::vector<std::string> &FeatureVec) const {
llvm::AMDGPU::fillAMDGPUFeatureMap({}, getTriple(), Features);

return TargetInfo::initFeatureMap(Features, Diags, {}, FeatureVec);
}

bool SPIRV64AMDGCNTargetInfo::validateAsmConstraint(
const char *&Name, TargetInfo::ConstraintInfo &Info) const {
return AMDGPUTI.validateAsmConstraint(Name, Info);
}

std::string
SPIRV64AMDGCNTargetInfo::convertConstraint(const char *&Constraint) const {
return AMDGPUTI.convertConstraint(Constraint);
}

ArrayRef<Builtin::Info> SPIRV64AMDGCNTargetInfo::getTargetBuiltins() const {
return AMDGPUTI.getTargetBuiltins();
}

void SPIRV64AMDGCNTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
BaseSPIRVTargetInfo::getTargetDefines(Opts, Builder);
DefineStd(Builder, "SPIRV64", Opts);

Builder.defineMacro("__AMD__");
Builder.defineMacro("__AMDGPU__");
Builder.defineMacro("__AMDGCN__");
}

void SPIRV64AMDGCNTargetInfo::setAuxTarget(const TargetInfo *Aux) {
assert(Aux && "Cannot invoke setAuxTarget without a valid auxiliary target!");

// This is a 1:1 copy of AMDGPUTargetInfo::setAuxTarget()
assert(HalfFormat == Aux->HalfFormat);
assert(FloatFormat == Aux->FloatFormat);
assert(DoubleFormat == Aux->DoubleFormat);

// On x86_64 long double is 80-bit extended precision format, which is
// not supported by AMDGPU. 128-bit floating point format is also not
// supported by AMDGPU. Therefore keep its own format for these two types.
auto SaveLongDoubleFormat = LongDoubleFormat;
auto SaveFloat128Format = Float128Format;
auto SaveLongDoubleWidth = LongDoubleWidth;
auto SaveLongDoubleAlign = LongDoubleAlign;
copyAuxTarget(Aux);
LongDoubleFormat = SaveLongDoubleFormat;
Float128Format = SaveFloat128Format;
LongDoubleWidth = SaveLongDoubleWidth;
LongDoubleAlign = SaveLongDoubleAlign;
// For certain builtin types support on the host target, claim they are
// supported to pass the compilation of the host code during the device-side
// compilation.
// FIXME: As the side effect, we also accept `__float128` uses in the device
// code. To reject these builtin types supported in the host target but not in
// the device target, one approach would support `device_builtin` attribute
// so that we could tell the device builtin types from the host ones. This
// also solves the different representations of the same builtin type, such
// as `size_t` in the MSVC environment.
if (Aux->hasFloat128Type()) {
HasFloat128 = true;
Float128Format = DoubleFormat;
}
}
51 changes: 51 additions & 0 deletions clang/lib/Basic/Targets/SPIR.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,57 @@ class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo : public BaseSPIRVTargetInfo {
MacroBuilder &Builder) const override;
};

class LLVM_LIBRARY_VISIBILITY SPIRV64AMDGCNTargetInfo final
: public BaseSPIRVTargetInfo {
public:
SPIRV64AMDGCNTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: BaseSPIRVTargetInfo(Triple, Opts) {
assert(Triple.getArch() == llvm::Triple::spirv64 &&
"Invalid architecture for 64-bit AMDGCN SPIR-V.");
assert(Triple.getVendor() == llvm::Triple::VendorType::AMD &&
"64-bit AMDGCN SPIR-V target must use AMD vendor");
assert(getTriple().getOS() == llvm::Triple::OSType::AMDHSA &&
"64-bit AMDGCN SPIR-V target must use AMDHSA OS");
assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
"64-bit SPIR-V target must use unknown environment type");
PointerWidth = PointerAlign = 64;
SizeType = TargetInfo::UnsignedLong;
PtrDiffType = IntPtrType = TargetInfo::SignedLong;

resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-"
"v96:128-v192:256-v256:256-v512:512-v1024:1024-G1-P4-A0");

BFloat16Width = BFloat16Align = 16;
BFloat16Format = &llvm::APFloat::BFloat();

HasLegalHalfType = true;
HasFloat16 = true;
HalfArgsAndReturns = true;
}

bool hasBFloat16Type() const override { return true; }

ArrayRef<const char *> getGCCRegNames() const override;

bool initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
StringRef,
const std::vector<std::string> &) const override;

bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const override;

std::string convertConstraint(const char *&Constraint) const override;

ArrayRef<Builtin::Info> getTargetBuiltins() const override;

void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;

void setAuxTarget(const TargetInfo *Aux) override;

bool hasInt128Type() const override { return TargetInfo::hasInt128Type(); }
};

} // namespace targets
} // namespace clang
#endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGBlocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,

// First, 'this'.
if (block->capturesCXXThis()) {
assert(CGF && CGF->CurFuncDecl && isa<CXXMethodDecl>(CGF->CurFuncDecl) &&
assert(CGF && isa_and_nonnull<CXXMethodDecl>(CGF->CurFuncDecl) &&
"Can't capture 'this' outside a method");
QualType thisType = cast<CXXMethodDecl>(CGF->CurFuncDecl)->getThisType();

Expand Down
19 changes: 19 additions & 0 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2923,6 +2923,18 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
SetSqrtFPAccuracy(Call);
return RValue::get(Call);
}

case Builtin::BItan:
case Builtin::BItanf:
case Builtin::BItanl:
case Builtin::BI__builtin_tan:
case Builtin::BI__builtin_tanf:
case Builtin::BI__builtin_tanf16:
case Builtin::BI__builtin_tanl:
case Builtin::BI__builtin_tanf128:
return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(
*this, E, Intrinsic::tan, Intrinsic::experimental_constrained_tan));

case Builtin::BItrunc:
case Builtin::BItruncf:
case Builtin::BItruncl:
Expand Down Expand Up @@ -6012,6 +6024,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
llvm::Triple::getArchTypePrefix(getTarget().getTriple().getArch());
if (!Prefix.empty()) {
IntrinsicID = Intrinsic::getIntrinsicForClangBuiltin(Prefix.data(), Name);
if (IntrinsicID == Intrinsic::not_intrinsic && Prefix == "spv" &&
getTarget().getTriple().getOS() == llvm::Triple::OSType::AMDHSA)
IntrinsicID = Intrinsic::getIntrinsicForClangBuiltin("amdgcn", Name);
// NOTE we don't need to perform a compatibility flag check here since the
// intrinsics are declared in Builtins*.def via LANGBUILTIN which filter the
// MS builtins via ALL_MS_LANGUAGES and are filtered earlier.
Expand Down Expand Up @@ -6182,6 +6197,10 @@ static Value *EmitTargetArchBuiltinExpr(CodeGenFunction *CGF,
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
return CGF->EmitRISCVBuiltinExpr(BuiltinID, E, ReturnValue);
case llvm::Triple::spirv64:
if (CGF->getTarget().getTriple().getOS() != llvm::Triple::OSType::AMDHSA)
return nullptr;
return CGF->EmitAMDGPUBuiltinExpr(BuiltinID, E);
default:
return nullptr;
}
Expand Down
1 change: 1 addition & 0 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1917,6 +1917,7 @@ static void getTrivialDefaultFunctionAttributes(
case CodeGenOptions::FramePointerKind::None:
// This is the default behavior.
break;
case CodeGenOptions::FramePointerKind::Reserved:
case CodeGenOptions::FramePointerKind::NonLeaf:
case CodeGenOptions::FramePointerKind::All:
FuncAttrs.addAttribute("frame-pointer",
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CGClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,7 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) {

// Enter the function-try-block before the constructor prologue if
// applicable.
bool IsTryBody = (Body && isa<CXXTryStmt>(Body));
bool IsTryBody = isa_and_nonnull<CXXTryStmt>(Body);
if (IsTryBody)
EnterCXXTryStmt(*cast<CXXTryStmt>(Body), true);

Expand Down Expand Up @@ -1475,7 +1475,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {

// If the body is a function-try-block, enter the try before
// anything else.
bool isTryBody = (Body && isa<CXXTryStmt>(Body));
bool isTryBody = isa_and_nonnull<CXXTryStmt>(Body);
if (isTryBody)
EnterCXXTryStmt(*cast<CXXTryStmt>(Body), true);
EmitAsanPrologueOrEpilogue(false);
Expand Down
43 changes: 20 additions & 23 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,16 @@ using namespace clang::CodeGen;

static uint32_t getTypeAlignIfRequired(const Type *Ty, const ASTContext &Ctx) {
auto TI = Ctx.getTypeInfo(Ty);
return TI.isAlignRequired() ? TI.Align : 0;
if (TI.isAlignRequired())
return TI.Align;

// MaxFieldAlignmentAttr is the attribute added to types
// declared after #pragma pack(n).
if (auto *Decl = Ty->getAsRecordDecl())
if (Decl->hasAttr<MaxFieldAlignmentAttr>())
return TI.Align;

return 0;
}

static uint32_t getTypeAlignIfRequired(QualType Ty, const ASTContext &Ctx) {
Expand Down Expand Up @@ -5757,28 +5766,16 @@ void CGDebugInfo::EmitPseudoVariable(CGBuilderTy &Builder,
// it is loaded upon use, so we identify such pattern here.
if (llvm::LoadInst *Load = dyn_cast<llvm::LoadInst>(Value)) {
llvm::Value *Var = Load->getPointerOperand();
if (llvm::Metadata *MDValue = llvm::ValueAsMetadata::getIfExists(Var)) {
if (llvm::Value *DbgValue = llvm::MetadataAsValue::getIfExists(
CGM.getLLVMContext(), MDValue)) {
for (llvm::User *U : DbgValue->users()) {
if (llvm::CallInst *DbgDeclare = dyn_cast<llvm::CallInst>(U)) {
if (DbgDeclare->getCalledFunction()->getIntrinsicID() ==
llvm::Intrinsic::dbg_declare &&
DbgDeclare->getArgOperand(0) == DbgValue) {
// There can be implicit type cast applied on a variable if it is
// an opaque ptr, in this case its debug info may not match the
// actual type of object being used as in the next instruction, so
// we will need to emit a pseudo variable for type-casted value.
llvm::DILocalVariable *MDNode = cast<llvm::DILocalVariable>(
cast<llvm::MetadataAsValue>(DbgDeclare->getOperand(1))
->getMetadata());
if (MDNode->getType() == Type)
return;
}
}
}
}
}
// There can be implicit type cast applied on a variable if it is an opaque
// ptr, in this case its debug info may not match the actual type of object
// being used as in the next instruction, so we will need to emit a pseudo
// variable for type-casted value.
auto DeclareTypeMatches = [&](auto *DbgDeclare) {
return DbgDeclare->getVariable()->getType() == Type;
};
if (any_of(llvm::findDbgDeclares(Var), DeclareTypeMatches) ||
any_of(llvm::findDVRDeclares(Var), DeclareTypeMatches))
return;
}

// Find the correct location to insert a sequence of instructions to
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/CodeGen/CGDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,10 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrCleanUpFunction(
!isInNoSanitizeList(SanitizerKind::Thread, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeThread);

if (getLangOpts().Sanitize.has(SanitizerKind::NumericalStability) &&
!isInNoSanitizeList(SanitizerKind::NumericalStability, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeNumericalStability);

if (getLangOpts().Sanitize.has(SanitizerKind::Memory) &&
!isInNoSanitizeList(SanitizerKind::Memory, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
Expand Down
5 changes: 2 additions & 3 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3571,9 +3571,8 @@ void CodeGenFunction::EmitCheck(
llvm::BasicBlock *Handlers = createBasicBlock("handler." + CheckName);
llvm::Instruction *Branch = Builder.CreateCondBr(JointCond, Cont, Handlers);
// Give hint that we very much don't expect to execute the handler
// Value chosen to match UR_NONTAKEN_WEIGHT, see BranchProbabilityInfo.cpp
llvm::MDBuilder MDHelper(getLLVMContext());
llvm::MDNode *Node = MDHelper.createBranchWeights((1U << 20) - 1, 1);
llvm::MDNode *Node = MDHelper.createLikelyBranchWeights();
Branch->setMetadata(llvm::LLVMContext::MD_prof, Node);
EmitBlock(Handlers);

Expand Down Expand Up @@ -3641,7 +3640,7 @@ void CodeGenFunction::EmitCfiSlowPathCheck(
llvm::BranchInst *BI = Builder.CreateCondBr(Cond, Cont, CheckBB);

llvm::MDBuilder MDHelper(getLLVMContext());
llvm::MDNode *Node = MDHelper.createBranchWeights((1U << 20) - 1, 1);
llvm::MDNode *Node = MDHelper.createLikelyBranchWeights();
BI->setMetadata(llvm::LLVMContext::MD_prof, Node);

EmitBlock(CheckBB);
Expand Down
29 changes: 9 additions & 20 deletions clang/lib/CodeGen/CGExprAgg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,15 +513,6 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,

QualType elementType =
CGF.getContext().getAsArrayType(ArrayQTy)->getElementType();

// DestPtr is an array*. Construct an elementType* by drilling
// down a level.
llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0);
llvm::Value *indices[] = { zero, zero };
llvm::Value *begin = Builder.CreateInBoundsGEP(DestPtr.getElementType(),
DestPtr.emitRawPointer(CGF),
indices, "arrayinit.begin");

CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType);
CharUnits elementAlign =
DestPtr.getAlignment().alignmentOfArrayElement(elementSize);
Expand Down Expand Up @@ -562,6 +553,7 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
Address endOfInit = Address::invalid();
CodeGenFunction::CleanupDeactivationScope deactivation(CGF);

llvm::Value *begin = DestPtr.emitRawPointer(CGF);
if (dtorKind) {
CodeGenFunction::AllocaTrackerRAII allocaTracker(CGF);
// In principle we could tell the cleanup where we are more
Expand All @@ -585,19 +577,13 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,

llvm::Value *one = llvm::ConstantInt::get(CGF.SizeTy, 1);

// The 'current element to initialize'. The invariants on this
// variable are complicated. Essentially, after each iteration of
// the loop, it points to the last initialized element, except
// that it points to the beginning of the array before any
// elements have been initialized.
llvm::Value *element = begin;

// Emit the explicit initializers.
for (uint64_t i = 0; i != NumInitElements; ++i) {
// Advance to the next element.
llvm::Value *element = begin;
if (i > 0) {
element = Builder.CreateInBoundsGEP(
llvmElementType, element, one, "arrayinit.element");
element = Builder.CreateInBoundsGEP(llvmElementType, begin,
llvm::ConstantInt::get(CGF.SizeTy, i),
"arrayinit.element");

// Tell the cleanup that it needs to destroy up to this
// element. TODO: some of these stores can be trivially
Expand All @@ -624,9 +610,12 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
// do { *array++ = filler; } while (array != end);

// Advance to the start of the rest of the array.
llvm::Value *element = begin;
if (NumInitElements) {
element = Builder.CreateInBoundsGEP(
llvmElementType, element, one, "arrayinit.start");
llvmElementType, element,
llvm::ConstantInt::get(CGF.SizeTy, NumInitElements),
"arrayinit.start");
if (endOfInit.isValid()) Builder.CreateStore(element, endOfInit);
}

Expand Down
3 changes: 1 addition & 2 deletions clang/lib/CodeGen/CGExprComplex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -856,8 +856,7 @@ ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) {
llvm::BasicBlock *OrigBB = Branch->getParent();

// Give hint that we very much don't expect to see NaNs.
// Value chosen to match UR_NONTAKEN_WEIGHT, see BranchProbabilityInfo.cpp
llvm::MDNode *BrWeight = MDHelper.createBranchWeights(1, (1U << 20) - 1);
llvm::MDNode *BrWeight = MDHelper.createUnlikelyBranchWeights();
Branch->setMetadata(llvm::LLVMContext::MD_prof, BrWeight);

// Now test the imaginary part and create its branch.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,7 @@ bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
const Expr *Init = nullptr;
if (ElementNo < ILE->getNumInits())
Init = ILE->getInit(ElementNo++);
if (Init && isa<NoInitExpr>(Init))
if (isa_and_nonnull<NoInitExpr>(Init))
continue;

// Zero-sized fields are not emitted, but their initializers may still
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGHLSLRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ void clang::CodeGen::CGHLSLRuntime::setHLSLEntryAttributes(
assert(ShaderAttr && "All entry functions must have a HLSLShaderAttr");
const StringRef ShaderAttrKindStr = "hlsl.shader";
Fn->addFnAttr(ShaderAttrKindStr,
ShaderAttr->ConvertShaderTypeToStr(ShaderAttr->getType()));
llvm::Triple::getEnvironmentTypeName(ShaderAttr->getType()));
if (HLSLNumThreadsAttr *NumThreadsAttr = FD->getAttr<HLSLNumThreadsAttr>()) {
const StringRef NumThreadsKindStr = "hlsl.numthreads";
std::string NumThreadsStr =
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CGObjCGNU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2069,7 +2069,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {

Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue, Zero),
SelfIsNilBlock, ContBlock,
MDHelper.createBranchWeights(1, 1 << 20));
MDHelper.createUnlikelyBranchWeights());

CGF.EmitBlock(SelfIsNilBlock);

Expand Down Expand Up @@ -2104,7 +2104,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
CGF.createBasicBlock("objc_direct_method.class_initialized");
Builder.CreateCondBr(Builder.CreateICmpEQ(isInitialized, Zeros[0]),
notInitializedBlock, initializedBlock,
MDHelper.createBranchWeights(1, 1 << 20));
MDHelper.createUnlikelyBranchWeights());
CGF.EmitBlock(notInitializedBlock);
Builder.SetInsertPoint(notInitializedBlock);
CGF.EmitRuntimeCall(SentInitializeFn, selfValue);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGObjCMac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4072,7 +4072,7 @@ void CGObjCCommonMac::GenerateDirectMethodPrologue(

llvm::MDBuilder MDHelper(CGM.getLLVMContext());
Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue, Zero), SelfIsNilBlock,
ContBlock, MDHelper.createBranchWeights(1, 1 << 20));
ContBlock, MDHelper.createUnlikelyBranchWeights());

CGF.EmitBlock(SelfIsNilBlock);

Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CGStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,8 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
CGM.ErrorUnsupported(S, "OpenMP dispatch directive");
break;
case Stmt::OMPScopeDirectiveClass:
llvm_unreachable("scope not supported with FE outlining");
CGM.ErrorUnsupported(S, "scope with FE outlining");
break;
case Stmt::OMPMaskedDirectiveClass:
EmitOMPMaskedDirective(cast<OMPMaskedDirective>(*S));
break;
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/CodeGen/CGStmtOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class OMPLexicalScope : public CodeGenFunction::LexicalScope {
static bool isCapturedVar(CodeGenFunction &CGF, const VarDecl *VD) {
return CGF.LambdaCaptureFields.lookup(VD) ||
(CGF.CapturedStmtInfo && CGF.CapturedStmtInfo->lookup(VD)) ||
(CGF.CurCodeDecl && isa<BlockDecl>(CGF.CurCodeDecl) &&
(isa_and_nonnull<BlockDecl>(CGF.CurCodeDecl) &&
cast<BlockDecl>(CGF.CurCodeDecl)->capturesVariable(VD));
}

Expand Down Expand Up @@ -227,7 +227,7 @@ class OMPSimdLexicalScope : public CodeGenFunction::LexicalScope {
static bool isCapturedVar(CodeGenFunction &CGF, const VarDecl *VD) {
return CGF.LambdaCaptureFields.lookup(VD) ||
(CGF.CapturedStmtInfo && CGF.CapturedStmtInfo->lookup(VD)) ||
(CGF.CurCodeDecl && isa<BlockDecl>(CGF.CurCodeDecl) &&
(isa_and_nonnull<BlockDecl>(CGF.CurCodeDecl) &&
cast<BlockDecl>(CGF.CurCodeDecl)->capturesVariable(VD));
}

Expand Down Expand Up @@ -315,7 +315,7 @@ LValue CodeGenFunction::EmitOMPSharedLValue(const Expr *E) {
bool IsCaptured =
LambdaCaptureFields.lookup(OrigVD) ||
(CapturedStmtInfo && CapturedStmtInfo->lookup(OrigVD)) ||
(CurCodeDecl && isa<BlockDecl>(CurCodeDecl));
(isa_and_nonnull<BlockDecl>(CurCodeDecl));
DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD), IsCaptured,
OrigDRE->getType(), VK_LValue, OrigDRE->getExprLoc());
return EmitLValue(&DRE);
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
Fn->addFnAttr(llvm::Attribute::SanitizeMemTag);
if (SanOpts.has(SanitizerKind::Thread))
Fn->addFnAttr(llvm::Attribute::SanitizeThread);
if (SanOpts.has(SanitizerKind::NumericalStability))
Fn->addFnAttr(llvm::Attribute::SanitizeNumericalStability);
if (SanOpts.hasOneOf(SanitizerKind::Memory | SanitizerKind::KernelMemory))
Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
}
Expand Down Expand Up @@ -2951,7 +2953,7 @@ void CodeGenFunction::emitAlignmentAssumptionCheck(
SourceLocation SecondaryLoc, llvm::Value *Alignment,
llvm::Value *OffsetValue, llvm::Value *TheCheck,
llvm::Instruction *Assumption) {
assert(Assumption && isa<llvm::CallInst>(Assumption) &&
assert(isa_and_nonnull<llvm::CallInst>(Assumption) &&
cast<llvm::CallInst>(Assumption)->getCalledOperand() ==
llvm::Intrinsic::getDeclaration(
Builder.GetInsertBlock()->getParent()->getParent(),
Expand Down
22 changes: 18 additions & 4 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1328,6 +1328,9 @@ void CodeGenModule::Release() {
case CodeGenOptions::FramePointerKind::None:
// 0 ("none") is the default.
break;
case CodeGenOptions::FramePointerKind::Reserved:
getModule().setFramePointer(llvm::FramePointerKind::Reserved);
break;
case CodeGenOptions::FramePointerKind::NonLeaf:
getModule().setFramePointer(llvm::FramePointerKind::NonLeaf);
break;
Expand Down Expand Up @@ -4509,6 +4512,19 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
return Resolver;
}

bool CodeGenModule::shouldDropDLLAttribute(const Decl *D,
const llvm::GlobalValue *GV) const {
auto SC = GV->getDLLStorageClass();
if (SC == llvm::GlobalValue::DefaultStorageClass)
return false;
const Decl *MRD = D->getMostRecentDecl();
return (((SC == llvm::GlobalValue::DLLImportStorageClass &&
!MRD->hasAttr<DLLImportAttr>()) ||
(SC == llvm::GlobalValue::DLLExportStorageClass &&
!MRD->hasAttr<DLLExportAttr>())) &&
!shouldMapVisibilityToDLLExport(cast<NamedDecl>(MRD)));
}

/// GetOrCreateLLVMFunction - If the specified mangled name is not in the
/// module, create and return an llvm Function with the specified type. If there
/// is something in the module with the specified name, return it potentially
Expand Down Expand Up @@ -4561,8 +4577,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
}

// Handle dropped DLL attributes.
if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>() &&
!shouldMapVisibilityToDLLExport(cast_or_null<NamedDecl>(D))) {
if (D && shouldDropDLLAttribute(D, Entry)) {
Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
setDSOLocal(Entry);
}
Expand Down Expand Up @@ -4856,8 +4871,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty,
}

// Handle dropped DLL attributes.
if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>() &&
!shouldMapVisibilityToDLLExport(D))
if (D && shouldDropDLLAttribute(D, Entry))
Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);

if (LangOpts.OpenMP && !LangOpts.OpenMPSimd && D)
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -1594,6 +1594,8 @@ class CodeGenModule : public CodeGenTypeCache {
}

private:
bool shouldDropDLLAttribute(const Decl *D, const llvm::GlobalValue *GV) const;

llvm::Constant *GetOrCreateLLVMFunction(
StringRef MangledName, llvm::Type *Ty, GlobalDecl D, bool ForVTable,
bool DontDefer = false, bool IsThunk = false,
Expand Down
7 changes: 5 additions & 2 deletions clang/lib/Driver/SanitizerArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ static const SanitizerMask NotAllowedWithExecuteOnly =
SanitizerKind::Function | SanitizerKind::KCFI;
static const SanitizerMask NeedsUnwindTables =
SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Thread |
SanitizerKind::Memory | SanitizerKind::DataFlow;
SanitizerKind::Memory | SanitizerKind::DataFlow |
SanitizerKind::NumericalStability;
static const SanitizerMask SupportsCoverage =
SanitizerKind::Address | SanitizerKind::HWAddress |
SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
Expand All @@ -53,7 +54,8 @@ static const SanitizerMask SupportsCoverage =
SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero |
SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack |
SanitizerKind::Thread | SanitizerKind::ObjCCast | SanitizerKind::KCFI;
SanitizerKind::Thread | SanitizerKind::ObjCCast | SanitizerKind::KCFI |
SanitizerKind::NumericalStability;
static const SanitizerMask RecoverableByDefault =
SanitizerKind::Undefined | SanitizerKind::Integer |
SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
Expand Down Expand Up @@ -175,6 +177,7 @@ static void addDefaultIgnorelists(const Driver &D, SanitizerMask Kinds,
{"hwasan_ignorelist.txt", SanitizerKind::HWAddress},
{"memtag_ignorelist.txt", SanitizerKind::MemTag},
{"msan_ignorelist.txt", SanitizerKind::Memory},
{"nsan_ignorelist.txt", SanitizerKind::NumericalStability},
{"tsan_ignorelist.txt", SanitizerKind::Thread},
{"dfsan_abilist.txt", SanitizerKind::DataFlow},
{"cfi_ignorelist.txt", SanitizerKind::CFI},
Expand Down
8 changes: 4 additions & 4 deletions clang/lib/Driver/ToolChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
}

llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
ToolChain::executeToolChainProgram(StringRef Executable) const {
ToolChain::executeToolChainProgram(StringRef Executable,
unsigned SecondsToWait) const {
llvm::SmallString<64> OutputFile;
llvm::sys::fs::createTemporaryFile("toolchain-program", "txt", OutputFile);
llvm::FileRemover OutputRemover(OutputFile.c_str());
Expand All @@ -115,9 +116,8 @@ ToolChain::executeToolChainProgram(StringRef Executable) const {
};

std::string ErrorMessage;
if (llvm::sys::ExecuteAndWait(Executable, {}, {}, Redirects,
/* SecondsToWait */ 0,
/*MemoryLimit*/ 0, &ErrorMessage))
if (llvm::sys::ExecuteAndWait(Executable, {}, {}, Redirects, SecondsToWait,
/*MemoryLimit=*/0, &ErrorMessage))
return llvm::createStringError(std::error_code(),
Executable + ": " + ErrorMessage);

Expand Down
8 changes: 6 additions & 2 deletions clang/lib/Driver/ToolChains/AMDGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,11 @@ void amdgpu::getAMDGPUTargetFeatures(const Driver &D,
std::vector<StringRef> &Features) {
// Add target ID features to -target-feature options. No diagnostics should
// be emitted here since invalid target ID is diagnosed at other places.
StringRef TargetID = Args.getLastArgValue(options::OPT_mcpu_EQ);
StringRef TargetID;
if (Args.hasArg(options::OPT_mcpu_EQ))
TargetID = Args.getLastArgValue(options::OPT_mcpu_EQ);
else if (Args.hasArg(options::OPT_march_EQ))
TargetID = Args.getLastArgValue(options::OPT_march_EQ);
if (!TargetID.empty()) {
llvm::StringMap<bool> FeatureMap;
auto OptionalGpuArch = parseTargetID(Triple, TargetID, &FeatureMap);
Expand Down Expand Up @@ -877,7 +881,7 @@ AMDGPUToolChain::getSystemGPUArchs(const ArgList &Args) const {
else
Program = GetProgramPath("amdgpu-arch");

auto StdoutOrErr = executeToolChainProgram(Program);
auto StdoutOrErr = executeToolChainProgram(Program, /*SecondsToWait=*/10);
if (!StdoutOrErr)
return StdoutOrErr.takeError();

Expand Down
5 changes: 0 additions & 5 deletions clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,9 @@ void AMDGPUOpenMPToolChain::addClangTargetOptions(
Action::OffloadKind DeviceOffloadingKind) const {
HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind);

StringRef GPUArch = DriverArgs.getLastArgValue(options::OPT_march_EQ);
assert(!GPUArch.empty() && "Must have an explicit GPU arch.");

assert(DeviceOffloadingKind == Action::OFK_OpenMP &&
"Only OpenMP offloading kinds are supported.");

CC1Args.push_back("-target-cpu");
CC1Args.push_back(DriverArgs.MakeArgStringRef(GPUArch));
CC1Args.push_back("-fcuda-is-device");

if (DriverArgs.hasArg(options::OPT_nogpulib))
Expand Down
2 changes: 0 additions & 2 deletions clang/lib/Driver/ToolChains/Arch/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -799,8 +799,6 @@ llvm::ARM::FPUKind arm::getARMTargetFeatures(const Driver &D,
StringRef FrameChainOption = A->getValue();
if (FrameChainOption.starts_with("aapcs"))
Features.push_back("+aapcs-frame-chain");
if (FrameChainOption == "aapcs+leaf")
Features.push_back("+aapcs-frame-chain-leaf");
}

// CMSE: Check for target 8M (for -mcmse to be applicable) is performed later.
Expand Down
31 changes: 18 additions & 13 deletions clang/lib/Driver/ToolChains/Arch/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,6 @@ static void getRISCFeaturesFromMcpu(const Driver &D, const Arg *A,
D.Diag(clang::diag::err_drv_unsupported_option_argument)
<< A->getSpelling() << Mcpu;
}

if (llvm::RISCV::hasFastUnalignedAccess(Mcpu)) {
Features.push_back("+unaligned-scalar-mem");
Features.push_back("+unaligned-vector-mem");
}
}

void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
Expand All @@ -82,6 +77,8 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
if (!getArchFeatures(D, MArch, Features, Args))
return;

bool CPUFastUnaligned = false;

// If users give march and mcpu, get std extension feature from MArch
// and other features (ex. mirco architecture feature) from mcpu
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
Expand All @@ -90,6 +87,9 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
CPU = llvm::sys::getHostCPUName();

getRISCFeaturesFromMcpu(D, A, Triple, CPU, Features);

if (llvm::RISCV::hasFastUnalignedAccess(CPU))
CPUFastUnaligned = true;
}

// Handle features corresponding to "-ffixed-X" options
Expand Down Expand Up @@ -169,18 +169,23 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
Features.push_back("-relax");
}

// Android requires fast unaligned access on RISCV64.
if (Triple.isAndroid()) {
// If -mstrict-align or -mno-strict-align is passed, use it. Otherwise, the
// unaligned-*-mem is enabled if the CPU supports it or the target is
// Android.
if (const Arg *A = Args.getLastArg(options::OPT_mno_strict_align,
options::OPT_mstrict_align)) {
if (A->getOption().matches(options::OPT_mno_strict_align)) {
Features.push_back("+unaligned-scalar-mem");
Features.push_back("+unaligned-vector-mem");
} else {
Features.push_back("-unaligned-scalar-mem");
Features.push_back("-unaligned-vector-mem");
}
} else if (CPUFastUnaligned || Triple.isAndroid()) {
Features.push_back("+unaligned-scalar-mem");
Features.push_back("+unaligned-vector-mem");
}

// -mstrict-align is default, unless -mno-strict-align is specified.
AddTargetFeature(Args, Features, options::OPT_mno_strict_align,
options::OPT_mstrict_align, "unaligned-scalar-mem");
AddTargetFeature(Args, Features, options::OPT_mno_strict_align,
options::OPT_mstrict_align, "unaligned-vector-mem");

// Now add any that the user explicitly requested on the command line,
// which may override the defaults.
handleTargetFeaturesGroup(D, Triple, Args, Features,
Expand Down
14 changes: 14 additions & 0 deletions clang/lib/Driver/ToolChains/BareMetal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
ArgStringList CmdArgs;

auto &TC = static_cast<const toolchains::BareMetal &>(getToolChain());
const Driver &D = getToolChain().getDriver();
const llvm::Triple::ArchType Arch = TC.getArch();
const llvm::Triple &Triple = getToolChain().getEffectiveTriple();

Expand Down Expand Up @@ -466,6 +467,19 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
TC.AddLinkRuntimeLib(Args, CmdArgs);
}

if (D.isUsingLTO()) {
assert(!Inputs.empty() && "Must have at least one input.");
// Find the first filename InputInfo object.
auto Input = llvm::find_if(
Inputs, [](const InputInfo &II) -> bool { return II.isFilename(); });
if (Input == Inputs.end())
// For a very rare case, all of the inputs to the linker are
// InputArg. If that happens, just use the first InputInfo.
Input = Inputs.begin();

addLTOOptions(TC, Args, CmdArgs, Output, *Input,
D.getLTOMode() == LTOK_Thin);
}
if (TC.getTriple().isRISCV())
CmdArgs.push_back("-X");

Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5678,6 +5678,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
case CodeGenOptions::FramePointerKind::None:
FPKeepKindStr = "-mframe-pointer=none";
break;
case CodeGenOptions::FramePointerKind::Reserved:
FPKeepKindStr = "-mframe-pointer=reserved";
break;
case CodeGenOptions::FramePointerKind::NonLeaf:
FPKeepKindStr = "-mframe-pointer=non-leaf";
break;
Expand Down
115 changes: 88 additions & 27 deletions clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,14 @@ static bool useFramePointerForTargetByDefault(const llvm::opt::ArgList &Args,
return true;
}

static bool useLeafFramePointerForTargetByDefault(const llvm::Triple &Triple) {
if (Triple.isAArch64() || Triple.isPS() || Triple.isVE() ||
(Triple.isAndroid() && Triple.isRISCV64()))
return false;

return true;
}

static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) {
switch (Triple.getArch()) {
default:
Expand All @@ -176,38 +184,91 @@ static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) {
}
}

// True if a target-specific option requires the frame chain to be preserved,
// even if new frame records are not created.
static bool mustMaintainValidFrameChain(const llvm::opt::ArgList &Args,
const llvm::Triple &Triple) {
if (Triple.isARM() || Triple.isThumb()) {
// For 32-bit Arm, the -mframe-chain=aapcs and -mframe-chain=aapcs+leaf
// options require the frame pointer register to be reserved (or point to a
// new AAPCS-compilant frame record), even with -fno-omit-frame-pointer.
if (Arg *A = Args.getLastArg(options::OPT_mframe_chain)) {
StringRef V = A->getValue();
return V != "none";
}
return false;
}
return false;
}

// True if a target-specific option causes -fno-omit-frame-pointer to also
// cause frame records to be created in leaf functions.
static bool framePointerImpliesLeafFramePointer(const llvm::opt::ArgList &Args,
const llvm::Triple &Triple) {
if (Triple.isARM() || Triple.isThumb()) {
// For 32-bit Arm, the -mframe-chain=aapcs+leaf option causes the
// -fno-omit-frame-pointer optiion to imply -mno-omit-leaf-frame-pointer,
// but does not by itself imply either option.
if (Arg *A = Args.getLastArg(options::OPT_mframe_chain)) {
StringRef V = A->getValue();
return V == "aapcs+leaf";
}
return false;
}
return false;
}

clang::CodeGenOptions::FramePointerKind
getFramePointerKind(const llvm::opt::ArgList &Args,
const llvm::Triple &Triple) {
// We have 4 states:
// There are three things to consider here:
// * Should a frame record be created for non-leaf functions?
// * Should a frame record be created for leaf functions?
// * Is the frame pointer register reserved, i.e. must it always point to
// either a new, valid frame record or be un-modified?
//
// 00) leaf retained, non-leaf retained
// 01) leaf retained, non-leaf omitted (this is invalid)
// 10) leaf omitted, non-leaf retained
// (what -momit-leaf-frame-pointer was designed for)
// 11) leaf omitted, non-leaf omitted
// Not all combinations of these are valid:
// * It's not useful to have leaf frame records without non-leaf ones.
// * It's not useful to have frame records without reserving the frame
// pointer.
//
// "omit" options taking precedence over "no-omit" options is the only way
// to make 3 valid states representable
llvm::opt::Arg *A =
Args.getLastArg(clang::driver::options::OPT_fomit_frame_pointer,
clang::driver::options::OPT_fno_omit_frame_pointer);

bool OmitFP = A && A->getOption().matches(
clang::driver::options::OPT_fomit_frame_pointer);
bool NoOmitFP = A && A->getOption().matches(
clang::driver::options::OPT_fno_omit_frame_pointer);
bool OmitLeafFP =
Args.hasFlag(clang::driver::options::OPT_momit_leaf_frame_pointer,
clang::driver::options::OPT_mno_omit_leaf_frame_pointer,
Triple.isAArch64() || Triple.isPS() || Triple.isVE() ||
(Triple.isAndroid() && Triple.isRISCV64()));
if (NoOmitFP || mustUseNonLeafFramePointerForTarget(Triple) ||
(!OmitFP && useFramePointerForTargetByDefault(Args, Triple))) {
if (OmitLeafFP)
return clang::CodeGenOptions::FramePointerKind::NonLeaf;
return clang::CodeGenOptions::FramePointerKind::All;
}
// | Non-leaf | Leaf | Reserved |
// | N | N | N | FramePointerKind::None
// | N | N | Y | FramePointerKind::Reserved
// | N | Y | N | Invalid
// | N | Y | Y | Invalid
// | Y | N | N | Invalid
// | Y | N | Y | FramePointerKind::NonLeaf
// | Y | Y | N | Invalid
// | Y | Y | Y | FramePointerKind::All
//
// The FramePointerKind::Reserved case is currently only reachable for Arm,
// which has the -mframe-chain= option which can (in combination with
// -fno-omit-frame-pointer) specify that the frame chain must be valid,
// without requiring new frame records to be created.

bool DefaultFP = useFramePointerForTargetByDefault(Args, Triple);
bool EnableFP =
mustUseNonLeafFramePointerForTarget(Triple) ||
Args.hasFlag(clang::driver::options::OPT_fno_omit_frame_pointer,
clang::driver::options::OPT_fomit_frame_pointer, DefaultFP);

bool DefaultLeafFP =
useLeafFramePointerForTargetByDefault(Triple) ||
(EnableFP && framePointerImpliesLeafFramePointer(Args, Triple));
bool EnableLeafFP = Args.hasFlag(
clang::driver::options::OPT_mno_omit_leaf_frame_pointer,
clang::driver::options::OPT_momit_leaf_frame_pointer, DefaultLeafFP);

bool FPRegReserved = EnableFP || mustMaintainValidFrameChain(Args, Triple);

if (EnableFP) {
if (EnableLeafFP)
return clang::CodeGenOptions::FramePointerKind::All;
return clang::CodeGenOptions::FramePointerKind::NonLeaf;
}
if (FPRegReserved)
return clang::CodeGenOptions::FramePointerKind::Reserved;
return clang::CodeGenOptions::FramePointerKind::None;
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Cuda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -826,7 +826,7 @@ NVPTXToolChain::getSystemGPUArchs(const ArgList &Args) const {
else
Program = GetProgramPath("nvptx-arch");

auto StdoutOrErr = executeToolChainProgram(Program);
auto StdoutOrErr = executeToolChainProgram(Program, /*SecondsToWait=*/10);
if (!StdoutOrErr)
return StdoutOrErr.takeError();

Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/ToolChains/Darwin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3448,6 +3448,7 @@ SanitizerMask Darwin::getSupportedSanitizers() const {
Res |= SanitizerKind::PointerCompare;
Res |= SanitizerKind::PointerSubtract;
Res |= SanitizerKind::Leak;
Res |= SanitizerKind::NumericalStability;
Res |= SanitizerKind::Fuzzer;
Res |= SanitizerKind::FuzzerNoLink;
Res |= SanitizerKind::ObjCCast;
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChains/Flang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,9 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
case CodeGenOptions::FramePointerKind::None:
FPKeepKindStr = "-mframe-pointer=none";
break;
case CodeGenOptions::FramePointerKind::Reserved:
FPKeepKindStr = "-mframe-pointer=reserved";
break;
case CodeGenOptions::FramePointerKind::NonLeaf:
FPKeepKindStr = "-mframe-pointer=non-leaf";
break;
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChains/Linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,9 @@ SanitizerMask Linux::getSupportedSanitizers() const {
if (IsX86_64 || IsAArch64) {
Res |= SanitizerKind::KernelHWAddress;
}
if (IsX86_64 || IsAArch64)
Res |= SanitizerKind::NumericalStability;

// Work around "Cannot represent a difference across sections".
if (getTriple().getArch() == llvm::Triple::ppc64)
Res &= ~SanitizerKind::Function;
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Format/ContinuationIndenter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,11 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
}
return CurrentState.Indent;
}
if (Current.is(TT_TrailingReturnArrow) &&
Previous.isOneOf(tok::kw_noexcept, tok::kw_mutable, tok::kw_constexpr,
tok::kw_consteval, tok::kw_static, TT_AttributeSquare)) {
return ContinuationIndent;
}
if ((Current.isOneOf(tok::r_brace, tok::r_square) ||
(Current.is(tok::greater) && (Style.isProto() || Style.isTableGen()))) &&
State.Stack.size() > 1) {
Expand Down
9 changes: 2 additions & 7 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1358,6 +1358,8 @@ class AnnotatingParser {
Line.First->startsSequence(tok::kw_export, Keywords.kw_module) ||
Line.First->startsSequence(tok::kw_export, Keywords.kw_import)) {
Tok->setType(TT_ModulePartitionColon);
} else if (Line.First->is(tok::kw_asm)) {
Tok->setType(TT_InlineASMColon);
} else if (Contexts.back().ColonIsDictLiteral || Style.isProto()) {
Tok->setType(TT_DictLiteral);
if (Style.Language == FormatStyle::LK_TextProto) {
Expand Down Expand Up @@ -1425,13 +1427,6 @@ class AnnotatingParser {
// This handles a special macro in ObjC code where selectors including
// the colon are passed as macro arguments.
Tok->setType(TT_ObjCMethodExpr);
} else if (Contexts.back().ContextKind == tok::l_paren &&
!Line.InPragmaDirective) {
if (Style.isTableGen() && Contexts.back().IsTableGenDAGArg) {
Tok->setType(TT_TableGenDAGArgListColon);
break;
}
Tok->setType(TT_InlineASMColon);
}
break;
case tok::pipe:
Expand Down
34 changes: 23 additions & 11 deletions clang/lib/Index/CommentToXML.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,8 @@ class CommentASTToXMLConverter :
void visitParagraphComment(const ParagraphComment *C);

void appendParagraphCommentWithKind(const ParagraphComment *C,
StringRef Kind);
StringRef ParagraphKind,
StringRef PrependBodyText);

void visitBlockCommandComment(const BlockCommandComment *C);
void visitParamCommandComment(const ParamCommandComment *C);
Expand Down Expand Up @@ -680,24 +681,27 @@ CommentASTToXMLConverter::visitHTMLEndTagComment(const HTMLEndTagComment *C) {
Result << ">&lt;/" << C->getTagName() << "&gt;</rawHTML>";
}

void
CommentASTToXMLConverter::visitParagraphComment(const ParagraphComment *C) {
appendParagraphCommentWithKind(C, StringRef());
void CommentASTToXMLConverter::visitParagraphComment(
const ParagraphComment *C) {
appendParagraphCommentWithKind(C, StringRef(), StringRef());
}

void CommentASTToXMLConverter::appendParagraphCommentWithKind(
const ParagraphComment *C,
StringRef ParagraphKind) {
if (C->isWhitespace())
const ParagraphComment *C, StringRef ParagraphKind,
StringRef PrependBodyText) {
if (C->isWhitespace() && PrependBodyText.empty())
return;

if (ParagraphKind.empty())
Result << "<Para>";
else
Result << "<Para kind=\"" << ParagraphKind << "\">";

for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
I != E; ++I) {
if (!PrependBodyText.empty())
Result << PrependBodyText << " ";

for (Comment::child_iterator I = C->child_begin(), E = C->child_end(); I != E;
++I) {
visit(*I);
}
Result << "</Para>";
Expand All @@ -706,8 +710,15 @@ void CommentASTToXMLConverter::appendParagraphCommentWithKind(
void CommentASTToXMLConverter::visitBlockCommandComment(
const BlockCommandComment *C) {
StringRef ParagraphKind;
StringRef ExceptionType;

switch (C->getCommandID()) {
const unsigned CommandID = C->getCommandID();
const CommandInfo *Info = Traits.getCommandInfo(CommandID);
if (Info->IsThrowsCommand && C->getNumArgs() > 0) {
ExceptionType = C->getArgText(0);
}

switch (CommandID) {
case CommandTraits::KCI_attention:
case CommandTraits::KCI_author:
case CommandTraits::KCI_authors:
Expand All @@ -732,7 +743,8 @@ void CommentASTToXMLConverter::visitBlockCommandComment(
break;
}

appendParagraphCommentWithKind(C->getParagraph(), ParagraphKind);
appendParagraphCommentWithKind(C->getParagraph(), ParagraphKind,
ExceptionType);
}

void CommentASTToXMLConverter::visitParamCommandComment(
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Index/IndexBody.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
}
return true;
};
bool IsPropCall = Containing && isa<PseudoObjectExpr>(Containing);
bool IsPropCall = isa_and_nonnull<PseudoObjectExpr>(Containing);
// Implicit property message sends are not 'implicit'.
if ((E->isImplicit() || IsPropCall) &&
!(IsPropCall &&
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Lex/PPMacroExpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ void Preprocessor::updateModuleMacroInfo(const IdentifierInfo *II,
bool IsSystemMacro = true;
bool IsAmbiguous = false;
if (auto *MD = Info.MD) {
while (MD && isa<VisibilityMacroDirective>(MD))
while (isa_and_nonnull<VisibilityMacroDirective>(MD))
MD = MD->getPrevious();
if (auto *DMD = dyn_cast_or_null<DefMacroDirective>(MD)) {
MI = DMD->getInfo();
Expand Down
8 changes: 4 additions & 4 deletions clang/lib/Sema/AnalysisBasedWarnings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
if (!live[B->getBlockID()]) {
if (B->pred_begin() == B->pred_end()) {
const Stmt *Term = B->getTerminatorStmt();
if (Term && isa<CXXTryStmt>(Term))
if (isa_and_nonnull<CXXTryStmt>(Term))
// When not adding EH edges from calls, catch clauses
// can otherwise seem dead. Avoid noting them as dead.
count += reachable_code::ScanReachableFromBlock(B, live);
Expand Down Expand Up @@ -1100,7 +1100,7 @@ namespace {
// issue a warn_fallthrough_attr_unreachable for them.
for (const auto *B : *Cfg) {
const Stmt *L = B->getLabel();
if (L && isa<SwitchCase>(L) && ReachableBlocks.insert(B).second)
if (isa_and_nonnull<SwitchCase>(L) && ReachableBlocks.insert(B).second)
BlockQueue.push_back(B);
}

Expand Down Expand Up @@ -1128,7 +1128,7 @@ namespace {
if (!P) continue;

const Stmt *Term = P->getTerminatorStmt();
if (Term && isa<SwitchStmt>(Term))
if (isa_and_nonnull<SwitchStmt>(Term))
continue; // Switch statement, good.

const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(P->getLabel());
Expand Down Expand Up @@ -1327,7 +1327,7 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC,
B = *B->succ_begin();
Term = B->getTerminatorStmt();
}
if (!(B->empty() && Term && isa<BreakStmt>(Term))) {
if (!(B->empty() && isa_and_nonnull<BreakStmt>(Term))) {
Preprocessor &PP = S.getPreprocessor();
StringRef AnnotationSpelling = getFallthroughAttrSpelling(PP, L);
SmallString<64> TextToInsert(AnnotationSpelling);
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Sema/SemaAvailability.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/IdentifierTable.h"
Expand Down Expand Up @@ -46,6 +47,10 @@ static const AvailabilityAttr *getAttrForPlatform(ASTContext &Context,
// Check each AvailabilityAttr to find the one for this platform.
// For multiple attributes with the same platform try to find one for this
// environment.
// The attribute is always on the FunctionDecl, not on the
// FunctionTemplateDecl.
if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
D = FTD->getTemplatedDecl();
for (const auto *A : D->attrs()) {
if (const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
// FIXME: this is copied from CheckAvailability. We should try to
Expand Down
41 changes: 25 additions & 16 deletions clang/lib/Sema/SemaCUDA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1018,24 +1018,33 @@ void SemaCUDA::checkTargetOverload(FunctionDecl *NewFD,
// HD/global functions "exist" in some sense on both the host and device, so
// should have the same implementation on both sides.
if (NewTarget != OldTarget &&
((NewTarget == CUDAFunctionTarget::HostDevice &&
!(getLangOpts().OffloadImplicitHostDeviceTemplates &&
isImplicitHostDeviceFunction(NewFD) &&
OldTarget == CUDAFunctionTarget::Device)) ||
(OldTarget == CUDAFunctionTarget::HostDevice &&
!(getLangOpts().OffloadImplicitHostDeviceTemplates &&
isImplicitHostDeviceFunction(OldFD) &&
NewTarget == CUDAFunctionTarget::Device)) ||
(NewTarget == CUDAFunctionTarget::Global) ||
(OldTarget == CUDAFunctionTarget::Global)) &&
!SemaRef.IsOverload(NewFD, OldFD, /* UseMemberUsingDeclRules = */ false,
/* ConsiderCudaAttrs = */ false)) {
Diag(NewFD->getLocation(), diag::err_cuda_ovl_target)
<< llvm::to_underlying(NewTarget) << NewFD->getDeclName()
<< llvm::to_underlying(OldTarget) << OldFD;
Diag(OldFD->getLocation(), diag::note_previous_declaration);
NewFD->setInvalidDecl();
break;
if ((NewTarget == CUDAFunctionTarget::HostDevice &&
!(getLangOpts().OffloadImplicitHostDeviceTemplates &&
isImplicitHostDeviceFunction(NewFD) &&
OldTarget == CUDAFunctionTarget::Device)) ||
(OldTarget == CUDAFunctionTarget::HostDevice &&
!(getLangOpts().OffloadImplicitHostDeviceTemplates &&
isImplicitHostDeviceFunction(OldFD) &&
NewTarget == CUDAFunctionTarget::Device)) ||
(NewTarget == CUDAFunctionTarget::Global) ||
(OldTarget == CUDAFunctionTarget::Global)) {
Diag(NewFD->getLocation(), diag::err_cuda_ovl_target)
<< llvm::to_underlying(NewTarget) << NewFD->getDeclName()
<< llvm::to_underlying(OldTarget) << OldFD;
Diag(OldFD->getLocation(), diag::note_previous_declaration);
NewFD->setInvalidDecl();
break;
}
if ((NewTarget == CUDAFunctionTarget::Host &&
OldTarget == CUDAFunctionTarget::Device) ||
(NewTarget == CUDAFunctionTarget::Device &&
OldTarget == CUDAFunctionTarget::Host)) {
Diag(NewFD->getLocation(), diag::warn_offload_incompatible_redeclare)
<< llvm::to_underlying(NewTarget) << llvm::to_underlying(OldTarget);
Diag(OldFD->getLocation(), diag::note_previous_declaration);
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaCXXScopeSpec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
R.setBegin(SS.getRange().getBegin());

Diag(CCLoc, diag::err_non_type_template_in_nested_name_specifier)
<< (TD && isa<VarTemplateDecl>(TD)) << Template << R;
<< isa_and_nonnull<VarTemplateDecl>(TD) << Template << R;
NoteAllFoundTemplates(Template);
return true;
}
Expand Down
10 changes: 5 additions & 5 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3839,11 +3839,11 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
if (CallType != VariadicDoesNotApply &&
(!FD || FD->getBuiltinID() != Builtin::BI__noop)) {
unsigned NumParams = Proto ? Proto->getNumParams()
: FDecl && isa<FunctionDecl>(FDecl)
? cast<FunctionDecl>(FDecl)->getNumParams()
: FDecl && isa<ObjCMethodDecl>(FDecl)
? cast<ObjCMethodDecl>(FDecl)->param_size()
: 0;
: isa_and_nonnull<FunctionDecl>(FDecl)
? cast<FunctionDecl>(FDecl)->getNumParams()
: isa_and_nonnull<ObjCMethodDecl>(FDecl)
? cast<ObjCMethodDecl>(FDecl)->param_size()
: 0;

for (unsigned ArgIdx = NumParams; ArgIdx < Args.size(); ++ArgIdx) {
// Args[ArgIdx] can be null in malformed code.
Expand Down
41 changes: 28 additions & 13 deletions clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1806,6 +1806,7 @@ static unsigned getRecordDiagFromTagKind(TagTypeKind Tag) {
static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
Stmt *Body,
Sema::CheckConstexprKind Kind);
static bool CheckConstexprMissingReturn(Sema &SemaRef, const FunctionDecl *Dcl);

// Check whether a function declaration satisfies the requirements of a
// constexpr function definition or a constexpr constructor definition. If so,
Expand Down Expand Up @@ -2411,20 +2412,9 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
}
} else {
if (ReturnStmts.empty()) {
// C++1y doesn't require constexpr functions to contain a 'return'
// statement. We still do, unless the return type might be void, because
// otherwise if there's no return statement, the function cannot
// be used in a core constant expression.
bool OK = SemaRef.getLangOpts().CPlusPlus14 &&
(Dcl->getReturnType()->isVoidType() ||
Dcl->getReturnType()->isDependentType());
switch (Kind) {
case Sema::CheckConstexprKind::Diagnose:
SemaRef.Diag(Dcl->getLocation(),
OK ? diag::warn_cxx11_compat_constexpr_body_no_return
: diag::err_constexpr_body_no_return)
<< Dcl->isConsteval();
if (!OK)
if (!CheckConstexprMissingReturn(SemaRef, Dcl))
return false;
break;

Expand Down Expand Up @@ -2494,6 +2484,28 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
return true;
}

static bool CheckConstexprMissingReturn(Sema &SemaRef,
const FunctionDecl *Dcl) {
bool IsVoidOrDependentType = Dcl->getReturnType()->isVoidType() ||
Dcl->getReturnType()->isDependentType();
// Skip emitting a missing return error diagnostic for non-void functions
// since C++23 no longer mandates constexpr functions to yield constant
// expressions.
if (SemaRef.getLangOpts().CPlusPlus23 && !IsVoidOrDependentType)
return true;

// C++14 doesn't require constexpr functions to contain a 'return'
// statement. We still do, unless the return type might be void, because
// otherwise if there's no return statement, the function cannot
// be used in a core constant expression.
bool OK = SemaRef.getLangOpts().CPlusPlus14 && IsVoidOrDependentType;
SemaRef.Diag(Dcl->getLocation(),
OK ? diag::warn_cxx11_compat_constexpr_body_no_return
: diag::err_constexpr_body_no_return)
<< Dcl->isConsteval();
return OK;
}

bool Sema::CheckImmediateEscalatingFunctionDefinition(
FunctionDecl *FD, const sema::FunctionScopeInfo *FSI) {
if (!getLangOpts().CPlusPlus20 || !FD->isImmediateEscalating())
Expand Down Expand Up @@ -13079,7 +13091,10 @@ NamedDecl *Sema::BuildUsingDeclaration(
// A using-declaration shall not name a namespace.
if (R.getAsSingle<NamespaceDecl>()) {
Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace)
<< SS.getRange();
<< SS.getRange();
// Suggest using 'using namespace ...' instead.
Diag(SS.getBeginLoc(), diag::note_namespace_using_decl)
<< FixItHint::CreateInsertion(SS.getBeginLoc(), "namespace ");
return BuildInvalid();
}

Expand Down
Loading