87 changes: 71 additions & 16 deletions clang/include/clang/AST/OpenACCClause.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,33 +156,88 @@ class OpenACCSelfClause : public OpenACCClauseWithCondition {
Expr *ConditionExpr, SourceLocation EndLoc);
};

/// Represents oen of a handful of classes that have a single integer
/// Represents a clause that has one or more IntExprs. It does not own the
/// IntExprs, but provides 'children' and other accessors.
class OpenACCClauseWithIntExprs : public OpenACCClauseWithParams {
MutableArrayRef<Expr *> IntExprs;

protected:
OpenACCClauseWithIntExprs(OpenACCClauseKind K, SourceLocation BeginLoc,
SourceLocation LParenLoc, SourceLocation EndLoc)
: OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc) {}

/// Used only for initialization, the leaf class can initialize this to
/// trailing storage.
void setIntExprs(MutableArrayRef<Expr *> NewIntExprs) {
assert(IntExprs.empty() && "Cannot change IntExprs list");
IntExprs = NewIntExprs;
}

/// Gets the entire list of integer expressions, but leave it to the
/// individual clauses to expose this how they'd like.
llvm::ArrayRef<Expr *> getIntExprs() const { return IntExprs; }

public:
child_range children() {
return child_range(reinterpret_cast<Stmt **>(IntExprs.begin()),
reinterpret_cast<Stmt **>(IntExprs.end()));
}

const_child_range children() const {
child_range Children =
const_cast<OpenACCClauseWithIntExprs *>(this)->children();
return const_child_range(Children.begin(), Children.end());
}
};

class OpenACCNumGangsClause final
: public OpenACCClauseWithIntExprs,
public llvm::TrailingObjects<OpenACCNumGangsClause, Expr *> {

OpenACCNumGangsClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> IntExprs, SourceLocation EndLoc)
: OpenACCClauseWithIntExprs(OpenACCClauseKind::NumGangs, BeginLoc,
LParenLoc, EndLoc) {
std::uninitialized_copy(IntExprs.begin(), IntExprs.end(),
getTrailingObjects<Expr *>());
setIntExprs(MutableArrayRef(getTrailingObjects<Expr *>(), IntExprs.size()));
}

public:
static OpenACCNumGangsClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);

llvm::ArrayRef<Expr *> getIntExprs() {
return OpenACCClauseWithIntExprs::getIntExprs();
}

llvm::ArrayRef<Expr *> getIntExprs() const {
return OpenACCClauseWithIntExprs::getIntExprs();
}
};

/// Represents one of a handful of clauses that have a single integer
/// expression.
class OpenACCClauseWithSingleIntExpr : public OpenACCClauseWithParams {
class OpenACCClauseWithSingleIntExpr : public OpenACCClauseWithIntExprs {
Expr *IntExpr;

protected:
OpenACCClauseWithSingleIntExpr(OpenACCClauseKind K, SourceLocation BeginLoc,
SourceLocation LParenLoc, Expr *IntExpr,
SourceLocation EndLoc)
: OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc),
IntExpr(IntExpr) {}
: OpenACCClauseWithIntExprs(K, BeginLoc, LParenLoc, EndLoc),
IntExpr(IntExpr) {
setIntExprs(MutableArrayRef<Expr *>{&this->IntExpr, 1});
}

public:
bool hasIntExpr() const { return IntExpr; }
const Expr *getIntExpr() const { return IntExpr; }

Expr *getIntExpr() { return IntExpr; };

child_range children() {
return child_range(reinterpret_cast<Stmt **>(&IntExpr),
reinterpret_cast<Stmt **>(&IntExpr + 1));
bool hasIntExpr() const { return !getIntExprs().empty(); }
const Expr *getIntExpr() const {
return hasIntExpr() ? getIntExprs()[0] : nullptr;
}

const_child_range children() const {
return const_child_range(reinterpret_cast<Stmt *const *>(&IntExpr),
reinterpret_cast<Stmt *const *>(&IntExpr + 1));
}
Expr *getIntExpr() { return hasIntExpr() ? getIntExprs()[0] : nullptr; };
};

class OpenACCNumWorkersClause : public OpenACCClauseWithSingleIntExpr {
Expand Down
15 changes: 15 additions & 0 deletions clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,21 @@ class Environment {
Environment::ValueModel &Model,
ExprJoinBehavior ExprBehavior);

/// Returns a value that approximates both `Val1` and `Val2`, or null if no
/// such value can be produced.
///
/// `Env1` and `Env2` can be used to query child values and path condition
/// implications of `Val1` and `Val2` respectively. The joined value will be
/// produced in `JoinedEnv`.
///
/// Requirements:
///
/// `Val1` and `Val2` must model values of type `Type`.
static Value *joinValues(QualType Ty, Value *Val1, const Environment &Env1,
Value *Val2, const Environment &Env2,
Environment &JoinedEnv,
Environment::ValueModel &Model);

/// Widens the environment point-wise, using `PrevEnv` as needed to inform the
/// approximation.
///
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Analysis/FlowSensitive/Transfer.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ class StmtToEnvMap {
/// Requirements:
///
/// `S` must not be `ParenExpr` or `ExprWithCleanups`.
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env);
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env,
Environment::ValueModel &Model);

} // namespace dataflow
} // namespace clang
Expand Down
10 changes: 5 additions & 5 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -368,8 +368,8 @@ class Clang<string name, bit allowInC = 1, int version = 1>
bit AllowInC = allowInC;
}

// HLSL Semantic spellings
class HLSLSemantic<string name> : Spelling<name, "HLSLSemantic">;
// HLSL Annotation spellings
class HLSLAnnotation<string name> : Spelling<name, "HLSLAnnotation">;

class Accessor<string name, list<Spelling> spellings> {
string Name = name;
Expand Down Expand Up @@ -4358,22 +4358,22 @@ def HLSLNumThreads: InheritableAttr {
}

def HLSLSV_GroupIndex: HLSLAnnotationAttr {
let Spellings = [HLSLSemantic<"SV_GroupIndex">];
let Spellings = [HLSLAnnotation<"SV_GroupIndex">];
let Subjects = SubjectList<[ParmVar, GlobalVar]>;
let LangOpts = [HLSL];
let Documentation = [HLSLSV_GroupIndexDocs];
}

def HLSLResourceBinding: InheritableAttr {
let Spellings = [HLSLSemantic<"register">];
let Spellings = [HLSLAnnotation<"register">];
let Subjects = SubjectList<[HLSLBufferObj, ExternalGlobalVar]>;
let LangOpts = [HLSL];
let Args = [StringArgument<"Slot">, StringArgument<"Space", 1>];
let Documentation = [HLSLResourceBindingDocs];
}

def HLSLSV_DispatchThreadID: HLSLAnnotationAttr {
let Spellings = [HLSLSemantic<"SV_DispatchThreadID">];
let Spellings = [HLSLAnnotation<"SV_DispatchThreadID">];
let Subjects = SubjectList<[ParmVar, Field]>;
let LangOpts = [HLSL];
let Documentation = [HLSLSV_DispatchThreadIDDocs];
Expand Down
6 changes: 3 additions & 3 deletions clang/include/clang/Basic/AttributeCommonInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ class AttributeCommonInfo {
/// Context-sensitive version of a keyword attribute.
AS_ContextSensitiveKeyword,

/// <vardecl> : <semantic>
AS_HLSLSemantic,
/// <vardecl> : <annotation>
AS_HLSLAnnotation,

/// The attibute has no source code manifestation and is only created
/// implicitly.
Expand Down Expand Up @@ -120,7 +120,7 @@ class AttributeCommonInfo {
}
static Form Pragma() { return AS_Pragma; }
static Form ContextSensitiveKeyword() { return AS_ContextSensitiveKeyword; }
static Form HLSLSemantic() { return AS_HLSLSemantic; }
static Form HLSLAnnotation() { return AS_HLSLAnnotation; }
static Form Implicit() { return AS_Implicit; }

private:
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticCommonKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,9 @@ def err_cxx23_size_t_suffix: Error<
def err_size_t_literal_too_large: Error<
"%select{signed |}0'size_t' literal is out of range of possible "
"%select{signed |}0'size_t' values">;
def ext_cxx_bitint_suffix : Extension<
"'_BitInt' suffix for literals is a Clang extension">,
InGroup<BitIntExtension>;
def ext_c23_bitint_suffix : ExtWarn<
"'_BitInt' suffix for literals is a C23 extension">,
InGroup<C23>;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -1520,5 +1520,8 @@ def UnsafeBufferUsage : DiagGroup<"unsafe-buffer-usage", [UnsafeBufferUsageInCon
// Warnings and notes InstallAPI verification.
def InstallAPIViolation : DiagGroup<"installapi-violation">;

// Warnings related to _BitInt extension
def BitIntExtension : DiagGroup<"bit-int-extension">;

// Warnings about misuse of ExtractAPI options.
def ExtractAPIMisuse : DiagGroup<"extractapi-misuse">;
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -1654,7 +1654,7 @@ def warn_ext_int_deprecated : Warning<
"'_ExtInt' is deprecated; use '_BitInt' instead">, InGroup<DeprecatedType>;
def ext_bit_int : Extension<
"'_BitInt' in %select{C17 and earlier|C++}0 is a Clang extension">,
InGroup<DiagGroup<"bit-int-extension">>;
InGroup<BitIntExtension>;
} // end of Parse Issue category.

let CategoryName = "Modules Issue" in {
Expand Down
11 changes: 8 additions & 3 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ def err_expr_not_cce : Error<
"call to 'size()'|call to 'data()'}0 is not a constant expression">;
def ext_cce_narrowing : ExtWarn<
"%select{case value|enumerator value|non-type template argument|"
"array size|explicit specifier argument|noexcept specifier argument}0 "
"%select{cannot be narrowed from type %2 to %3|"
"evaluates to %2, which cannot be narrowed to type %3}1">,
"array size|explicit specifier argument|noexcept specifier argument|"
"call to 'size()'|call to 'data()'}0 %select{cannot be narrowed from "
"type %2 to %3|evaluates to %2, which cannot be narrowed to type %3}1">,
InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
def err_ice_not_integral : Error<
"%select{integer|integral}1 constant expression must have "
Expand Down Expand Up @@ -12293,4 +12293,9 @@ def note_acc_int_expr_conversion
: Note<"conversion to %select{integral|enumeration}0 type %1">;
def err_acc_int_expr_multiple_conversions
: Error<"multiple conversions from expression type %0 to an integral type">;
def err_acc_num_gangs_num_args
: Error<"%select{no|too many}0 integer expression arguments provided to "
"OpenACC 'num_gangs' "
"%select{|clause: '%1' directive expects maximum of %2, %3 were "
"provided}0">;
} // end of sema component.
11 changes: 11 additions & 0 deletions clang/include/clang/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,8 @@ class FPOptions {
/// Return difference with the given option set.
FPOptionsOverride getChangesFrom(const FPOptions &Base) const;

void applyChanges(FPOptionsOverride FPO);

// We can define most of the accessors automatically:
#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
TYPE get##NAME() const { \
Expand Down Expand Up @@ -959,6 +961,11 @@ class FPOptionsOverride {
setAllowFPContractAcrossStatement();
}

void setDisallowOptimizations() {
setFPPreciseEnabled(true);
setDisallowFPContract();
}

storage_type getAsOpaqueInt() const {
return (static_cast<storage_type>(Options.getAsOpaqueInt())
<< FPOptions::StorageBitSize) |
Expand Down Expand Up @@ -1015,6 +1022,10 @@ inline FPOptionsOverride FPOptions::getChangesFrom(const FPOptions &Base) const
return getChangesSlow(Base);
}

inline void FPOptions::applyChanges(FPOptionsOverride FPO) {
*this = FPO.applyOverrides(*this);
}

/// Describes the kind of translation unit being processed.
enum TranslationUnitKind {
/// The translation unit is a complete translation unit.
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/OpenACCClauses.def
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
VISIT_CLAUSE(Default)
VISIT_CLAUSE(If)
VISIT_CLAUSE(Self)
VISIT_CLAUSE(NumGangs)
VISIT_CLAUSE(NumWorkers)
VISIT_CLAUSE(VectorLength)

Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -5041,6 +5041,12 @@ def maix_small_local_exec_tls : Flag<["-"], "maix-small-local-exec-tls">,
"where the offset from the TLS base is encoded as an "
"immediate operand (AIX 64-bit only). "
"This access sequence is not used for variables larger than 32KB.">;
def maix_small_local_dynamic_tls : Flag<["-"], "maix-small-local-dynamic-tls">,
Group<m_ppc_Features_Group>,
HelpText<"Produce a faster access sequence for local-dynamic TLS variables "
"where the offset from the TLS base is encoded as an "
"immediate operand (AIX 64-bit only). "
"This access sequence is not used for variables larger than 32KB.">;
def maix_struct_return : Flag<["-"], "maix-struct-return">,
Group<m_Group>, Visibility<[ClangOption, CC1Option]>,
HelpText<"Return all structs in memory (PPC32 only)">,
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Lex/LiteralSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ class NumericLiteralParser {
bool isFloat128 : 1; // 1.0q
bool isFract : 1; // 1.0hr/r/lr/uhr/ur/ulr
bool isAccum : 1; // 1.0hk/k/lk/uhk/uk/ulk
bool isBitInt : 1; // 1wb, 1uwb (C23)
bool isBitInt : 1; // 1wb, 1uwb (C23) or 1__wb, 1__uwb (Clang extension in C++
// mode)
uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64.


Expand Down
60 changes: 48 additions & 12 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,15 @@ class Parser : public CodeCompletionHandler {
/// top-level declaration is finished.
SmallVector<TemplateIdAnnotation *, 16> TemplateIds;

/// Don't destroy template annotations in MaybeDestroyTemplateIds even if
/// we're at the end of a declaration. Instead, we defer the destruction until
/// after a top-level declaration.
/// Use DelayTemplateIdDestructionRAII rather than setting it directly.
bool DelayTemplateIdDestruction = false;

void MaybeDestroyTemplateIds() {
if (DelayTemplateIdDestruction)
return;
if (!TemplateIds.empty() &&
(Tok.is(tok::eof) || !PP.mightHavePendingAnnotationTokens()))
DestroyTemplateIds();
Expand All @@ -329,6 +337,22 @@ class Parser : public CodeCompletionHandler {
~DestroyTemplateIdAnnotationsRAIIObj() { Self.MaybeDestroyTemplateIds(); }
};

struct DelayTemplateIdDestructionRAII {
Parser &Self;
bool PrevDelayTemplateIdDestruction;

DelayTemplateIdDestructionRAII(Parser &Self,
bool DelayTemplateIdDestruction) noexcept
: Self(Self),
PrevDelayTemplateIdDestruction(Self.DelayTemplateIdDestruction) {
Self.DelayTemplateIdDestruction = DelayTemplateIdDestruction;
}

~DelayTemplateIdDestructionRAII() noexcept {
Self.DelayTemplateIdDestruction = PrevDelayTemplateIdDestruction;
}
};

/// Identifiers which have been declared within a tentative parse.
SmallVector<const IdentifierInfo *, 8> TentativelyDeclaredIdentifiers;

Expand Down Expand Up @@ -2967,25 +2991,25 @@ class Parser : public CodeCompletionHandler {
Sema::AttributeCompletion Completion = Sema::AttributeCompletion::None,
const IdentifierInfo *EnclosingScope = nullptr);

void MaybeParseHLSLSemantics(Declarator &D,
SourceLocation *EndLoc = nullptr) {
assert(getLangOpts().HLSL && "MaybeParseHLSLSemantics is for HLSL only");
void MaybeParseHLSLAnnotations(Declarator &D,
SourceLocation *EndLoc = nullptr) {
assert(getLangOpts().HLSL && "MaybeParseHLSLAnnotations is for HLSL only");
if (Tok.is(tok::colon)) {
ParsedAttributes Attrs(AttrFactory);
ParseHLSLSemantics(Attrs, EndLoc);
ParseHLSLAnnotations(Attrs, EndLoc);
D.takeAttributes(Attrs);
}
}

void MaybeParseHLSLSemantics(ParsedAttributes &Attrs,
SourceLocation *EndLoc = nullptr) {
assert(getLangOpts().HLSL && "MaybeParseHLSLSemantics is for HLSL only");
void MaybeParseHLSLAnnotations(ParsedAttributes &Attrs,
SourceLocation *EndLoc = nullptr) {
assert(getLangOpts().HLSL && "MaybeParseHLSLAnnotations is for HLSL only");
if (getLangOpts().HLSL && Tok.is(tok::colon))
ParseHLSLSemantics(Attrs, EndLoc);
ParseHLSLAnnotations(Attrs, EndLoc);
}

void ParseHLSLSemantics(ParsedAttributes &Attrs,
SourceLocation *EndLoc = nullptr);
void ParseHLSLAnnotations(ParsedAttributes &Attrs,
SourceLocation *EndLoc = nullptr);
Decl *ParseHLSLBuffer(SourceLocation &DeclEnd);

void MaybeParseMicrosoftAttributes(ParsedAttributes &Attrs) {
Expand Down Expand Up @@ -3644,10 +3668,22 @@ class Parser : public CodeCompletionHandler {
/// Parses the clause of the 'bind' argument, which can be a string literal or
/// an ID expression.
ExprResult ParseOpenACCBindClauseArgument();

/// A type to represent the state of parsing after an attempt to parse an
/// OpenACC int-expr. This is useful to determine whether an int-expr list can
/// continue parsing after a failed int-expr.
using OpenACCIntExprParseResult =
std::pair<ExprResult, OpenACCParseCanContinue>;
/// Parses the clause kind of 'int-expr', which can be any integral
/// expression.
ExprResult ParseOpenACCIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
SourceLocation Loc);
OpenACCIntExprParseResult ParseOpenACCIntExpr(OpenACCDirectiveKind DK,
OpenACCClauseKind CK,
SourceLocation Loc);
/// Parses the argument list for 'num_gangs', which allows up to 3
/// 'int-expr's.
bool ParseOpenACCIntExprList(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
SourceLocation Loc,
llvm::SmallVectorImpl<Expr *> &IntExprs);
/// Parses the 'device-type-list', which is a list of identifiers.
bool ParseOpenACCDeviceTypeList();
/// Parses the 'async-argument', which is an integral value with two
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Sema/MultiplexExternalSemaSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class MultiplexExternalSemaSource : public ExternalSemaSource {

/// Resolve a declaration ID into a declaration, potentially
/// building a new declaration.
Decl *GetExternalDecl(uint32_t ID) override;
Decl *GetExternalDecl(Decl::DeclID ID) override;

/// Complete the redeclaration chain if it's been extended since the
/// previous generation of the AST source.
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -3084,6 +3084,7 @@ class Sema final : public SemaBase {
Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D,
SkipBodyInfo *SkipBody = nullptr,
FnBodyKind BodyKind = FnBodyKind::Other);
void applyFunctionAttributesBeforeParsingBody(Decl *FD);

/// Determine whether we can delay parsing the body of a function or
/// function template until it is used, assuming we don't care about emitting
Expand Down
16 changes: 13 additions & 3 deletions clang/include/clang/Sema/SemaOpenACC.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,16 @@ class SemaOpenACC : public SemaBase {
}

unsigned getNumIntExprs() const {
assert((ClauseKind == OpenACCClauseKind::NumWorkers ||
assert((ClauseKind == OpenACCClauseKind::NumGangs ||
ClauseKind == OpenACCClauseKind::NumWorkers ||
ClauseKind == OpenACCClauseKind::VectorLength) &&
"Parsed clause kind does not have a int exprs");
return std::get<IntExprDetails>(Details).IntExprs.size();
}

ArrayRef<Expr *> getIntExprs() {
assert((ClauseKind == OpenACCClauseKind::NumWorkers ||
assert((ClauseKind == OpenACCClauseKind::NumGangs ||
ClauseKind == OpenACCClauseKind::NumWorkers ||
ClauseKind == OpenACCClauseKind::VectorLength) &&
"Parsed clause kind does not have a int exprs");
return std::get<IntExprDetails>(Details).IntExprs;
Expand Down Expand Up @@ -134,11 +136,19 @@ class SemaOpenACC : public SemaBase {
}

void setIntExprDetails(ArrayRef<Expr *> IntExprs) {
assert((ClauseKind == OpenACCClauseKind::NumWorkers ||
assert((ClauseKind == OpenACCClauseKind::NumGangs ||
ClauseKind == OpenACCClauseKind::NumWorkers ||
ClauseKind == OpenACCClauseKind::VectorLength) &&
"Parsed clause kind does not have a int exprs");
Details = IntExprDetails{{IntExprs.begin(), IntExprs.end()}};
}
void setIntExprDetails(llvm::SmallVector<Expr *> &&IntExprs) {
assert((ClauseKind == OpenACCClauseKind::NumGangs ||
ClauseKind == OpenACCClauseKind::NumWorkers ||
ClauseKind == OpenACCClauseKind::VectorLength) &&
"Parsed clause kind does not have a int exprs");
Details = IntExprDetails{IntExprs};
}
};

SemaOpenACC(Sema &S);
Expand Down
131 changes: 98 additions & 33 deletions clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,85 @@ using IdentifierID = uint32_t;
/// discovery), with values below NUM_PREDEF_DECL_IDS being reserved.
/// At the start of a chain of precompiled headers, declaration ID 1 is
/// used for the translation unit declaration.
///
/// FIXME: Merge with Decl::DeclID
using DeclID = uint32_t;

// FIXME: Turn these into classes so we can have some type safety when
// we go from local ID to global and vice-versa.
using LocalDeclID = DeclID;
using GlobalDeclID = DeclID;
class LocalDeclID {
public:
explicit LocalDeclID(DeclID ID) : ID(ID) {}

DeclID get() const { return ID; }

private:
DeclID ID;
};

/// Wrapper class for DeclID. This is helpful to not mix the use of LocalDeclID
/// and GlobalDeclID to improve the type safety.
class GlobalDeclID {
public:
GlobalDeclID() : ID(0) {}
explicit GlobalDeclID(DeclID ID) : ID(ID) {}

DeclID get() const { return ID; }

explicit operator DeclID() const { return ID; }

friend bool operator==(const GlobalDeclID &LHS, const GlobalDeclID &RHS) {
return LHS.ID == RHS.ID;
}
friend bool operator!=(const GlobalDeclID &LHS, const GlobalDeclID &RHS) {
return LHS.ID != RHS.ID;
}
// We may sort the global decl ID.
friend bool operator<(const GlobalDeclID &LHS, const GlobalDeclID &RHS) {
return LHS.ID < RHS.ID;
}
friend bool operator>(const GlobalDeclID &LHS, const GlobalDeclID &RHS) {
return LHS.ID > RHS.ID;
}
friend bool operator<=(const GlobalDeclID &LHS, const GlobalDeclID &RHS) {
return LHS.ID <= RHS.ID;
}
friend bool operator>=(const GlobalDeclID &LHS, const GlobalDeclID &RHS) {
return LHS.ID >= RHS.ID;
}

private:
DeclID ID;
};

/// A helper iterator adaptor to convert the iterators to `SmallVector<DeclID>`
/// to the iterators to `SmallVector<GlobalDeclID>`.
class GlobalDeclIDIterator
: public llvm::iterator_adaptor_base<GlobalDeclIDIterator, const DeclID *,
std::forward_iterator_tag,
GlobalDeclID> {
public:
GlobalDeclIDIterator() : iterator_adaptor_base(nullptr) {}

GlobalDeclIDIterator(const DeclID *ID) : iterator_adaptor_base(ID) {}

value_type operator*() const { return GlobalDeclID(*I); }

bool operator==(const GlobalDeclIDIterator &RHS) const { return I == RHS.I; }
};

/// A helper iterator adaptor to convert the iterators to
/// `SmallVector<GlobalDeclID>` to the iterators to `SmallVector<DeclID>`.
class DeclIDIterator
: public llvm::iterator_adaptor_base<DeclIDIterator, const GlobalDeclID *,
std::forward_iterator_tag, DeclID> {
public:
DeclIDIterator() : iterator_adaptor_base(nullptr) {}

DeclIDIterator(const GlobalDeclID *ID) : iterator_adaptor_base(ID) {}

value_type operator*() const { return DeclID(*I); }

bool operator==(const DeclIDIterator &RHS) const { return I == RHS.I; }
};

/// An ID number that refers to a type in an AST file.
///
Expand Down Expand Up @@ -2056,35 +2129,6 @@ enum CtorInitializerType {
/// Kinds of cleanup objects owned by ExprWithCleanups.
enum CleanupObjectKind { COK_Block, COK_CompoundLiteral };

/// Describes the redeclarations of a declaration.
struct LocalRedeclarationsInfo {
// The ID of the first declaration
DeclID FirstID;

// Offset into the array of redeclaration chains.
unsigned Offset;

friend bool operator<(const LocalRedeclarationsInfo &X,
const LocalRedeclarationsInfo &Y) {
return X.FirstID < Y.FirstID;
}

friend bool operator>(const LocalRedeclarationsInfo &X,
const LocalRedeclarationsInfo &Y) {
return X.FirstID > Y.FirstID;
}

friend bool operator<=(const LocalRedeclarationsInfo &X,
const LocalRedeclarationsInfo &Y) {
return X.FirstID <= Y.FirstID;
}

friend bool operator>=(const LocalRedeclarationsInfo &X,
const LocalRedeclarationsInfo &Y) {
return X.FirstID >= Y.FirstID;
}
};

/// Describes the categories of an Objective-C class.
struct ObjCCategoriesInfo {
// The ID of the definition
Expand Down Expand Up @@ -2187,6 +2231,27 @@ template <> struct DenseMapInfo<clang::serialization::DeclarationNameKey> {
}
};

template <> struct DenseMapInfo<clang::serialization::GlobalDeclID> {
using DeclID = clang::serialization::DeclID;
using GlobalDeclID = clang::serialization::GlobalDeclID;

static GlobalDeclID getEmptyKey() {
return GlobalDeclID(DenseMapInfo<DeclID>::getEmptyKey());
}

static GlobalDeclID getTombstoneKey() {
return GlobalDeclID(DenseMapInfo<DeclID>::getTombstoneKey());
}

static unsigned getHashValue(const GlobalDeclID &Key) {
return DenseMapInfo<DeclID>::getHashValue(Key.get());
}

static bool isEqual(const GlobalDeclID &L, const GlobalDeclID &R) {
return L == R;
}
};

} // namespace llvm

#endif // LLVM_CLANG_SERIALIZATION_ASTBITCODES_H
98 changes: 59 additions & 39 deletions clang/include/clang/Serialization/ASTReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ class ASTReader
static_assert(std::is_same_v<serialization::DeclID, Decl::DeclID>);

using GlobalDeclMapType =
ContinuousRangeMap<serialization::DeclID, ModuleFile *, 4>;
ContinuousRangeMap<serialization::GlobalDeclID, ModuleFile *, 4>;

/// Mapping from global declaration IDs to the module in which the
/// declaration resides.
Expand All @@ -513,14 +513,14 @@ class ASTReader
using FileOffset = std::pair<ModuleFile *, uint64_t>;
using FileOffsetsTy = SmallVector<FileOffset, 2>;
using DeclUpdateOffsetsMap =
llvm::DenseMap<serialization::DeclID, FileOffsetsTy>;
llvm::DenseMap<serialization::GlobalDeclID, FileOffsetsTy>;

/// Declarations that have modifications residing in a later file
/// in the chain.
DeclUpdateOffsetsMap DeclUpdateOffsets;

using DelayedNamespaceOffsetMapTy = llvm::DenseMap<
serialization::DeclID,
serialization::GlobalDeclID,
std::pair</*LexicalOffset*/ uint64_t, /*VisibleOffset*/ uint64_t>>;

/// Mapping from global declaration IDs to the lexical and visible block
Expand Down Expand Up @@ -606,7 +606,11 @@ class ASTReader

/// An array of lexical contents of a declaration context, as a sequence of
/// Decl::Kind, DeclID pairs.
using LexicalContents = ArrayRef<llvm::support::unaligned_uint32_t>;
using unalighed_decl_id_t =
llvm::support::detail::packed_endian_specific_integral<
serialization::DeclID, llvm::endianness::native,
llvm::support::unaligned>;
using LexicalContents = ArrayRef<unalighed_decl_id_t>;

/// Map from a DeclContext to its lexical contents.
llvm::DenseMap<const DeclContext*, std::pair<ModuleFile*, LexicalContents>>
Expand All @@ -631,7 +635,7 @@ class ASTReader

/// Updates to the visible declarations of declaration contexts that
/// haven't been loaded yet.
llvm::DenseMap<serialization::DeclID, DeclContextVisibleUpdates>
llvm::DenseMap<serialization::GlobalDeclID, DeclContextVisibleUpdates>
PendingVisibleUpdates;

/// The set of C++ or Objective-C classes that have forward
Expand All @@ -658,7 +662,8 @@ class ASTReader
/// Read the record that describes the visible contents of a DC.
bool ReadVisibleDeclContextStorage(ModuleFile &M,
llvm::BitstreamCursor &Cursor,
uint64_t Offset, serialization::DeclID ID);
uint64_t Offset,
serialization::GlobalDeclID ID);

/// A vector containing identifiers that have already been
/// loaded.
Expand Down Expand Up @@ -811,29 +816,38 @@ class ASTReader
/// This contains the data loaded from all EAGERLY_DESERIALIZED_DECLS blocks
/// in the chain. The referenced declarations are deserialized and passed to
/// the consumer eagerly.
SmallVector<serialization::DeclID, 16> EagerlyDeserializedDecls;
SmallVector<serialization::GlobalDeclID, 16> EagerlyDeserializedDecls;

/// The IDs of all tentative definitions stored in the chain.
///
/// Sema keeps track of all tentative definitions in a TU because it has to
/// complete them and pass them on to CodeGen. Thus, tentative definitions in
/// the PCH chain must be eagerly deserialized.
SmallVector<serialization::DeclID, 16> TentativeDefinitions;
SmallVector<serialization::GlobalDeclID, 16> TentativeDefinitions;

/// The IDs of all CXXRecordDecls stored in the chain whose VTables are
/// used.
///
/// CodeGen has to emit VTables for these records, so they have to be eagerly
/// deserialized.
SmallVector<serialization::DeclID, 64> VTableUses;
struct VTableUse {
serialization::GlobalDeclID ID;
SourceLocation::UIntTy RawLoc;
bool Used;
};
SmallVector<VTableUse> VTableUses;

/// A snapshot of the pending instantiations in the chain.
///
/// This record tracks the instantiations that Sema has to perform at the
/// end of the TU. It consists of a pair of values for every pending
/// instantiation where the first value is the ID of the decl and the second
/// is the instantiation location.
SmallVector<serialization::DeclID, 64> PendingInstantiations;
struct PendingInstantiation {
serialization::GlobalDeclID ID;
SourceLocation::UIntTy RawLoc;
};
SmallVector<PendingInstantiation, 64> PendingInstantiations;

//@}

Expand All @@ -843,11 +857,11 @@ class ASTReader

/// A snapshot of Sema's unused file-scoped variable tracking, for
/// generating warnings.
SmallVector<serialization::DeclID, 16> UnusedFileScopedDecls;
SmallVector<serialization::GlobalDeclID, 16> UnusedFileScopedDecls;

/// A list of all the delegating constructors we've seen, to diagnose
/// cycles.
SmallVector<serialization::DeclID, 4> DelegatingCtorDecls;
SmallVector<serialization::GlobalDeclID, 4> DelegatingCtorDecls;

/// Method selectors used in a @selector expression. Used for
/// implementation of -Wselector.
Expand All @@ -860,7 +874,7 @@ class ASTReader
/// The IDs of type aliases for ext_vectors that exist in the chain.
///
/// Used by Sema for finding sugared names for ext_vectors in diagnostics.
SmallVector<serialization::DeclID, 4> ExtVectorDecls;
SmallVector<serialization::GlobalDeclID, 4> ExtVectorDecls;

//@}

Expand All @@ -871,7 +885,7 @@ class ASTReader
/// The IDs of all potentially unused typedef names in the chain.
///
/// Sema tracks these to emit warnings.
SmallVector<serialization::DeclID, 16> UnusedLocalTypedefNameCandidates;
SmallVector<serialization::GlobalDeclID, 16> UnusedLocalTypedefNameCandidates;

/// Our current depth in #pragma cuda force_host_device begin/end
/// macros.
Expand All @@ -880,7 +894,7 @@ class ASTReader
/// The IDs of the declarations Sema stores directly.
///
/// Sema tracks a few important decls, such as namespace std, directly.
SmallVector<serialization::DeclID, 4> SemaDeclRefs;
SmallVector<serialization::GlobalDeclID, 4> SemaDeclRefs;

/// The IDs of the types ASTContext stores directly.
///
Expand All @@ -891,7 +905,7 @@ class ASTReader
///
/// The AST context tracks a few important decls, currently cudaConfigureCall,
/// directly.
SmallVector<serialization::DeclID, 2> CUDASpecialDeclRefs;
SmallVector<serialization::GlobalDeclID, 2> CUDASpecialDeclRefs;

/// The floating point pragma option settings.
SmallVector<uint64_t, 1> FPPragmaOptions;
Expand Down Expand Up @@ -940,11 +954,15 @@ class ASTReader
llvm::DenseMap<const Decl *, std::set<std::string>> OpenCLDeclExtMap;

/// A list of the namespaces we've seen.
SmallVector<serialization::DeclID, 4> KnownNamespaces;
SmallVector<serialization::GlobalDeclID, 4> KnownNamespaces;

/// A list of undefined decls with internal linkage followed by the
/// SourceLocation of a matching ODR-use.
SmallVector<serialization::DeclID, 8> UndefinedButUsed;
struct UndefinedButUsedDecl {
serialization::GlobalDeclID ID;
SourceLocation::UIntTy RawLoc;
};
SmallVector<UndefinedButUsedDecl, 8> UndefinedButUsed;

/// Delete expressions to analyze at the end of translation unit.
SmallVector<uint64_t, 8> DelayedDeleteExprs;
Expand All @@ -956,7 +974,8 @@ class ASTReader
/// The IDs of all decls to be checked for deferred diags.
///
/// Sema tracks these to emit deferred diags.
llvm::SmallSetVector<serialization::DeclID, 4> DeclsToCheckForDeferredDiags;
llvm::SmallSetVector<serialization::GlobalDeclID, 4>
DeclsToCheckForDeferredDiags;

private:
struct ImportedSubmodule {
Expand Down Expand Up @@ -1093,8 +1112,8 @@ class ASTReader
///
/// The declarations on the identifier chain for these identifiers will be
/// loaded once the recursive loading has completed.
llvm::MapVector<IdentifierInfo *, SmallVector<uint32_t, 4>>
PendingIdentifierInfos;
llvm::MapVector<IdentifierInfo *, SmallVector<serialization::GlobalDeclID, 4>>
PendingIdentifierInfos;

/// The set of lookup results that we have faked in order to support
/// merging of partially deserialized decls but that we have not yet removed.
Expand Down Expand Up @@ -1221,7 +1240,7 @@ class ASTReader
SmallVector<ObjCInterfaceDecl *, 16> ObjCClassesLoaded;

using KeyDeclsMap =
llvm::DenseMap<Decl *, SmallVector<serialization::DeclID, 2>>;
llvm::DenseMap<Decl *, SmallVector<serialization::GlobalDeclID, 2>>;

/// A mapping from canonical declarations to the set of global
/// declaration IDs for key declaration that have been merged with that
Expand Down Expand Up @@ -1430,15 +1449,15 @@ class ASTReader
QualType readTypeRecord(unsigned Index);
RecordLocation TypeCursorForIndex(unsigned Index);
void LoadedDecl(unsigned Index, Decl *D);
Decl *ReadDeclRecord(serialization::DeclID ID);
Decl *ReadDeclRecord(serialization::GlobalDeclID ID);
void markIncompleteDeclChain(Decl *D);

/// Returns the most recent declaration of a declaration (which must be
/// of a redeclarable kind) that is either local or has already been loaded
/// merged into its redecl chain.
Decl *getMostRecentExistingDecl(Decl *D);

RecordLocation DeclCursorForID(serialization::DeclID ID,
RecordLocation DeclCursorForID(serialization::GlobalDeclID ID,
SourceLocation &Location);
void loadDeclUpdateRecords(PendingUpdateRecord &Record);
void loadPendingDeclChain(Decl *D, uint64_t LocalOffset);
Expand Down Expand Up @@ -1897,8 +1916,8 @@ class ASTReader

/// Map from a local declaration ID within a given module to a
/// global declaration ID.
serialization::DeclID getGlobalDeclID(ModuleFile &F,
serialization::LocalDeclID LocalID) const;
serialization::GlobalDeclID
getGlobalDeclID(ModuleFile &F, serialization::LocalDeclID LocalID) const;

/// Returns true if global DeclID \p ID originated from module \p M.
bool isDeclIDFromModule(serialization::GlobalDeclID ID, ModuleFile &M) const;
Expand All @@ -1912,23 +1931,23 @@ class ASTReader

/// Resolve a declaration ID into a declaration, potentially
/// building a new declaration.
Decl *GetDecl(serialization::DeclID ID);
Decl *GetExternalDecl(uint32_t ID) override;
Decl *GetDecl(serialization::GlobalDeclID ID);
Decl *GetExternalDecl(Decl::DeclID ID) override;

/// Resolve a declaration ID into a declaration. Return 0 if it's not
/// been loaded yet.
Decl *GetExistingDecl(serialization::DeclID ID);
Decl *GetExistingDecl(serialization::GlobalDeclID ID);

/// Reads a declaration with the given local ID in the given module.
Decl *GetLocalDecl(ModuleFile &F, uint32_t LocalID) {
Decl *GetLocalDecl(ModuleFile &F, serialization::LocalDeclID LocalID) {
return GetDecl(getGlobalDeclID(F, LocalID));
}

/// Reads a declaration with the given local ID in the given module.
///
/// \returns The requested declaration, casted to the given return type.
template<typename T>
T *GetLocalDeclAs(ModuleFile &F, uint32_t LocalID) {
template <typename T>
T *GetLocalDeclAs(ModuleFile &F, serialization::LocalDeclID LocalID) {
return cast_or_null<T>(GetLocalDecl(F, LocalID));
}

Expand All @@ -1939,14 +1958,14 @@ class ASTReader
/// module file.
serialization::DeclID
mapGlobalIDToModuleFileGlobalID(ModuleFile &M,
serialization::DeclID GlobalID);
serialization::GlobalDeclID GlobalID);

/// Reads a declaration ID from the given position in a record in the
/// given module.
///
/// \returns The declaration ID read from the record, adjusted to a global ID.
serialization::DeclID ReadDeclID(ModuleFile &F, const RecordData &Record,
unsigned &Idx);
serialization::GlobalDeclID
ReadDeclID(ModuleFile &F, const RecordData &Record, unsigned &Idx);

/// Reads a declaration from the given position in a record in the
/// given module.
Expand Down Expand Up @@ -2120,9 +2139,10 @@ class ASTReader
void LoadSelector(Selector Sel);

void SetIdentifierInfo(unsigned ID, IdentifierInfo *II);
void SetGloballyVisibleDecls(IdentifierInfo *II,
const SmallVectorImpl<uint32_t> &DeclIDs,
SmallVectorImpl<Decl *> *Decls = nullptr);
void SetGloballyVisibleDecls(
IdentifierInfo *II,
const SmallVectorImpl<serialization::GlobalDeclID> &DeclIDs,
SmallVectorImpl<Decl *> *Decls = nullptr);

/// Report a diagnostic.
DiagnosticBuilder Diag(unsigned DiagID) const;
Expand Down Expand Up @@ -2363,7 +2383,7 @@ class ASTReader

// Contains the IDs for declarations that were requested before we have
// access to a Sema object.
SmallVector<uint64_t, 16> PreloadedDeclIDs;
SmallVector<serialization::GlobalDeclID, 16> PreloadedDeclIDs;

/// Retrieve the semantic analysis object used to analyze the
/// translation unit in which the precompiled header is being
Expand Down
12 changes: 2 additions & 10 deletions clang/include/clang/Serialization/ASTRecordReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,6 @@ class ASTRecordReader
DC);
}

/// Read the record that describes the visible contents of a DC.
bool readVisibleDeclContextStorage(uint64_t Offset,
serialization::DeclID ID) {
return Reader->ReadVisibleDeclContextStorage(*F, F->DeclsCursor, Offset,
ID);
}

ExplicitSpecifier readExplicitSpec() {
uint64_t Kind = readInt();
bool HasExpr = Kind & 0x1;
Expand Down Expand Up @@ -143,8 +136,7 @@ class ASTRecordReader
/// Reads a declaration with the given local ID in the given module.
///
/// \returns The requested declaration, casted to the given return type.
template<typename T>
T *GetLocalDeclAs(uint32_t LocalID) {
template <typename T> T *GetLocalDeclAs(serialization::LocalDeclID LocalID) {
return cast_or_null<T>(Reader->GetLocalDecl(*F, LocalID));
}

Expand Down Expand Up @@ -190,7 +182,7 @@ class ASTRecordReader
/// Reads a declaration ID from the given position in this record.
///
/// \returns The declaration ID read from the record, adjusted to a global ID.
serialization::DeclID readDeclID() {
serialization::GlobalDeclID readDeclID() {
return Reader->ReadDeclID(*F, Record, Idx);
}

Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Serialization/ModuleFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ class ModuleFile {
serialization::DeclID BaseDeclID = 0;

/// Remapping table for declaration IDs in this module.
ContinuousRangeMap<uint32_t, int, 2> DeclRemap;
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
Expand All @@ -474,7 +474,7 @@ class ModuleFile {
llvm::DenseMap<ModuleFile *, serialization::DeclID> GlobalToLocalDeclIDs;

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

/// Array of category list location information within this
Expand Down
11 changes: 10 additions & 1 deletion clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1083,7 +1083,8 @@ void ASTContext::addModuleInitializer(Module *M, Decl *D) {
Inits->Initializers.push_back(D);
}

void ASTContext::addLazyModuleInitializers(Module *M, ArrayRef<uint32_t> IDs) {
void ASTContext::addLazyModuleInitializers(Module *M,
ArrayRef<Decl::DeclID> IDs) {
auto *&Inits = ModuleInitializers[M];
if (!Inits)
Inits = new (*this) PerModuleInitializers;
Expand Down Expand Up @@ -7241,6 +7242,14 @@ QualType ASTContext::isPromotableBitField(Expr *E) const {
// We perform that promotion here to match GCC and C++.
// FIXME: C does not permit promotion of an enum bit-field whose rank is
// greater than that of 'int'. We perform that promotion to match GCC.
//
// C23 6.3.1.1p2:
// The value from a bit-field of a bit-precise integer type is converted to
// the corresponding bit-precise integer type. (The rest is the same as in
// C11.)
if (QualType QT = Field->getType(); QT->isBitIntType())
return QT;

if (BitWidth < IntSize)
return IntTy;

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/DeclTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const {
CommonBase *CommonBasePtr = getMostRecentDecl()->getCommonPtr();
if (CommonBasePtr->LazySpecializations) {
ASTContext &Context = getASTContext();
uint32_t *Specs = CommonBasePtr->LazySpecializations;
Decl::DeclID *Specs = CommonBasePtr->LazySpecializations;
CommonBasePtr->LazySpecializations = nullptr;
for (uint32_t I = 0, N = *Specs++; I != N; ++I)
(void)Context.getExternalSource()->GetExternalDecl(Specs[I]);
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16853,13 +16853,13 @@ bool Expr::EvaluateCharRangeAsString(std::string &Result,
if (!::EvaluateInteger(SizeExpression, SizeValue, Info))
return false;

int64_t Size = SizeValue.getExtValue();
uint64_t Size = SizeValue.getZExtValue();

if (!::EvaluatePointer(PtrExpression, String, Info))
return false;

QualType CharTy = PtrExpression->getType()->getPointeeType();
for (int64_t I = 0; I < Size; ++I) {
for (uint64_t I = 0; I < Size; ++I) {
APValue Char;
if (!handleLValueToRValueConversion(Info, PtrExpression, CharTy, String,
Char))
Expand Down
4 changes: 1 addition & 3 deletions clang/lib/AST/ExternalASTSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,7 @@ bool ExternalASTSource::layoutRecordType(
return false;
}

Decl *ExternalASTSource::GetExternalDecl(uint32_t ID) {
return nullptr;
}
Decl *ExternalASTSource::GetExternalDecl(Decl::DeclID ID) { return nullptr; }

Selector ExternalASTSource::GetExternalSelector(uint32_t ID) {
return Selector();
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/AST/Interp/IntegralAP.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,10 @@ template <bool Signed> class IntegralAP final {
}

IntegralAP truncate(unsigned BitWidth) const {
return IntegralAP(V.trunc(BitWidth));
if constexpr (Signed)
return IntegralAP(V.trunc(BitWidth).sextOrTrunc(this->bitWidth()));
else
return IntegralAP(V.trunc(BitWidth).zextOrTrunc(this->bitWidth()));
}

IntegralAP<false> toUnsigned() const {
Expand Down
16 changes: 16 additions & 0 deletions clang/lib/AST/OpenACCClause.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,16 @@ OpenACCVectorLengthClause::Create(const ASTContext &C, SourceLocation BeginLoc,
OpenACCVectorLengthClause(BeginLoc, LParenLoc, IntExpr, EndLoc);
}

OpenACCNumGangsClause *OpenACCNumGangsClause::Create(const ASTContext &C,
SourceLocation BeginLoc,
SourceLocation LParenLoc,
ArrayRef<Expr *> IntExprs,
SourceLocation EndLoc) {
void *Mem = C.Allocate(
OpenACCNumGangsClause::totalSizeToAlloc<Expr *>(IntExprs.size()));
return new (Mem) OpenACCNumGangsClause(BeginLoc, LParenLoc, IntExprs, EndLoc);
}

//===----------------------------------------------------------------------===//
// OpenACC clauses printing methods
//===----------------------------------------------------------------------===//
Expand All @@ -141,6 +151,12 @@ void OpenACCClausePrinter::VisitSelfClause(const OpenACCSelfClause &C) {
OS << "(" << CondExpr << ")";
}

void OpenACCClausePrinter::VisitNumGangsClause(const OpenACCNumGangsClause &C) {
OS << "num_gangs(";
llvm::interleaveComma(C.getIntExprs(), OS);
OS << ")";
}

void OpenACCClausePrinter::VisitNumWorkersClause(
const OpenACCNumWorkersClause &C) {
OS << "num_workers(" << C.getIntExpr() << ")";
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/AST/StmtProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2497,6 +2497,12 @@ void OpenACCClauseProfiler::VisitSelfClause(const OpenACCSelfClause &Clause) {
Profiler.VisitStmt(Clause.getConditionExpr());
}

void OpenACCClauseProfiler::VisitNumGangsClause(
const OpenACCNumGangsClause &Clause) {
for (auto *E : Clause.getIntExprs())
Profiler.VisitStmt(E);
}

void OpenACCClauseProfiler::VisitNumWorkersClause(
const OpenACCNumWorkersClause &Clause) {
assert(Clause.hasIntExpr() && "num_workers clause requires a valid int expr");
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
break;
case OpenACCClauseKind::If:
case OpenACCClauseKind::Self:
case OpenACCClauseKind::NumGangs:
case OpenACCClauseKind::NumWorkers:
case OpenACCClauseKind::VectorLength:
// The condition expression will be printed as a part of the 'children',
Expand Down
46 changes: 24 additions & 22 deletions clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,13 +237,8 @@ joinLocToVal(const llvm::MapVector<const StorageLocation *, Value *> &LocToVal,
continue;
assert(It->second != nullptr);

if (areEquivalentValues(*Val, *It->second)) {
Result.insert({Loc, Val});
continue;
}

if (Value *JoinedVal = joinDistinctValues(
Loc->getType(), *Val, Env1, *It->second, Env2, JoinedEnv, Model)) {
if (Value *JoinedVal = Environment::joinValues(
Loc->getType(), Val, Env1, It->second, Env2, JoinedEnv, Model)) {
Result.insert({Loc, JoinedVal});
}
}
Expand Down Expand Up @@ -775,27 +770,16 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB,
JoinedEnv.LocForRecordReturnVal = EnvA.LocForRecordReturnVal;
JoinedEnv.ThisPointeeLoc = EnvA.ThisPointeeLoc;

if (EnvA.ReturnVal == nullptr || EnvB.ReturnVal == nullptr) {
// `ReturnVal` might not always get set -- for example if we have a return
// statement of the form `return some_other_func()` and we decide not to
// analyze `some_other_func()`.
// In this case, we can't say anything about the joined return value -- we
// don't simply want to propagate the return value that we do have, because
// it might not be the correct one.
// This occurs for example in the test `ContextSensitiveMutualRecursion`.
if (EnvA.CallStack.empty()) {
JoinedEnv.ReturnVal = nullptr;
} else if (areEquivalentValues(*EnvA.ReturnVal, *EnvB.ReturnVal)) {
JoinedEnv.ReturnVal = EnvA.ReturnVal;
} else {
assert(!EnvA.CallStack.empty());
// FIXME: Make `CallStack` a vector of `FunctionDecl` so we don't need this
// cast.
auto *Func = dyn_cast<FunctionDecl>(EnvA.CallStack.back());
assert(Func != nullptr);
if (Value *JoinedVal =
joinDistinctValues(Func->getReturnType(), *EnvA.ReturnVal, EnvA,
*EnvB.ReturnVal, EnvB, JoinedEnv, Model))
JoinedEnv.ReturnVal = JoinedVal;
JoinedEnv.ReturnVal =
joinValues(Func->getReturnType(), EnvA.ReturnVal, EnvA, EnvB.ReturnVal,
EnvB, JoinedEnv, Model);
}

if (EnvA.ReturnLoc == EnvB.ReturnLoc)
Expand All @@ -821,6 +805,24 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB,
return JoinedEnv;
}

Value *Environment::joinValues(QualType Ty, Value *Val1,
const Environment &Env1, Value *Val2,
const Environment &Env2, Environment &JoinedEnv,
Environment::ValueModel &Model) {
if (Val1 == nullptr || Val2 == nullptr)
// We can't say anything about the joined value -- even if one of the values
// is non-null, we don't want to simply propagate it, because it would be
// too specific: Because the other value is null, that means we have no
// information at all about the value (i.e. the value is unconstrained).
return nullptr;

if (areEquivalentValues(*Val1, *Val2))
// Arbitrarily return one of the two values.
return Val1;

return joinDistinctValues(Ty, *Val1, Env1, *Val2, Env2, JoinedEnv, Model);
}

StorageLocation &Environment::createStorageLocation(QualType Type) {
return DACtx->createStorageLocation(Type);
}
Expand Down
58 changes: 43 additions & 15 deletions clang/lib/Analysis/FlowSensitive/Transfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,9 @@ namespace {

class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
public:
TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env)
: StmtToEnv(StmtToEnv), Env(Env) {}
TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env,
Environment::ValueModel &Model)
: StmtToEnv(StmtToEnv), Env(Env), Model(Model) {}

void VisitBinaryOperator(const BinaryOperator *S) {
const Expr *LHS = S->getLHS();
Expand Down Expand Up @@ -641,17 +642,42 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
}

void VisitConditionalOperator(const ConditionalOperator *S) {
// FIXME: Revisit this once flow conditions are added to the framework. For
// `a = b ? c : d` we can add `b => a == c && !b => a == d` to the flow
// condition.
// When we do this, we will need to retrieve the values of the operands from
// the environments for the basic blocks they are computed in, in a similar
// way to how this is done for short-circuited logical operators in
// `getLogicOperatorSubExprValue()`.
if (S->isGLValue())
Env.setStorageLocation(*S, Env.createObject(S->getType()));
else if (!S->getType()->isRecordType()) {
if (Value *Val = Env.createValue(S->getType()))
const Environment *TrueEnv = StmtToEnv.getEnvironment(*S->getTrueExpr());
const Environment *FalseEnv = StmtToEnv.getEnvironment(*S->getFalseExpr());

if (TrueEnv == nullptr || FalseEnv == nullptr) {
// If the true or false branch is dead, we may not have an environment for
// it. We could handle this specifically by forwarding the value or
// location of the live branch, but this case is rare enough that this
// probably isn't worth the additional complexity.
return;
}

if (S->isGLValue()) {
StorageLocation *TrueLoc = TrueEnv->getStorageLocation(*S->getTrueExpr());
StorageLocation *FalseLoc =
FalseEnv->getStorageLocation(*S->getFalseExpr());
if (TrueLoc == FalseLoc && TrueLoc != nullptr)
Env.setStorageLocation(*S, *TrueLoc);
} else if (!S->getType()->isRecordType()) {
// The conditional operator can evaluate to either of the values of the
// two branches. To model this, join these two values together to yield
// the result of the conditional operator.
// Note: Most joins happen in `computeBlockInputState()`, but this case is
// different:
// - `computeBlockInputState()` (which in turn calls `Environment::join()`
// joins values associated with the _same_ expression or storage
// location, then associates the joined value with that expression or
// storage location. This join has nothing to do with transfer --
// instead, it joins together the results of performing transfer on two
// different blocks.
// - Here, we join values associated with _different_ expressions (the
// true and false branch), then associate the joined value with a third
// expression (the conditional operator itself). This join is what it
// means to perform transfer on the conditional operator.
if (Value *Val = Environment::joinValues(
S->getType(), TrueEnv->getValue(*S->getTrueExpr()), *TrueEnv,
FalseEnv->getValue(*S->getFalseExpr()), *FalseEnv, Env, Model))
Env.setValue(*S, *Val);
}
}
Expand Down Expand Up @@ -810,12 +836,14 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {

const StmtToEnvMap &StmtToEnv;
Environment &Env;
Environment::ValueModel &Model;
};

} // namespace

void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env) {
TransferVisitor(StmtToEnv, Env).Visit(&S);
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env,
Environment::ValueModel &Model) {
TransferVisitor(StmtToEnv, Env, Model).Visit(&S);
}

} // namespace dataflow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ builtinTransferStatement(unsigned CurBlockID, const CFGStmt &Elt,
const Stmt *S = Elt.getStmt();
assert(S != nullptr);
transfer(StmtToEnvMap(AC.ACFG, AC.BlockStates, CurBlockID, InputState), *S,
InputState.Env);
InputState.Env, AC.Analysis);
}

/// Built-in transfer function for `CFGInitializer`.
Expand Down Expand Up @@ -452,7 +452,7 @@ transferCFGBlock(const CFGBlock &Block, AnalysisContext &AC,
// terminator condition, but not as a `CFGElement`. The condition of an if
// statement is one such example.
transfer(StmtToEnvMap(AC.ACFG, AC.BlockStates, Block.getBlockID(), State),
*TerminatorCond, State.Env);
*TerminatorCond, State.Env, AC.Analysis);

// If the transfer function didn't produce a value, create an atom so that
// we have *some* value for the condition expression. This ensures that
Expand Down
8 changes: 6 additions & 2 deletions clang/lib/Basic/Targets/PPC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasPrivileged = true;
} else if (Feature == "+aix-small-local-exec-tls") {
HasAIXSmallLocalExecTLS = true;
} else if (Feature == "+aix-small-local-dynamic-tls") {
HasAIXSmallLocalDynamicTLS = true;
} else if (Feature == "+isa-v206-instructions") {
IsISA2_06 = true;
} else if (Feature == "+isa-v207-instructions") {
Expand Down Expand Up @@ -573,9 +575,10 @@ bool PPCTargetInfo::initFeatureMap(
// Privileged instructions are off by default.
Features["privileged"] = false;

// The code generated by the -maix-small-local-exec-tls option is turned
// off by default.
// The code generated by the -maix-small-local-[exec|dynamic]-tls option is
// turned off by default.
Features["aix-small-local-exec-tls"] = false;
Features["aix-small-local-dynamic-tls"] = false;

Features["spe"] = llvm::StringSwitch<bool>(CPU)
.Case("8548", true)
Expand Down Expand Up @@ -713,6 +716,7 @@ bool PPCTargetInfo::hasFeature(StringRef Feature) const {
.Case("rop-protect", HasROPProtect)
.Case("privileged", HasPrivileged)
.Case("aix-small-local-exec-tls", HasAIXSmallLocalExecTLS)
.Case("aix-small-local-dynamic-tls", HasAIXSmallLocalDynamicTLS)
.Case("isa-v206-instructions", IsISA2_06)
.Case("isa-v207-instructions", IsISA2_07)
.Case("isa-v30-instructions", IsISA3_0)
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Targets/PPC.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {
bool HasROPProtect = false;
bool HasPrivileged = false;
bool HasAIXSmallLocalExecTLS = false;
bool HasAIXSmallLocalDynamicTLS = false;
bool HasVSX = false;
bool UseCRBits = false;
bool HasP8Vector = false;
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18267,8 +18267,8 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
if (!E->getArg(0)->getType()->hasFloatingRepresentation())
llvm_unreachable("lerp operand must have a float representation");
return Builder.CreateIntrinsic(
/*ReturnType=*/X->getType(), Intrinsic::dx_lerp,
ArrayRef<Value *>{X, Y, S}, nullptr, "dx.lerp");
/*ReturnType=*/X->getType(), CGM.getHLSLRuntime().getLerpIntrinsic(),
ArrayRef<Value *>{X, Y, S}, nullptr, "hlsl.lerp");
}
case Builtin::BI__builtin_hlsl_elementwise_frac: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
Expand Down
108 changes: 56 additions & 52 deletions clang/lib/CodeGen/CGExprConstant.cpp

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions clang/lib/CodeGen/CGHLSLRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class CGHLSLRuntime {

GENERATE_HLSL_INTRINSIC_FUNCTION(All, all)
GENERATE_HLSL_INTRINSIC_FUNCTION(Any, any)
GENERATE_HLSL_INTRINSIC_FUNCTION(Lerp, lerp)
GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id)

//===----------------------------------------------------------------------===//
Expand Down
11 changes: 8 additions & 3 deletions clang/lib/CodeGen/CoverageMappingGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1208,6 +1208,12 @@ struct CounterCoverageMappingBuilder
/// Find a valid gap range between \p AfterLoc and \p BeforeLoc.
std::optional<SourceRange> findGapAreaBetween(SourceLocation AfterLoc,
SourceLocation BeforeLoc) {
// Some statements (like AttributedStmt and ImplicitValueInitExpr) don't
// have valid source locations. Do not emit a gap region if this is the case
// in either AfterLoc end or BeforeLoc end.
if (AfterLoc.isInvalid() || BeforeLoc.isInvalid())
return std::nullopt;

// If AfterLoc is in function-like macro, use the right parenthesis
// location.
if (AfterLoc.isMacroID()) {
Expand Down Expand Up @@ -1368,9 +1374,8 @@ struct CounterCoverageMappingBuilder
for (const Stmt *Child : S->children())
if (Child) {
// If last statement contains terminate statements, add a gap area
// between the two statements. Skipping attributed statements, because
// they don't have valid start location.
if (LastStmt && HasTerminateStmt && !isa<AttributedStmt>(Child)) {
// between the two statements.
if (LastStmt && HasTerminateStmt) {
auto Gap = findGapAreaBetween(getEnd(LastStmt), getStart(Child));
if (Gap)
fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(),
Expand Down
17 changes: 9 additions & 8 deletions clang/lib/Driver/ToolChains/Arch/PPC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,21 +125,22 @@ void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,

bool UseSeparateSections = isUseSeparateSections(Triple);
bool HasDefaultDataSections = Triple.isOSBinFormatXCOFF();
if (Args.hasArg(options::OPT_maix_small_local_exec_tls)) {
if (Args.hasArg(options::OPT_maix_small_local_exec_tls) ||
Args.hasArg(options::OPT_maix_small_local_dynamic_tls)) {
if (!Triple.isOSAIX() || !Triple.isArch64Bit())
D.Diag(diag::err_opt_not_valid_on_target) << "-maix-small-local-exec-tls";
D.Diag(diag::err_opt_not_valid_on_target)
<< "-maix-small-local-[exec|dynamic]-tls";

// The -maix-small-local-exec-tls option should only be used with
// The -maix-small-local-[exec|dynamic]-tls option should only be used with
// -fdata-sections, as having data sections turned off with this option
// is not ideal for performance. Moreover, the small-local-exec-tls region
// is a limited resource, and should not be used for variables that may
// be replaced.
// is not ideal for performance. Moreover, the
// small-local-[exec|dynamic]-tls region is a limited resource, and should
// not be used for variables that may be replaced.
if (!Args.hasFlag(options::OPT_fdata_sections,
options::OPT_fno_data_sections,
UseSeparateSections || HasDefaultDataSections))
D.Diag(diag::err_drv_argument_only_allowed_with)
<< "-maix-small-local-exec-tls"
<< "-fdata-sections";
<< "-maix-small-local-[exec|dynamic]-tls" << "-fdata-sections";
}
}

Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,16 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) {
if (Arg *A = Args.getLastArg(options::OPT_O_Group))
RelaxDefault = A->getOption().matches(options::OPT_O0);

// RISC-V requires an indirect jump for offsets larger than 1MiB. This cannot
// be done by assembler branch relaxation as it needs a free temporary
// register. Because of this, branch relaxation is handled by a MachineIR
// pass before the assembler. Forcing assembler branch relaxation for -O0
// makes the MachineIR branch relaxation inaccurate and it will miss cases
// where an indirect branch is necessary. To avoid this issue we are
// sacrificing the compile time improvement of using -mrelax-all for -O0.
if (C.getDefaultToolChain().getTriple().isRISCV())
RelaxDefault = false;

if (RelaxDefault) {
RelaxDefault = false;
for (const auto &Act : C.getActions()) {
Expand Down
28 changes: 15 additions & 13 deletions clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,27 +164,29 @@ std::optional<Array> serializeAvailability(const AvailabilityInfo &Avail) {
if (Avail.isDefault())
return std::nullopt;

Object Availability;
Array AvailabilityArray;
Availability["domain"] = Avail.Domain;
serializeObject(Availability, "introduced",
serializeSemanticVersion(Avail.Introduced));
serializeObject(Availability, "deprecated",
serializeSemanticVersion(Avail.Deprecated));
serializeObject(Availability, "obsoleted",
serializeSemanticVersion(Avail.Obsoleted));

if (Avail.isUnconditionallyDeprecated()) {
Object UnconditionallyDeprecated;
UnconditionallyDeprecated["domain"] = "*";
UnconditionallyDeprecated["isUnconditionallyDeprecated"] = true;
AvailabilityArray.emplace_back(std::move(UnconditionallyDeprecated));
}
if (Avail.isUnconditionallyUnavailable()) {
Object UnconditionallyUnavailable;
UnconditionallyUnavailable["domain"] = "*";
UnconditionallyUnavailable["isUnconditionallyUnavailable"] = true;
AvailabilityArray.emplace_back(std::move(UnconditionallyUnavailable));
Object Availability;

Availability["domain"] = Avail.Domain;

if (Avail.isUnavailable()) {
Availability["isUnconditionallyUnavailable"] = true;
} else {
serializeObject(Availability, "introduced",
serializeSemanticVersion(Avail.Introduced));
serializeObject(Availability, "deprecated",
serializeSemanticVersion(Avail.Deprecated));
serializeObject(Availability, "obsoleted",
serializeSemanticVersion(Avail.Obsoleted));
}

AvailabilityArray.emplace_back(std::move(Availability));
return AvailabilityArray;
}
Expand Down
36 changes: 32 additions & 4 deletions clang/lib/Lex/LiteralSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
bool isFixedPointConstant = isFixedPointLiteral();
bool isFPConstant = isFloatingLiteral();
bool HasSize = false;
bool DoubleUnderscore = false;

// Loop over all of the characters of the suffix. If we see something bad,
// we break out of the loop.
Expand Down Expand Up @@ -1117,6 +1118,31 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
if (isImaginary) break; // Cannot be repeated.
isImaginary = true;
continue; // Success.
case '_':
if (isFPConstant)
break; // Invalid for floats
if (HasSize)
break;
if (DoubleUnderscore)
break; // Cannot be repeated.
if (LangOpts.CPlusPlus && s + 2 < ThisTokEnd &&
s[1] == '_') { // s + 2 < ThisTokEnd to ensure some character exists
// after __
DoubleUnderscore = true;
s += 2; // Skip both '_'
if (s + 1 < ThisTokEnd &&
(*s == 'u' || *s == 'U')) { // Ensure some character after 'u'/'U'
isUnsigned = true;
++s;
}
if (s + 1 < ThisTokEnd &&
((*s == 'w' && *(++s) == 'b') || (*s == 'W' && *(++s) == 'B'))) {
isBitInt = true;
HasSize = true;
continue;
}
}
break;
case 'w':
case 'W':
if (isFPConstant)
Expand All @@ -1127,9 +1153,9 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
// wb and WB are allowed, but a mixture of cases like Wb or wB is not. We
// explicitly do not support the suffix in C++ as an extension because a
// library-based UDL that resolves to a library type may be more
// appropriate there.
if (!LangOpts.CPlusPlus && ((s[0] == 'w' && s[1] == 'b') ||
(s[0] == 'W' && s[1] == 'B'))) {
// appropriate there. The same rules apply for __wb/__WB.
if ((!LangOpts.CPlusPlus || DoubleUnderscore) && s + 1 < ThisTokEnd &&
((s[0] == 'w' && s[1] == 'b') || (s[0] == 'W' && s[1] == 'B'))) {
isBitInt = true;
HasSize = true;
++s; // Skip both characters (2nd char skipped on continue).
Expand Down Expand Up @@ -1241,7 +1267,9 @@ bool NumericLiteralParser::isValidUDSuffix(const LangOptions &LangOpts,
return false;

// By C++11 [lex.ext]p10, ud-suffixes starting with an '_' are always valid.
if (Suffix[0] == '_')
// Suffixes starting with '__' (double underscore) are for use by
// the implementation.
if (Suffix.starts_with("_") && !Suffix.starts_with("__"))
return true;

// In C++11, there are no library suffixes.
Expand Down
8 changes: 4 additions & 4 deletions clang/lib/Lex/PPExpressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,11 +333,11 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
: diag::ext_cxx23_size_t_suffix
: diag::err_cxx23_size_t_suffix);

// 'wb/uwb' literals are a C23 feature. We explicitly do not support the
// suffix in C++ as an extension because a library-based UDL that resolves
// to a library type may be more appropriate there.
// 'wb/uwb' literals are a C23 feature.
// '__wb/__uwb' are a C++ extension.
if (Literal.isBitInt)
PP.Diag(PeekTok, PP.getLangOpts().C23
PP.Diag(PeekTok, PP.getLangOpts().CPlusPlus ? diag::ext_cxx_bitint_suffix
: PP.getLangOpts().C23
? diag::warn_c23_compat_bitint_suffix
: diag::ext_c23_bitint_suffix);

Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Parse/ParseCXXInlineMethods.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,8 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
// to be re-used for method bodies as well.
ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope |
Scope::CompoundStmtScope);
Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);

Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D);

if (Tok.is(tok::kw_try)) {
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2222,7 +2222,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
}

if (getLangOpts().HLSL)
MaybeParseHLSLSemantics(D);
MaybeParseHLSLAnnotations(D);

if (Tok.is(tok::kw_requires))
ParseTrailingRequiresClause(D);
Expand Down Expand Up @@ -2469,7 +2469,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
ParseDeclarator(D);

if (getLangOpts().HLSL)
MaybeParseHLSLSemantics(D);
MaybeParseHLSLAnnotations(D);

if (!D.isInvalidType()) {
// C++2a [dcl.decl]p1
Expand Down Expand Up @@ -7699,7 +7699,7 @@ void Parser::ParseParameterDeclarationClause(
// Parse GNU attributes, if present.
MaybeParseGNUAttributes(ParmDeclarator);
if (getLangOpts().HLSL)
MaybeParseHLSLSemantics(DS.getAttributes());
MaybeParseHLSLAnnotations(DS.getAttributes());

if (Tok.is(tok::kw_requires)) {
// User tried to define a requires clause in a parameter declaration,
Expand Down
18 changes: 8 additions & 10 deletions clang/lib/Parse/ParseHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Decl *Parser::ParseHLSLBuffer(SourceLocation &DeclEnd) {
SourceLocation IdentifierLoc = ConsumeToken();

ParsedAttributes Attrs(AttrFactory);
MaybeParseHLSLSemantics(Attrs, nullptr);
MaybeParseHLSLAnnotations(Attrs, nullptr);

ParseScope BufferScope(this, Scope::DeclScope);
BalancedDelimiterTracker T(*this, tok::l_brace);
Expand Down Expand Up @@ -118,12 +118,10 @@ static void fixSeparateAttrArgAndNumber(StringRef ArgStr, SourceLocation ArgLoc,
Slot = IdentifierLoc::create(Ctx, ArgLoc, PP.getIdentifierInfo(FixedArg));
}

void Parser::ParseHLSLSemantics(ParsedAttributes &Attrs,
SourceLocation *EndLoc) {
// FIXME: HLSLSemantic is shared for Semantic and resource binding which is
// confusing. Need a better name to avoid misunderstanding. Issue
// https://github.com/llvm/llvm-project/issues/57882
assert(Tok.is(tok::colon) && "Not a HLSL Semantic");
void Parser::ParseHLSLAnnotations(ParsedAttributes &Attrs,
SourceLocation *EndLoc) {

assert(Tok.is(tok::colon) && "Not a HLSL Annotation");
ConsumeToken();

IdentifierInfo *II = nullptr;
Expand All @@ -141,7 +139,7 @@ void Parser::ParseHLSLSemantics(ParsedAttributes &Attrs,
if (EndLoc)
*EndLoc = Tok.getLocation();
ParsedAttr::Kind AttrKind =
ParsedAttr::getParsedKind(II, nullptr, ParsedAttr::AS_HLSLSemantic);
ParsedAttr::getParsedKind(II, nullptr, ParsedAttr::AS_HLSLAnnotation);

ArgsVector ArgExprs;
switch (AttrKind) {
Expand Down Expand Up @@ -192,10 +190,10 @@ void Parser::ParseHLSLSemantics(ParsedAttributes &Attrs,
case ParsedAttr::AT_HLSLSV_DispatchThreadID:
break;
default:
llvm_unreachable("invalid HLSL Semantic");
llvm_unreachable("invalid HLSL Annotation");
break;
}

Attrs.addNew(II, Loc, nullptr, SourceLocation(), ArgExprs.data(),
ArgExprs.size(), ParsedAttr::Form::HLSLSemantic());
ArgExprs.size(), ParsedAttr::Form::HLSLAnnotation());
}
1 change: 1 addition & 0 deletions clang/lib/Parse/ParseObjc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3736,6 +3736,7 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
ParseScope BodyScope(this, (parseMethod ? Scope::ObjCMethodScope : 0) |
Scope::FnScope | Scope::DeclScope |
Scope::CompoundStmtScope);
Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);

// Tell the actions module that we have entered a method or c-function definition
// with the specified Declarator for the method/function.
Expand Down
87 changes: 70 additions & 17 deletions clang/lib/Parse/ParseOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -632,16 +632,54 @@ Parser::ParseOpenACCClauseList(OpenACCDirectiveKind DirKind) {
return Clauses;
}

ExprResult Parser::ParseOpenACCIntExpr(OpenACCDirectiveKind DK,
OpenACCClauseKind CK,
SourceLocation Loc) {
ExprResult ER =
getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression());
Parser::OpenACCIntExprParseResult
Parser::ParseOpenACCIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
SourceLocation Loc) {
ExprResult ER = ParseAssignmentExpression();

// If the actual parsing failed, we don't know the state of the parse, so
// don't try to continue.
if (!ER.isUsable())
return ER;
return {ER, OpenACCParseCanContinue::Cannot};

// Parsing can continue after the initial assignment expression parsing, so
// even if there was a typo, we can continue.
ER = getActions().CorrectDelayedTyposInExpr(ER);
if (!ER.isUsable())
return {ER, OpenACCParseCanContinue::Can};

return {getActions().OpenACC().ActOnIntExpr(DK, CK, Loc, ER.get()),
OpenACCParseCanContinue::Can};
}

bool Parser::ParseOpenACCIntExprList(OpenACCDirectiveKind DK,
OpenACCClauseKind CK, SourceLocation Loc,
llvm::SmallVectorImpl<Expr *> &IntExprs) {
OpenACCIntExprParseResult CurResult = ParseOpenACCIntExpr(DK, CK, Loc);

if (!CurResult.first.isUsable() &&
CurResult.second == OpenACCParseCanContinue::Cannot) {
SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
Parser::StopBeforeMatch);
return true;
}

IntExprs.push_back(CurResult.first.get());

while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
ExpectAndConsume(tok::comma);

CurResult = ParseOpenACCIntExpr(DK, CK, Loc);

return getActions().OpenACC().ActOnIntExpr(DK, CK, Loc, ER.get());
if (!CurResult.first.isUsable() &&
CurResult.second == OpenACCParseCanContinue::Cannot) {
SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
Parser::StopBeforeMatch);
return true;
}
IntExprs.push_back(CurResult.first.get());
}
return false;
}

bool Parser::ParseOpenACCClauseVarList(OpenACCClauseKind Kind) {
Expand Down Expand Up @@ -761,7 +799,7 @@ bool Parser::ParseOpenACCGangArg(SourceLocation GangLoc) {
ConsumeToken();
return ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid,
OpenACCClauseKind::Gang, GangLoc)
.isInvalid();
.first.isInvalid();
}

if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Num, getCurToken()) &&
Expand All @@ -773,7 +811,7 @@ bool Parser::ParseOpenACCGangArg(SourceLocation GangLoc) {
// This is just the 'num' case where 'num' is optional.
return ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid,
OpenACCClauseKind::Gang, GangLoc)
.isInvalid();
.first.isInvalid();
}

bool Parser::ParseOpenACCGangArgList(SourceLocation GangLoc) {
Expand Down Expand Up @@ -946,13 +984,25 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
}
break;
}
case OpenACCClauseKind::NumGangs:
case OpenACCClauseKind::NumGangs: {
llvm::SmallVector<Expr *> IntExprs;

if (ParseOpenACCIntExprList(OpenACCDirectiveKind::Invalid,
OpenACCClauseKind::NumGangs, ClauseLoc,
IntExprs)) {
Parens.skipToEnd();
return OpenACCCanContinue();
}
ParsedClause.setIntExprDetails(std::move(IntExprs));
break;
}
case OpenACCClauseKind::NumWorkers:
case OpenACCClauseKind::DeviceNum:
case OpenACCClauseKind::DefaultAsync:
case OpenACCClauseKind::VectorLength: {
ExprResult IntExpr = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid,
ClauseKind, ClauseLoc);
ClauseKind, ClauseLoc)
.first;
if (IntExpr.isInvalid()) {
Parens.skipToEnd();
return OpenACCCanContinue();
Expand Down Expand Up @@ -1017,7 +1067,8 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
: OpenACCSpecialTokenKind::Num,
ClauseKind);
ExprResult IntExpr = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid,
ClauseKind, ClauseLoc);
ClauseKind, ClauseLoc)
.first;
if (IntExpr.isInvalid()) {
Parens.skipToEnd();
return OpenACCCanContinue();
Expand Down Expand Up @@ -1081,11 +1132,13 @@ bool Parser::ParseOpenACCWaitArgument(SourceLocation Loc, bool IsDirective) {
// Consume colon.
ConsumeToken();

ExprResult IntExpr = ParseOpenACCIntExpr(
IsDirective ? OpenACCDirectiveKind::Wait
: OpenACCDirectiveKind::Invalid,
IsDirective ? OpenACCClauseKind::Invalid : OpenACCClauseKind::Wait,
Loc);
ExprResult IntExpr =
ParseOpenACCIntExpr(IsDirective ? OpenACCDirectiveKind::Wait
: OpenACCDirectiveKind::Invalid,
IsDirective ? OpenACCClauseKind::Invalid
: OpenACCClauseKind::Wait,
Loc)
.first;
if (IntExpr.isInvalid())
return true;

Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Parse/ParseTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,12 @@ NamedDecl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
// we introduce the type parameter into the local scope.
SourceLocation EqualLoc;
ParsedType DefaultArg;
std::optional<DelayTemplateIdDestructionRAII> DontDestructTemplateIds;
if (TryConsumeToken(tok::equal, EqualLoc)) {
// The default argument might contain a lambda declaration; avoid destroying
// parsed template ids at the end of that declaration because they can be
// used in a type constraint later.
DontDestructTemplateIds.emplace(*this, /*DelayTemplateIdDestruction=*/true);
// The default argument may declare template parameters, notably
// if it contains a generic lambda, so we need to increase
// the template depth as these parameters would not be instantiated
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Parse/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1497,6 +1497,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
return Actions.ActOnFinishFunctionBody(Res, nullptr, false);
}

Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);

if (Tok.is(tok::kw_try))
return ParseFunctionTryBlock(Res, BodyScope);

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/MultiplexExternalSemaSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ void MultiplexExternalSemaSource::AddSource(ExternalSemaSource *Source) {
// ExternalASTSource.
//===----------------------------------------------------------------------===//

Decl *MultiplexExternalSemaSource::GetExternalDecl(uint32_t ID) {
Decl *MultiplexExternalSemaSource::GetExternalDecl(Decl::DeclID ID) {
for(size_t i = 0; i < Sources.size(); ++i)
if (Decl *Result = Sources[i]->GetExternalDecl(ID))
return Result;
Expand Down
11 changes: 8 additions & 3 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12779,10 +12779,15 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
// In this case, the expression could be printed using a different
// specifier, but we've decided that the specifier is probably correct
// and we should cast instead. Just use the normal warning message.

unsigned Diag =
IsScopedEnum
? diag::warn_format_conversion_argument_type_mismatch_pedantic
: diag::warn_format_conversion_argument_type_mismatch;

EmitFormatDiagnostic(
S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
<< AT.getRepresentativeTypeName(S.Context) << ExprTy << IsEnum
<< E->getSourceRange(),
S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context) << ExprTy
<< IsEnum << E->getSourceRange(),
E->getBeginLoc(), /*IsStringLocation*/ false, SpecRange, Hints);
}
}
Expand Down
19 changes: 19 additions & 0 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15899,6 +15899,11 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
FD->setInvalidDecl();
return D;
}

// Some function attributes (like OptimizeNoneAttr) need actions before
// parsing body started.
applyFunctionAttributesBeforeParsingBody(D);

// We want to attach documentation to original Decl (which might be
// a function template).
ActOnDocumentableDecl(D);
Expand All @@ -15910,6 +15915,20 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
return D;
}

void Sema::applyFunctionAttributesBeforeParsingBody(Decl *FD) {
if (!FD || FD->isInvalidDecl())
return;
if (auto *TD = dyn_cast<FunctionTemplateDecl>(FD))
FD = TD->getTemplatedDecl();
if (FD && FD->hasAttr<OptimizeNoneAttr>()) {
FPOptionsOverride FPO;
FPO.setDisallowOptimizations();
CurFPFeatures.applyChanges(FPO);
FpPragmaStack.CurrentValue =
CurFPFeatures.getChangesFrom(FPOptions(LangOpts));
}
}

/// Given the set of return statements within a function body,
/// compute the variables that are subject to the named return value
/// optimization.
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Sema/SemaDeclObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,10 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
}
}
}

// Some function attributes (like OptimizeNoneAttr) need actions before
// parsing body started.
applyFunctionAttributesBeforeParsingBody(D);
}

namespace {
Expand Down
12 changes: 7 additions & 5 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4137,11 +4137,13 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// 'wb/uwb' literals are a C23 feature. We support _BitInt as a type in C++,
// but we do not currently support the suffix in C++ mode because it's not
// entirely clear whether WG21 will prefer this suffix to return a library
// type such as std::bit_int instead of returning a _BitInt.
if (Literal.isBitInt && !getLangOpts().CPlusPlus)
PP.Diag(Tok.getLocation(), getLangOpts().C23
? diag::warn_c23_compat_bitint_suffix
: diag::ext_c23_bitint_suffix);
// type such as std::bit_int instead of returning a _BitInt. '__wb/__uwb'
// literals are a C++ extension.
if (Literal.isBitInt)
PP.Diag(Tok.getLocation(),
getLangOpts().CPlusPlus ? diag::ext_cxx_bitint_suffix
: getLangOpts().C23 ? diag::warn_c23_compat_bitint_suffix
: diag::ext_c23_bitint_suffix);

// Get the value in the widest-possible width. What is "widest" depends on
// whether the literal is a bit-precise integer or not. For a bit-precise
Expand Down
35 changes: 35 additions & 0 deletions clang/lib/Sema/SemaOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind,
default:
return false;
}
case OpenACCClauseKind::NumGangs:
case OpenACCClauseKind::NumWorkers:
case OpenACCClauseKind::VectorLength:
switch (DirectiveKind) {
Expand Down Expand Up @@ -230,6 +231,40 @@ SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(),
Clause.getConditionExpr(), Clause.getEndLoc());
}
case OpenACCClauseKind::NumGangs: {
// Restrictions only properly implemented on 'compute' constructs, and
// 'compute' constructs are the only construct that can do anything with
// this yet, so skip/treat as unimplemented in this case.
if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
break;

// There is no prose in the standard that says duplicates aren't allowed,
// but this diagnostic is present in other compilers, as well as makes
// sense.
if (checkAlreadyHasClauseOfKind(*this, ExistingClauses, Clause))
return nullptr;

if (Clause.getIntExprs().empty())
Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args)
<< /*NoArgs=*/0;

unsigned MaxArgs =
(Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel ||
Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop)
? 3
: 1;
if (Clause.getIntExprs().size() > MaxArgs)
Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args)
<< /*NoArgs=*/1 << Clause.getDirectiveKind() << MaxArgs
<< Clause.getIntExprs().size();

// Create the AST node for the clause even if the number of expressions is
// incorrect.
return OpenACCNumGangsClause::Create(
getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(),
Clause.getIntExprs(), Clause.getEndLoc());
break;
}
case OpenACCClauseKind::NumWorkers: {
// Restrictions only properly implemented on 'compute' constructs, and
// 'compute' constructs are the only construct that can do anything with
Expand Down
6 changes: 0 additions & 6 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14261,12 +14261,6 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn,
OverloadResult, AllowTypoCorrection);
}

static bool IsOverloaded(const UnresolvedSetImpl &Functions) {
return Functions.size() > 1 ||
(Functions.size() == 1 &&
isa<FunctionTemplateDecl>((*Functions.begin())->getUnderlyingDecl()));
}

ExprResult Sema::CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass,
NestedNameSpecifierLoc NNSLoc,
DeclarationNameInfo DNI,
Expand Down
40 changes: 39 additions & 1 deletion clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -11162,6 +11162,32 @@ void OpenACCClauseTransform<Derived>::VisitSelfClause(
ParsedClause.getEndLoc());
}

template <typename Derived>
void OpenACCClauseTransform<Derived>::VisitNumGangsClause(
const OpenACCNumGangsClause &C) {
llvm::SmallVector<Expr *> InstantiatedIntExprs;

for (Expr *CurIntExpr : C.getIntExprs()) {
ExprResult Res = Self.TransformExpr(CurIntExpr);

if (!Res.isUsable())
return;

Res = Self.getSema().OpenACC().ActOnIntExpr(OpenACCDirectiveKind::Invalid,
C.getClauseKind(),
C.getBeginLoc(), Res.get());
if (!Res.isUsable())
return;

InstantiatedIntExprs.push_back(Res.get());
}

ParsedClause.setIntExprDetails(InstantiatedIntExprs);
NewClause = OpenACCNumGangsClause::Create(
Self.getSema().getASTContext(), ParsedClause.getBeginLoc(),
ParsedClause.getLParenLoc(), ParsedClause.getIntExprs(),
ParsedClause.getEndLoc());
}
template <typename Derived>
void OpenACCClauseTransform<Derived>::VisitNumWorkersClause(
const OpenACCNumWorkersClause &C) {
Expand Down Expand Up @@ -12917,6 +12943,19 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
ArraySize = NewArraySize.get();
}

// Per C++0x [expr.new]p5, the type being constructed may be a
// typedef of an array type.
QualType AllocType = AllocTypeInfo->getType();
if (ArraySize && E->isTypeDependent()) {
if (const ConstantArrayType *Array =
SemaRef.Context.getAsConstantArrayType(AllocType)) {
ArraySize = IntegerLiteral::Create(SemaRef.Context, Array->getSize(),
SemaRef.Context.getSizeType(),
E->getBeginLoc());
AllocType = Array->getElementType();
}
}

// Transform the placement arguments (if any).
bool ArgumentChanged = false;
SmallVector<Expr*, 8> PlacementArgs;
Expand Down Expand Up @@ -12978,7 +13017,6 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
return E;
}

QualType AllocType = AllocTypeInfo->getType();
if (!ArraySize) {
// If no array size was specified, but the new expression was
// instantiated with an array type (e.g., "new T" where T is
Expand Down
246 changes: 131 additions & 115 deletions clang/lib/Serialization/ASTReader.cpp

Large diffs are not rendered by default.

280 changes: 147 additions & 133 deletions clang/lib/Serialization/ASTReaderDecl.cpp

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions clang/lib/Serialization/ASTReaderInternals.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ class ASTDeclContextNameLookupTrait {
static const int MaxTables = 4;

/// The lookup result is a list of global declaration IDs.
using data_type = SmallVector<DeclID, 4>;
using data_type = SmallVector<GlobalDeclID, 4>;

struct data_type_builder {
data_type &Data;
llvm::DenseSet<DeclID> Found;
llvm::DenseSet<GlobalDeclID> Found;

data_type_builder(data_type &D) : Data(D) {}

void insert(DeclID ID) {
void insert(GlobalDeclID ID) {
// Just use a linear scan unless we have more than a few IDs.
if (Found.empty() && !Data.empty()) {
if (Data.size() <= 4) {
Expand Down Expand Up @@ -108,7 +108,7 @@ class ASTDeclContextNameLookupTrait {

static void MergeDataInto(const data_type &From, data_type_builder &To) {
To.Data.reserve(To.Data.size() + From.size());
for (DeclID ID : From)
for (GlobalDeclID ID : From)
To.insert(ID);
}

Expand Down
37 changes: 23 additions & 14 deletions clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3210,7 +3210,7 @@ uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
return 0;

uint64_t Offset = Stream.GetCurrentBitNo();
SmallVector<uint32_t, 128> KindDeclPairs;
SmallVector<DeclID, 128> KindDeclPairs;
for (const auto *D : DC->decls()) {
if (DoneWritingDeclsAndTypes && !wasDeclEmitted(D))
continue;
Expand Down Expand Up @@ -3348,11 +3348,11 @@ class ASTMethodPoolTrait {
for (const ObjCMethodList *Method = &Methods.Instance; Method;
Method = Method->getNext())
if (ShouldWriteMethodListNode(Method))
DataLen += 4;
DataLen += sizeof(DeclID);
for (const ObjCMethodList *Method = &Methods.Factory; Method;
Method = Method->getNext())
if (ShouldWriteMethodListNode(Method))
DataLen += 4;
DataLen += sizeof(DeclID);
return emitULEBKeyDataLength(KeyLen, DataLen, Out);
}

Expand Down Expand Up @@ -3410,11 +3410,11 @@ class ASTMethodPoolTrait {
for (const ObjCMethodList *Method = &Methods.Instance; Method;
Method = Method->getNext())
if (ShouldWriteMethodListNode(Method))
LE.write<uint32_t>(Writer.getDeclID(Method->getMethod()));
LE.write<DeclID>(Writer.getDeclID(Method->getMethod()));
for (const ObjCMethodList *Method = &Methods.Factory; Method;
Method = Method->getNext())
if (ShouldWriteMethodListNode(Method))
LE.write<uint32_t>(Writer.getDeclID(Method->getMethod()));
LE.write<DeclID>(Writer.getDeclID(Method->getMethod()));

assert(Out.tell() - Start == DataLen && "Data length is wrong");
}
Expand Down Expand Up @@ -3687,7 +3687,8 @@ class ASTIdentifierTableTrait {
DataLen += 4; // MacroDirectives offset.

if (NeedDecls)
DataLen += std::distance(IdResolver.begin(II), IdResolver.end()) * 4;
DataLen += std::distance(IdResolver.begin(II), IdResolver.end()) *
sizeof(DeclID);
}
return emitULEBKeyDataLength(KeyLen, DataLen, Out);
}
Expand Down Expand Up @@ -3733,7 +3734,7 @@ class ASTIdentifierTableTrait {
// Only emit declarations that aren't from a chained PCH, though.
SmallVector<NamedDecl *, 16> Decls(IdResolver.decls(II));
for (NamedDecl *D : llvm::reverse(Decls))
LE.write<uint32_t>(
LE.write<DeclID>(
Writer.getDeclID(getDeclForLocalLookup(PP.getLangOpts(), D)));
}
}
Expand Down Expand Up @@ -3883,7 +3884,8 @@ class ASTDeclContextNameLookupTrait {

data_type ImportData(const reader::ASTDeclContextNameLookupTrait::data_type &FromReader) {
unsigned Start = DeclIDs.size();
llvm::append_range(DeclIDs, FromReader);
DeclIDs.insert(DeclIDs.end(), DeclIDIterator(FromReader.begin()),
DeclIDIterator(FromReader.end()));
return std::make_pair(Start, DeclIDs.size());
}

Expand Down Expand Up @@ -3928,8 +3930,8 @@ class ASTDeclContextNameLookupTrait {
break;
}

// 4 bytes for each DeclID.
unsigned DataLen = 4 * (Lookup.second - Lookup.first);
// length of DeclIDs.
unsigned DataLen = sizeof(DeclID) * (Lookup.second - Lookup.first);

return emitULEBKeyDataLength(KeyLen, DataLen, Out);
}
Expand Down Expand Up @@ -3972,7 +3974,7 @@ class ASTDeclContextNameLookupTrait {
endian::Writer LE(Out, llvm::endianness::little);
uint64_t Start = Out.tell(); (void)Start;
for (unsigned I = Lookup.first, N = Lookup.second; I != N; ++I)
LE.write<uint32_t>(DeclIDs[I]);
LE.write<DeclID>(DeclIDs[I]);
assert(Out.tell() - Start == DataLen && "Data length is wrong");
}
};
Expand Down Expand Up @@ -5095,7 +5097,7 @@ void ASTWriter::WriteSpecialDeclRecords(Sema &SemaRef) {
DeclsToCheckForDeferredDiags.push_back(getDeclID(D));
if (!DeclsToCheckForDeferredDiags.empty())
Stream.EmitRecord(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS,
DeclsToCheckForDeferredDiags);
DeclsToCheckForDeferredDiags);

// Write the record containing CUDA-specific declaration references.
RecordData CUDASpecialDeclRefs;
Expand Down Expand Up @@ -5486,7 +5488,7 @@ void ASTWriter::WriteDeclAndTypes(ASTContext &Context) {
const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
// Create a lexical update block containing all of the declarations in the
// translation unit that do not come from other AST files.
SmallVector<uint32_t, 128> NewGlobalKindDeclPairs;
SmallVector<DeclID, 128> NewGlobalKindDeclPairs;
for (const auto *D : TU->noload_decls()) {
if (D->isFromASTFile())
continue;
Expand Down Expand Up @@ -7657,6 +7659,14 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
AddStmt(const_cast<Expr *>(SC->getConditionExpr()));
return;
}
case OpenACCClauseKind::NumGangs: {
const auto *NGC = cast<OpenACCNumGangsClause>(C);
writeSourceLocation(NGC->getLParenLoc());
writeUInt32(NGC->getIntExprs().size());
for (Expr *E : NGC->getIntExprs())
AddStmt(E);
return;
}
case OpenACCClauseKind::NumWorkers: {
const auto *NWC = cast<OpenACCNumWorkersClause>(C);
writeSourceLocation(NWC->getLParenLoc());
Expand Down Expand Up @@ -7697,7 +7707,6 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
case OpenACCClauseKind::Reduction:
case OpenACCClauseKind::Collapse:
case OpenACCClauseKind::Bind:
case OpenACCClauseKind::NumGangs:
case OpenACCClauseKind::DeviceNum:
case OpenACCClauseKind::DefaultAsync:
case OpenACCClauseKind::DeviceType:
Expand Down
14 changes: 6 additions & 8 deletions clang/lib/StaticAnalyzer/Checkers/Taint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,21 +216,17 @@ std::vector<SymbolRef> taint::getTaintedSymbolsImpl(ProgramStateRef State,
std::vector<SymbolRef> TaintedSymbols;
if (!Reg)
return TaintedSymbols;
// Element region (array element) is tainted if either the base or the offset
// are tainted.

// Element region (array element) is tainted if the offset is tainted.
if (const ElementRegion *ER = dyn_cast<ElementRegion>(Reg)) {
std::vector<SymbolRef> TaintedIndex =
getTaintedSymbolsImpl(State, ER->getIndex(), K, returnFirstOnly);
llvm::append_range(TaintedSymbols, TaintedIndex);
if (returnFirstOnly && !TaintedSymbols.empty())
return TaintedSymbols; // return early if needed
std::vector<SymbolRef> TaintedSuperRegion =
getTaintedSymbolsImpl(State, ER->getSuperRegion(), K, returnFirstOnly);
llvm::append_range(TaintedSymbols, TaintedSuperRegion);
if (returnFirstOnly && !TaintedSymbols.empty())
return TaintedSymbols; // return early if needed
}

// Symbolic region is tainted if the corresponding symbol is tainted.
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Reg)) {
std::vector<SymbolRef> TaintedRegions =
getTaintedSymbolsImpl(State, SR->getSymbol(), K, returnFirstOnly);
Expand All @@ -239,6 +235,8 @@ std::vector<SymbolRef> taint::getTaintedSymbolsImpl(ProgramStateRef State,
return TaintedSymbols; // return early if needed
}

// Any subregion (including Element and Symbolic regions) is tainted if its
// super-region is tainted.
if (const SubRegion *ER = dyn_cast<SubRegion>(Reg)) {
std::vector<SymbolRef> TaintedSubRegions =
getTaintedSymbolsImpl(State, ER->getSuperRegion(), K, returnFirstOnly);
Expand Down Expand Up @@ -318,4 +316,4 @@ std::vector<SymbolRef> taint::getTaintedSymbolsImpl(ProgramStateRef State,
}
}
return TaintedSymbols;
}
}
68 changes: 65 additions & 3 deletions clang/test/AST/ast-dump-fpfeatures.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Test without serialization:
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-linux -std=c++11 -ast-dump %s \
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-linux -std=c++11 -fcxx-exceptions -ast-dump %s \
// RUN: | FileCheck --strict-whitespace %s

// Test with serialization:
// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-pch -o %t %s
// RUN: %clang_cc1 -x c++ -triple x86_64-pc-linux -include-pch %t -ast-dump-all /dev/null \
// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-pch -fcxx-exceptions -o %t %s
// RUN: %clang_cc1 -x c++ -triple x86_64-pc-linux -include-pch %t -fcxx-exceptions -ast-dump-all /dev/null \
// RUN: | sed -e "s/ <undeserialized declarations>//" -e "s/ imported//" \
// RUN: | FileCheck --strict-whitespace %s

Expand Down Expand Up @@ -187,3 +187,65 @@ float func_18(float x, float y) {
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} ConstRoundingMode=downward

#pragma float_control(precise, off)

__attribute__((optnone))
float func_19(float x, float y) {
return x + y;
}

// CHECK-LABEL: FunctionDecl {{.*}} func_19 'float (float, float)'
// CHECK: CompoundStmt {{.*}} MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1

__attribute__((optnone))
float func_20(float x, float y) try {
return x + y;
} catch (...) {
return 1.0;
}

// CHECK-LABEL: FunctionDecl {{.*}} func_20 'float (float, float)'
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1

struct C21 {
C21(float x, float y);
__attribute__((optnone)) float a_method(float x, float y) {
return x * y;
}
float member;
};

// CHECK-LABEL: CXXMethodDecl {{.*}} a_method 'float (float, float)'
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} 'float' '*' ConstRoundingMode=downward MathErrno=1

__attribute__((optnone)) C21::C21(float x, float y) : member(x + y) {}

// CHECK-LABEL: CXXConstructorDecl {{.*}} C21 'void (float, float)'
// CHECK: CXXCtorInitializer {{.*}} 'member' 'float'
// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1

template <typename T>
__attribute__((optnone)) T func_22(T x, T y) {
return x + y;
}

// CHECK-LABEL: FunctionTemplateDecl {{.*}} func_22
// CHECK: FunctionDecl {{.*}} func_22 'T (T, T)'
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} '+' ConstRoundingMode=downward MathErrno=1
// CHECK: FunctionDecl {{.*}} func_22 'float (float, float)'
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1

float func_23(float x, float y) {
return func_22(x, y);
}
29 changes: 29 additions & 0 deletions clang/test/AST/ast-dump-fpfeatures.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Test without serialization:
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-linux -ast-dump %s \
// RUN: | FileCheck --strict-whitespace %s

// Test with serialization:
// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-pch -o %t %s
// RUN: %clang_cc1 -x objective-c -triple x86_64-pc-linux -include-pch %t -ast-dump-all /dev/null \
// RUN: | sed -e "s/ <undeserialized declarations>//" -e "s/ imported//" \
// RUN: | FileCheck --strict-whitespace %s


@interface Adder
- (float) sum: (float)x with: (float)y __attribute((optnone));
@end

#pragma float_control(precise, off)

@implementation Adder
- (float) sum: (float)x with: (float)y __attribute((optnone)) {
return x + y;
}

@end

// CHECK-LABEL: ObjCImplementationDecl {{.*}} Adder
// CHECK: ObjCMethodDecl {{.*}} - sum:with: 'float'
// CHECK: CompoundStmt {{.*}} MathErrno=1
// CHECK-NEXT: ReturnStmt
// CHECK-NEXT: BinaryOperator {{.*}} 'float' '+' MathErrno=1
24 changes: 24 additions & 0 deletions clang/test/AST/ast-dump-late-parsing.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-linux -std=c++11 -fcxx-exceptions -fdelayed-template-parsing -ast-dump %s \
// RUN: | FileCheck %s

#pragma STDC FENV_ROUND FE_DOWNWARD
#pragma float_control(precise, off)

template <typename T>
__attribute__((optnone)) T func_22(T x, T y) {
return x + y;
}

// CHECK-LABEL: FunctionTemplateDecl {{.*}} func_22
// CHECK: FunctionDecl {{.*}} func_22 'T (T, T)'
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} '+' ConstRoundingMode=downward MathErrno=1
// CHECK: FunctionDecl {{.*}} func_22 'float (float, float)'
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1

float func_23(float x, float y) {
return func_22(x, y);
}
32 changes: 32 additions & 0 deletions clang/test/AST/bitint-suffix.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// RUN: %clang_cc1 -ast-dump -Wno-unused %s | FileCheck --strict-whitespace %s

// CHECK: FunctionDecl 0x{{[^ ]*}} <{{.*}}:[[@LINE+1]]:1, line:{{[0-9]*}}:1> line:[[@LINE+1]]:6 func 'void ()'
void func() {
// Ensure that we calculate the correct type from the literal suffix.

// Note: 0__wb should create an _BitInt(2) because a signed bit-precise
// integer requires one bit for the sign and one bit for the value,
// at a minimum.
// CHECK: TypedefDecl 0x{{[^ ]*}} <col:3, col:29> col:29 zero_wb 'typeof (0wb)':'_BitInt(2)'
typedef __typeof__(0__wb) zero_wb;
// CHECK: TypedefDecl 0x{{[^ ]*}} <col:3, col:30> col:30 neg_zero_wb 'typeof (-0wb)':'_BitInt(2)'
typedef __typeof__(-0__wb) neg_zero_wb;
// CHECK: TypedefDecl 0x{{[^ ]*}} <col:3, col:29> col:29 one_wb 'typeof (1wb)':'_BitInt(2)'
typedef __typeof__(1__wb) one_wb;
// CHECK: TypedefDecl 0x{{[^ ]*}} <col:3, col:30> col:30 neg_one_wb 'typeof (-1wb)':'_BitInt(2)'
typedef __typeof__(-1__wb) neg_one_wb;

// CHECK: TypedefDecl 0x{{[^ ]*}} <col:3, col:30> col:30 zero_uwb 'typeof (0uwb)':'unsigned _BitInt(1)'
typedef __typeof__(0__uwb) zero_uwb;
// CHECK: TypedefDecl 0x{{[^ ]*}} <col:3, col:31> col:31 neg_zero_uwb 'typeof (-0uwb)':'unsigned _BitInt(1)'
typedef __typeof__(-0__uwb) neg_zero_uwb;
// CHECK: TypedefDecl 0x{{[^ ]*}} <col:3, col:30> col:30 one_uwb 'typeof (1uwb)':'unsigned _BitInt(1)'
typedef __typeof__(1__uwb) one_uwb;

// Try a value that is too large to fit in [u]intmax_t.

// CHECK: TypedefDecl 0x{{[^ ]*}} <col:3, col:49> col:49 huge_uwb 'typeof (18446744073709551616uwb)':'unsigned _BitInt(65)'
typedef __typeof__(18446744073709551616__uwb) huge_uwb;
// CHECK: TypedefDecl 0x{{[^ ]*}} <col:3, col:48> col:48 huge_wb 'typeof (18446744073709551616wb)':'_BitInt(66)'
typedef __typeof__(18446744073709551616__wb) huge_wb;
}
8 changes: 4 additions & 4 deletions clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -o - | FileCheck %s

// CHECK-LABEL: builtin_lerp_half_vector
// CHECK: %dx.lerp = call <3 x half> @llvm.dx.lerp.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2)
// CHECK: ret <3 x half> %dx.lerp
// CHECK: %hlsl.lerp = call <3 x half> @llvm.dx.lerp.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2)
// CHECK: ret <3 x half> %hlsl.lerp
half3 builtin_lerp_half_vector (half3 p0) {
return __builtin_hlsl_lerp ( p0, p0, p0 );
}

// CHECK-LABEL: builtin_lerp_floar_vector
// CHECK: %dx.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2)
// CHECK: ret <2 x float> %dx.lerp
// CHECK: %hlsl.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2)
// CHECK: ret <2 x float> %hlsl.lerp
float2 builtin_lerp_floar_vector ( float2 p0) {
return __builtin_hlsl_lerp ( p0, p0, p0 );
}
Loading