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

/// 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 OpenACCClauseWithIntExprs {
Expr *IntExpr;

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

public:
bool hasIntExpr() const { return !getIntExprs().empty(); }
const Expr *getIntExpr() const {
return hasIntExpr() ? getIntExprs()[0] : nullptr;
}

Expr *getIntExpr() { return hasIntExpr() ? getIntExprs()[0] : nullptr; };
};

class OpenACCNumWorkersClause : public OpenACCClauseWithSingleIntExpr {
OpenACCNumWorkersClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
Expr *IntExpr, SourceLocation EndLoc);

public:
static OpenACCNumWorkersClause *Create(const ASTContext &C,
SourceLocation BeginLoc,
SourceLocation LParenLoc,
Expr *IntExpr, SourceLocation EndLoc);
};

class OpenACCVectorLengthClause : public OpenACCClauseWithSingleIntExpr {
OpenACCVectorLengthClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
Expr *IntExpr, SourceLocation EndLoc);

public:
static OpenACCVectorLengthClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
Expr *IntExpr, SourceLocation EndLoc);
};

template <class Impl> class OpenACCClauseVisitor {
Impl &getDerived() { return static_cast<Impl &>(*this); }

Expand Down
5 changes: 0 additions & 5 deletions clang/include/clang/AST/Stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -1067,11 +1067,6 @@ class alignas(void *) Stmt {
/// argument-dependent lookup if this is the operand of a function call.
LLVM_PREFERRED_TYPE(bool)
unsigned RequiresADL : 1;

/// True if these lookup results are overloaded. This is pretty trivially
/// rederivable if we urgently need to kill this field.
LLVM_PREFERRED_TYPE(bool)
unsigned Overloaded : 1;
};
static_assert(sizeof(UnresolvedLookupExprBitfields) <= 4,
"UnresolvedLookupExprBitfields must be <= than 4 bytes to"
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/Analysis/FlowSensitive/ASTOps.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class RecordInitListHelper {
public:
// `InitList` must have record type.
RecordInitListHelper(const InitListExpr *InitList);
RecordInitListHelper(const CXXParenListInitExpr *ParenInitList);

// Base classes with their associated initializer expressions.
ArrayRef<std::pair<const CXXBaseSpecifier *, Expr *>> base_inits() const {
Expand All @@ -68,6 +69,9 @@ class RecordInitListHelper {
}

private:
RecordInitListHelper(QualType Ty, std::vector<const FieldDecl *> Fields,
ArrayRef<Expr *> Inits);

SmallVector<std::pair<const CXXBaseSpecifier *, Expr *>> BaseInits;
SmallVector<std::pair<const FieldDecl *, Expr *>> FieldInits;

Expand All @@ -92,6 +96,9 @@ struct ReferencedDecls {
/// Returns declarations that are declared in or referenced from `FD`.
ReferencedDecls getReferencedDecls(const FunctionDecl &FD);

/// Returns declarations that are declared in or referenced from `S`.
ReferencedDecls getReferencedDecls(const Stmt &S);

} // namespace dataflow
} // namespace clang

Expand Down
53 changes: 33 additions & 20 deletions clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class Environment {
virtual ComparisonResult compare(QualType Type, const Value &Val1,
const Environment &Env1, const Value &Val2,
const Environment &Env2) {
// FIXME: Consider adding QualType to RecordValue and removing the Type
// FIXME: Consider adding `QualType` to `Value` and removing the `Type`
// argument here.
return ComparisonResult::Unknown;
}
Expand Down 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 Expand Up @@ -407,20 +422,15 @@ class Environment {
/// storage locations and values for indirections until it finds a
/// non-pointer/non-reference type.
///
/// If `Type` is a class, struct, or union type, creates values for all
/// modeled fields (including synthetic fields) and calls `setValue()` to
/// associate the `RecordValue` with its storage location
/// (`RecordValue::getLoc()`).
///
/// If `Type` is one of the following types, this function will always return
/// a non-null pointer:
/// - `bool`
/// - Any integer type
/// - Any class, struct, or union type
///
/// Requirements:
///
/// `Type` must not be null.
/// - `Type` must not be null.
/// - `Type` must not be a reference type or record type.
Value *createValue(QualType Type);

/// Creates an object (i.e. a storage location with an associated value) of
Expand Down Expand Up @@ -452,6 +462,7 @@ class Environment {
/// Initializes the fields (including synthetic fields) of `Loc` with values,
/// unless values of the field type are not supported or we hit one of the
/// limits at which we stop producing values.
/// If a field already has a value, that value is preserved.
/// If `Type` is provided, initializes only those fields that are modeled for
/// `Type`; this is intended for use in cases where `Loc` is a derived type
/// and we only want to initialize the fields of a base type.
Expand All @@ -461,6 +472,10 @@ class Environment {
}

/// Assigns `Val` as the value of `Loc` in the environment.
///
/// Requirements:
///
/// `Loc` must not be a `RecordStorageLocation`.
void setValue(const StorageLocation &Loc, Value &Val);

/// Clears any association between `Loc` and a value in the environment.
Expand All @@ -470,20 +485,24 @@ class Environment {
///
/// Requirements:
///
/// - `E` must be a prvalue
/// - If `Val` is a `RecordValue`, its `RecordStorageLocation` must be
/// `getResultObjectLocation(E)`. An exception to this is if `E` is an
/// expression that originally creates a `RecordValue` (such as a
/// `CXXConstructExpr` or `CallExpr`), as these establish the location of
/// the result object in the first place.
/// - `E` must be a prvalue.
/// - `E` must not have record type.
void setValue(const Expr &E, Value &Val);

/// Returns the value assigned to `Loc` in the environment or null if `Loc`
/// isn't assigned a value in the environment.
///
/// Requirements:
///
/// `Loc` must not be a `RecordStorageLocation`.
Value *getValue(const StorageLocation &Loc) const;

/// Equivalent to `getValue(getStorageLocation(D))` if `D` is assigned a
/// storage location in the environment, otherwise returns null.
///
/// Requirements:
///
/// `D` must not have record type.
Value *getValue(const ValueDecl &D) const;

/// Equivalent to `getValue(getStorageLocation(E, SP))` if `E` is assigned a
Expand Down Expand Up @@ -775,12 +794,6 @@ RecordStorageLocation *getImplicitObjectLocation(const CXXMemberCallExpr &MCE,
RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME,
const Environment &Env);

/// Associates a new `RecordValue` with `Loc` and returns the new value.
RecordValue &refreshRecordValue(RecordStorageLocation &Loc, Environment &Env);

/// Associates a new `RecordValue` with `Expr` and returns the new value.
RecordValue &refreshRecordValue(const Expr &Expr, Environment &Env);

} // namespace dataflow
} // namespace clang

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
41 changes: 0 additions & 41 deletions clang/include/clang/Analysis/FlowSensitive/Value.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ class Value {
enum class Kind {
Integer,
Pointer,
Record,

// TODO: Top values should not be need to be type-specific.
TopBool,
Expand Down Expand Up @@ -67,7 +66,6 @@ class Value {
/// Properties may not be set on `RecordValue`s; use synthetic fields instead
/// (for details, see documentation for `RecordStorageLocation`).
void setProperty(llvm::StringRef Name, Value &Val) {
assert(getKind() != Kind::Record);
Properties.insert_or_assign(Name, &Val);
}

Expand Down Expand Up @@ -184,45 +182,6 @@ class PointerValue final : public Value {
StorageLocation &PointeeLoc;
};

/// Models a value of `struct` or `class` type.
/// In C++, prvalues of class type serve only a limited purpose: They can only
/// be used to initialize a result object. It is not possible to access member
/// variables or call member functions on a prvalue of class type.
/// Correspondingly, `RecordValue` also serves only a limited purpose: It
/// conveys a prvalue of class type from the place where the object is
/// constructed to the result object that it initializes.
///
/// When creating a prvalue of class type, we already need a storage location
/// for `this`, even though prvalues are otherwise not associated with storage
/// locations. `RecordValue` is therefore essentially a wrapper for a storage
/// location, which is then used to set the storage location for the result
/// object when we process the AST node for that result object.
///
/// For example:
/// MyStruct S = MyStruct(3);
///
/// In this example, `MyStruct(3) is a prvalue, which is modeled as a
/// `RecordValue` that wraps a `RecordStorageLocation`. This
/// `RecordStorageLocation` is then used as the storage location for `S`.
///
/// Over time, we may eliminate `RecordValue` entirely. See also the discussion
/// here: https://reviews.llvm.org/D155204#inline-1503204
class RecordValue final : public Value {
public:
explicit RecordValue(RecordStorageLocation &Loc)
: Value(Kind::Record), Loc(Loc) {}

static bool classof(const Value *Val) {
return Val->getKind() == Kind::Record;
}

/// Returns the storage location that this `RecordValue` is associated with.
RecordStorageLocation &getLoc() const { return Loc; }

private:
RecordStorageLocation &Loc;
};

raw_ostream &operator<<(raw_ostream &OS, const Value &Val);

} // namespace dataflow
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/DebugOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ DEBUGOPT(CodeViewCommandLine, 1, 0)
/// Whether emit extra debug info for sample pgo profile collection.
DEBUGOPT(DebugInfoForProfiling, 1, 0)

/// Whether to emit DW_TAG_template_alias for template aliases.
DEBUGOPT(DebugTemplateAlias, 1, 0)

/// Whether to emit .debug_gnu_pubnames section instead of .debug_pubnames.
DEBUGOPT(DebugNameTable, 2, 0)

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">;
1 change: 1 addition & 0 deletions clang/include/clang/Basic/DiagnosticInstallAPIKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def err_no_matching_target : Error<"no matching target found for target variant
def err_unsupported_vendor : Error<"vendor '%0' is not supported: '%1'">;
def err_unsupported_environment : Error<"environment '%0' is not supported: '%1'">;
def err_unsupported_os : Error<"os '%0' is not supported: '%1'">;
def err_cannot_read_alias_list : Error<"could not read alias list '%0': %1">;
} // end of command line category.

let CategoryName = "Verification" in {
Expand Down
4 changes: 3 additions & 1 deletion clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -863,6 +863,8 @@ def err_empty_requires_expr : Error<
"a requires expression must contain at least one requirement">;
def err_requires_expr_parameter_list_ellipsis : Error<
"varargs not allowed in requires expression">;
def err_requires_expr_explicit_object_parameter: Error<
"a requires expression cannot have an explicit object parameter">;
def err_expected_semi_requirement : Error<
"expected ';' at end of requirement">;
def err_requires_expr_missing_arrow : Error<
Expand Down Expand Up @@ -1652,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
36 changes: 27 additions & 9 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 @@ -3669,6 +3669,9 @@ def warn_attribute_dllexport_explicit_instantiation_decl : Warning<
def warn_attribute_dllexport_explicit_instantiation_def : Warning<
"'dllexport' attribute ignored on explicit instantiation definition">,
InGroup<IgnoredAttributes>;
def warn_attribute_exclude_from_explicit_instantiation_local_class : Warning<
"%0 attribute ignored on local class%select{| member}1">,
InGroup<IgnoredAttributes>;
def warn_invalid_initializer_from_system_header : Warning<
"invalid constructor from class in system header, should not be explicit">,
InGroup<DiagGroup<"invalid-initializer-from-system-header">>;
Expand Down Expand Up @@ -3752,14 +3755,12 @@ def err_sme_definition_using_za_in_non_sme_target : Error<
def err_sme_definition_using_zt0_in_non_sme2_target : Error<
"function using ZT0 state requires 'sme2'">;
def warn_sme_streaming_pass_return_vl_to_non_streaming : Warning<
"passing a VL-dependent argument to/from a function that has a different"
" streaming-mode. The streaming and non-streaming vector lengths may be"
" different">,
"%select{returning|passing}0 a VL-dependent argument %select{from|to}0 a function with a different"
" streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime">,
InGroup<AArch64SMEAttributes>, DefaultIgnore;
def warn_sme_locally_streaming_has_vl_args_returns : Warning<
"passing/returning a VL-dependent argument to/from a __arm_locally_streaming"
" function. The streaming and non-streaming vector"
" lengths may be different">,
"%select{returning|passing}0 a VL-dependent argument %select{from|to}0 a locally streaming function is undefined"
" behaviour when the streaming and non-streaming vector lengths are different at runtime">,
InGroup<AArch64SMEAttributes>, DefaultIgnore;
def err_conflicting_attributes_arm_state : Error<
"conflicting attributes for state '%0'">;
Expand Down Expand Up @@ -12278,4 +12279,21 @@ def warn_acc_if_self_conflict
: Warning<"OpenACC construct 'self' has no effect when an 'if' clause "
"evaluates to true">,
InGroup<DiagGroup<"openacc-self-if-potential-conflict">>;
def err_acc_int_expr_requires_integer
: Error<"OpenACC %select{clause|directive}0 '%1' requires expression of "
"integer type (%2 invalid)">;
def err_acc_int_expr_incomplete_class_type
: Error<"OpenACC integer expression has incomplete class type %0">;
def err_acc_int_expr_explicit_conversion
: Error<"OpenACC integer expression type %0 requires explicit conversion "
"to %1">;
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.
16 changes: 16 additions & 0 deletions clang/include/clang/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,11 @@ class LangOptionsBase {
/// - the parameter list of a template template parameter
Ver17,

/// Attempt to be ABI-compatible with code generated by Clang 18.0.x.
/// This causes clang to revert some fixes to the mangling of lambdas
/// in the initializers of members of local classes.
Ver18,

/// Conform to the underlying platform's C and C++ ABIs as closely
/// as we can.
Latest
Expand Down Expand Up @@ -873,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 @@ -954,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 @@ -1010,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
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/OpenACCClauses.def
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,8 @@
VISIT_CLAUSE(Default)
VISIT_CLAUSE(If)
VISIT_CLAUSE(Self)
VISIT_CLAUSE(NumGangs)
VISIT_CLAUSE(NumWorkers)
VISIT_CLAUSE(VectorLength)

#undef VISIT_CLAUSE
101 changes: 76 additions & 25 deletions clang/include/clang/Basic/riscv_vector.td

Large diffs are not rendered by default.

17 changes: 11 additions & 6 deletions clang/include/clang/Driver/OffloadBundler.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ struct OffloadTargetInfo {
// - Version (2 bytes)
// - Compression Method (2 bytes) - Uses the values from
// llvm::compression::Format.
// - Total file size (4 bytes). Available in version 2 and above.
// - Uncompressed Size (4 bytes).
// - Truncated MD5 Hash (8 bytes).
// - Compressed Data (variable length).
Expand All @@ -109,13 +110,17 @@ class CompressedOffloadBundle {
static inline const size_t MagicSize = 4;
static inline const size_t VersionFieldSize = sizeof(uint16_t);
static inline const size_t MethodFieldSize = sizeof(uint16_t);
static inline const size_t SizeFieldSize = sizeof(uint32_t);
static inline const size_t HashFieldSize = 8;
static inline const size_t HeaderSize = MagicSize + VersionFieldSize +
MethodFieldSize + SizeFieldSize +
HashFieldSize;
static inline const size_t FileSizeFieldSize = sizeof(uint32_t);
static inline const size_t UncompressedSizeFieldSize = sizeof(uint32_t);
static inline const size_t HashFieldSize = sizeof(uint64_t);
static inline const size_t V1HeaderSize =
MagicSize + VersionFieldSize + MethodFieldSize +
UncompressedSizeFieldSize + HashFieldSize;
static inline const size_t V2HeaderSize =
MagicSize + VersionFieldSize + FileSizeFieldSize + MethodFieldSize +
UncompressedSizeFieldSize + HashFieldSize;
static inline const llvm::StringRef MagicNumber = "CCOB";
static inline const uint16_t Version = 1;
static inline const uint16_t Version = 2;

public:
static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
Expand Down
40 changes: 34 additions & 6 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -807,8 +807,12 @@ def gcc_install_dir_EQ : Joined<["--"], "gcc-install-dir=">,
"Note: executables (e.g. ld) used by the compiler are not overridden by the selected GCC installation">;
def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[NoXarchOption]>,
Visibility<[ClangOption, FlangOption]>,
HelpText<"Specify a directory where Clang can find 'include' and 'lib{,32,64}/gcc{,-cross}/$triple/$version'. "
"Clang will use the GCC installation with the largest version">;
HelpText<
"Specify a directory where Clang can find 'include' and 'lib{,32,64}/gcc{,-cross}/$triple/$version'. "
"Clang will use the GCC installation with the largest version">,
HelpTextForVariants<[FlangOption],
"Specify a directory where Flang can find 'lib{,32,64}/gcc{,-cross}/$triple/$version'. "
"Flang will use the GCC installation with the largest version">;
def gcc_triple_EQ : Joined<["--"], "gcc-triple=">,
HelpText<"Search for the GCC installation with the specified triple.">;
def CC : Flag<["-"], "CC">, Visibility<[ClangOption, CC1Option]>,
Expand Down Expand Up @@ -1505,6 +1509,7 @@ def end_no_unused_arguments : Flag<["--"], "end-no-unused-arguments">,
def interface_stub_version_EQ : JoinedOrSeparate<["-"], "interface-stub-version=">,
Visibility<[ClangOption, CC1Option]>;
def exported__symbols__list : Separate<["-"], "exported_symbols_list">;
def alias_list : Separate<["-"], "alias_list">, Flags<[LinkerInput]>;
def extract_api : Flag<["-"], "extract-api">,
Visibility<[ClangOption, CC1Option]>, Group<Action_Group>,
HelpText<"Extract API information">;
Expand Down Expand Up @@ -3099,6 +3104,11 @@ defm modules_skip_header_search_paths : BoolFOption<"modules-skip-header-search-
HeaderSearchOpts<"ModulesSkipHeaderSearchPaths">, DefaultFalse,
PosFlag<SetTrue, [], [], "Disable writing header search paths">,
NegFlag<SetFalse>, BothFlags<[], [CC1Option]>>;
def fno_modules_prune_non_affecting_module_map_files :
Flag<["-"], "fno-modules-prune-non-affecting-module-map-files">,
Group<f_Group>, Flags<[]>, Visibility<[CC1Option]>,
MarshallingInfoNegativeFlag<HeaderSearchOpts<"ModulesPruneNonAffectingModuleMaps">>,
HelpText<"Do not prune non-affecting module map files when writing module files">;

def fincremental_extensions :
Flag<["-"], "fincremental-extensions">,
Expand Down Expand Up @@ -4308,6 +4318,8 @@ def gsplit_dwarf_EQ : Joined<["-"], "gsplit-dwarf=">, Group<g_flags_Group>,
Values<"split,single">;
def gno_split_dwarf : Flag<["-"], "gno-split-dwarf">, Group<g_flags_Group>,
Visibility<[ClangOption, CLOption, DXCOption]>;
def gtemplate_alias : Flag<["-"], "gtemplate-alias">, Group<g_flags_Group>, Visibility<[ClangOption, CC1Option]>;
def gno_template_alias : Flag<["-"], "gno-template-alias">, Group<g_flags_Group>, Visibility<[ClangOption]>;
def gsimple_template_names : Flag<["-"], "gsimple-template-names">, Group<g_flags_Group>;
def gsimple_template_names_EQ
: Joined<["-"], "gsimple-template-names=">,
Expand Down Expand Up @@ -4744,9 +4756,9 @@ def munaligned_symbols : Flag<["-"], "munaligned-symbols">, Group<m_Group>,
HelpText<"Expect external char-aligned symbols to be without ABI alignment (SystemZ only)">;
def mno_unaligned_symbols : Flag<["-"], "mno-unaligned-symbols">, Group<m_Group>,
HelpText<"Expect external char-aligned symbols to be without ABI alignment (SystemZ only)">;
def mstrict_align : Flag<["-"], "mstrict-align">,
def mstrict_align : Flag<["-"], "mstrict-align">, Group<m_Group>,
HelpText<"Force all memory accesses to be aligned (AArch64/LoongArch/RISC-V only)">;
def mno_strict_align : Flag<["-"], "mno-strict-align">,
def mno_strict_align : Flag<["-"], "mno-strict-align">, Group<m_Group>,
HelpText<"Allow memory accesses to be unaligned (AArch64/LoongArch/RISC-V only)">;
def mno_thumb : Flag<["-"], "mno-thumb">, Group<m_arm_Features_Group>;
def mrestrict_it: Flag<["-"], "mrestrict-it">, Group<m_arm_Features_Group>,
Expand Down Expand Up @@ -5029,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 Expand Up @@ -5490,6 +5508,14 @@ def fno_rtlib_add_rpath: Flag<["-"], "fno-rtlib-add-rpath">,
Visibility<[ClangOption, FlangOption]>,
HelpText<"Do not add -rpath with architecture-specific resource directory to the linker flags. "
"When --hip-link is specified, do not add -rpath with HIP runtime library directory to the linker flags">;
def frtlib_defaultlib : Flag<["-"], "frtlib-defaultlib">,
Visibility<[ClangOption, CLOption]>,
Group<f_Group>,
HelpText<"On Windows, emit /defaultlib: directives to link compiler-rt libraries (default)">;
def fno_rtlib_defaultlib : Flag<["-"], "fno-rtlib-defaultlib">,
Visibility<[ClangOption, CLOption]>,
Group<f_Group>,
HelpText<"On Windows, do not emit /defaultlib: directives to link compiler-rt libraries">;
def offload_add_rpath: Flag<["--"], "offload-add-rpath">,
Flags<[NoArgumentUnused]>,
Alias<frtlib_add_rpath>;
Expand Down Expand Up @@ -8343,14 +8369,15 @@ def _SLASH_FI : CLJoinedOrSeparate<"FI">,
def _SLASH_Fe : CLJoined<"Fe">,
HelpText<"Set output executable file name">,
MetaVarName<"<file or dir/>">;
def _SLASH_Fe_COLON : CLJoined<"Fe:">, Alias<_SLASH_Fe>;
def _SLASH_Fe_COLON : CLJoinedOrSeparate<"Fe:">, Alias<_SLASH_Fe>;
def _SLASH_Fi : CLCompileJoined<"Fi">,
HelpText<"Set preprocess output file name (with /P)">,
MetaVarName<"<file>">;
def _SLASH_Fi_COLON : CLJoinedOrSeparate<"Fi:">, Alias<_SLASH_Fi>;
def _SLASH_Fo : CLCompileJoined<"Fo">,
HelpText<"Set output object file (with /c)">,
MetaVarName<"<file or dir/>">;
def _SLASH_Fo_COLON : CLCompileJoined<"Fo:">, Alias<_SLASH_Fo>;
def _SLASH_Fo_COLON : CLCompileJoinedOrSeparate<"Fo:">, Alias<_SLASH_Fo>;
def _SLASH_guard : CLJoined<"guard:">,
HelpText<"Enable Control Flow Guard with /guard:cf, or only the table with /guard:cf,nochecks. "
"Enable EH Continuation Guard with /guard:ehcont">;
Expand Down Expand Up @@ -8445,6 +8472,7 @@ def _SLASH_Zc_dllexportInlines_ : CLFlag<"Zc:dllexportInlines-">,
HelpText<"Do not dllexport/dllimport inline member functions of dllexport/import classes">;
def _SLASH_Fp : CLJoined<"Fp">,
HelpText<"Set pch file name (with /Yc and /Yu)">, MetaVarName<"<file>">;
def _SLASH_Fp_COLON : CLJoinedOrSeparate<"Fp:">, Alias<_SLASH_Fp>;

def _SLASH_Gd : CLFlag<"Gd">,
HelpText<"Set __cdecl as a default calling convention">;
Expand Down
135 changes: 91 additions & 44 deletions clang/include/clang/ExtractAPI/API.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,20 +208,20 @@ struct APIRecord {
RK_ClassTemplate,
RK_ClassTemplateSpecialization,
RK_ClassTemplatePartialSpecialization,
RK_LastRecordContext,
RK_GlobalFunction,
RK_GlobalFunctionTemplate,
RK_GlobalFunctionTemplateSpecialization,
RK_StructField,
RK_UnionField,
RK_CXXField,
RK_StaticField,
RK_CXXFieldTemplate,
RK_GlobalVariable,
RK_GlobalVariableTemplate,
RK_GlobalVariableTemplateSpecialization,
RK_GlobalVariableTemplatePartialSpecialization,
RK_LastRecordContext,
RK_GlobalFunction,
RK_GlobalFunctionTemplate,
RK_GlobalFunctionTemplateSpecialization,
RK_EnumConstant,
RK_StructField,
RK_UnionField,
RK_StaticField,
RK_CXXField,
RK_CXXFieldTemplate,
RK_Concept,
RK_CXXStaticMethod,
RK_CXXInstanceMethod,
Expand Down Expand Up @@ -321,6 +321,10 @@ class RecordContext {

RecordContext(APIRecord::RecordKind Kind) : Kind(Kind) {}

/// Append \p Other children chain into ours and empty out Other's record
/// chain.
void stealRecordChain(RecordContext &Other);

APIRecord::RecordKind getKind() const { return Kind; }

struct record_iterator {
Expand Down Expand Up @@ -370,6 +374,7 @@ class RecordContext {
APIRecord::RecordKind Kind;
mutable APIRecord *First = nullptr;
mutable APIRecord *Last = nullptr;
bool IsWellFormed() const;

protected:
friend class APISet;
Expand Down Expand Up @@ -475,31 +480,36 @@ struct GlobalFunctionTemplateSpecializationRecord : GlobalFunctionRecord {
};

/// This holds information associated with global functions.
struct GlobalVariableRecord : APIRecord {
struct GlobalVariableRecord : APIRecord, RecordContext {
GlobalVariableRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(RK_GlobalVariable, USR, Name, Parent, Loc,
std::move(Availability), Linkage, Comment, Declaration,
SubHeading, IsFromSystemHeader) {}
SubHeading, IsFromSystemHeader),
RecordContext(RK_GlobalVariable) {}

GlobalVariableRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent,

PresumedLoc Loc, AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
Linkage, Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
IsFromSystemHeader),
RecordContext(Kind) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_GlobalVariable; }
static bool classofKind(RecordKind K) {
return K == RK_GlobalVariable || K == RK_GlobalVariableTemplate ||
K == RK_GlobalVariableTemplateSpecialization ||
K == RK_GlobalVariableTemplatePartialSpecialization;
}

private:
virtual void anchor();
Expand Down Expand Up @@ -591,36 +601,64 @@ struct EnumConstantRecord : APIRecord {
virtual void anchor();
};

struct TagRecord : APIRecord, RecordContext {
TagRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
bool IsFromSystemHeader, bool IsEmbeddedInVarDeclarator,
AccessControl Access = AccessControl())
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader, std::move(Access)),
RecordContext(Kind),
IsEmbeddedInVarDeclarator(IsEmbeddedInVarDeclarator){};

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) {
return K == RK_Struct || K == RK_Union || K == RK_Enum;
}

bool IsEmbeddedInVarDeclarator;

virtual ~TagRecord() = 0;
};

/// This holds information associated with enums.
struct EnumRecord : APIRecord, RecordContext {
struct EnumRecord : TagRecord {
EnumRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(RK_Enum, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
RecordContext(RK_Enum) {}
DeclarationFragments SubHeading, bool IsFromSystemHeader,
bool IsEmbeddedInVarDeclarator,
AccessControl Access = AccessControl())
: TagRecord(RK_Enum, USR, Name, Parent, Loc, std::move(Availability),
Comment, Declaration, SubHeading, IsFromSystemHeader,
IsEmbeddedInVarDeclarator, std::move(Access)) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}

static bool classofKind(RecordKind K) { return K == RK_Enum; }

private:
virtual void anchor();
};

/// This holds information associated with struct or union fields fields.
struct RecordFieldRecord : APIRecord {
struct RecordFieldRecord : APIRecord, RecordContext {
RecordFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
IsFromSystemHeader),
RecordContext(Kind) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
Expand All @@ -633,16 +671,17 @@ struct RecordFieldRecord : APIRecord {
};

/// This holds information associated with structs and unions.
struct RecordRecord : APIRecord, RecordContext {
struct RecordRecord : TagRecord {
RecordRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
RecordContext(Kind) {}
DeclarationFragments SubHeading, bool IsFromSystemHeader,
bool IsEmbeddedInVarDeclarator,
AccessControl Access = AccessControl())
: TagRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
Comment, Declaration, SubHeading, IsFromSystemHeader,
IsEmbeddedInVarDeclarator, std::move(Access)) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
Expand All @@ -651,6 +690,8 @@ struct RecordRecord : APIRecord, RecordContext {
return K == RK_Struct || K == RK_Union;
}

bool isAnonymousWithNoTypedef() { return Name.empty(); }

virtual ~RecordRecord() = 0;
};

Expand All @@ -676,9 +717,11 @@ struct StructRecord : RecordRecord {
StructRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
DeclarationFragments SubHeading, bool IsFromSystemHeader,
bool IsEmbeddedInVarDeclarator)
: RecordRecord(RK_Struct, USR, Name, Parent, Loc, std::move(Availability),
Comment, Declaration, SubHeading, IsFromSystemHeader) {}
Comment, Declaration, SubHeading, IsFromSystemHeader,
IsEmbeddedInVarDeclarator) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
Expand Down Expand Up @@ -711,9 +754,11 @@ struct UnionRecord : RecordRecord {
UnionRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
DeclarationFragments SubHeading, bool IsFromSystemHeader,
bool IsEmbeddedInVarDeclarator)
: RecordRecord(RK_Union, USR, Name, Parent, Loc, std::move(Availability),
Comment, Declaration, SubHeading, IsFromSystemHeader) {}
Comment, Declaration, SubHeading, IsFromSystemHeader,
IsEmbeddedInVarDeclarator) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
Expand All @@ -724,15 +769,16 @@ struct UnionRecord : RecordRecord {
virtual void anchor();
};

struct CXXFieldRecord : APIRecord {
struct CXXFieldRecord : APIRecord, RecordContext {
CXXFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
bool IsFromSystemHeader)
: APIRecord(RK_CXXField, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader, std::move(Access)) {}
IsFromSystemHeader, std::move(Access)),
RecordContext(RK_CXXField) {}

CXXFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
Expand All @@ -742,7 +788,8 @@ struct CXXFieldRecord : APIRecord {
bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader, std::move(Access)) {}
IsFromSystemHeader, std::move(Access)),
RecordContext(Kind) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
Expand Down Expand Up @@ -1118,18 +1165,18 @@ struct ObjCContainerRecord : APIRecord, RecordContext {
virtual ~ObjCContainerRecord() = 0;
};

struct CXXClassRecord : APIRecord, RecordContext {
struct CXXClassRecord : RecordRecord {
SmallVector<SymbolReference> Bases;

CXXClassRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, RecordKind Kind,
AccessControl Access, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader, std::move(Access)),
RecordContext(Kind) {}
AccessControl Access, bool IsFromSystemHeader,
bool IsEmbeddedInVarDeclarator = false)
: RecordRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
Comment, Declaration, SubHeading, IsFromSystemHeader,
IsEmbeddedInVarDeclarator, std::move(Access)) {}

static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
Expand Down
16 changes: 14 additions & 2 deletions clang/include/clang/ExtractAPI/APIRecords.inc
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@ CONCRETE_RECORD(GlobalVariableTemplateSpecializationRecord,
CONCRETE_RECORD(GlobalVariableTemplatePartialSpecializationRecord,
GlobalVariableRecord,
RK_GlobalVariableTemplatePartialSpecialization)
ABSTRACT_RECORD(TagRecord, APIRecord)
CONCRETE_RECORD(EnumConstantRecord, APIRecord, RK_EnumConstant)
CONCRETE_RECORD(EnumRecord, APIRecord, RK_Enum)
CONCRETE_RECORD(EnumRecord, TagRecord, RK_Enum)
ABSTRACT_RECORD(RecordFieldRecord, APIRecord)
ABSTRACT_RECORD(RecordRecord, APIRecord)
ABSTRACT_RECORD(RecordRecord, TagRecord)
CONCRETE_RECORD(StructFieldRecord, RecordFieldRecord, RK_StructField)
CONCRETE_RECORD(StructRecord, APIRecord, RK_Struct)
CONCRETE_RECORD(UnionFieldRecord, RecordFieldRecord, RK_UnionField)
Expand Down Expand Up @@ -99,5 +100,16 @@ RECORD_CONTEXT(ClassTemplateSpecializationRecord,
RK_ClassTemplateSpecialization)
RECORD_CONTEXT(ClassTemplatePartialSpecializationRecord,
RK_ClassTemplatePartialSpecialization)
RECORD_CONTEXT(StructFieldRecord, RK_StructField)
RECORD_CONTEXT(UnionFieldRecord, RK_UnionField)
RECORD_CONTEXT(CXXFieldRecord, RK_CXXField)
RECORD_CONTEXT(StaticFieldRecord, RK_StaticField)
RECORD_CONTEXT(CXXFieldTemplateRecord, RK_CXXFieldTemplate)
RECORD_CONTEXT(GlobalVariableRecord, RK_GlobalVariable)
RECORD_CONTEXT(GlobalVariableTemplateRecord, RK_GlobalVariableTemplate)
RECORD_CONTEXT(GlobalVariableTemplateSpecializationRecord,
RK_GlobalVariableTemplateSpecialization)
RECORD_CONTEXT(GlobalVariableTemplatePartialSpecializationRecord,
RK_GlobalVariableTemplatePartialSpecialization)

#undef RECORD_CONTEXT
84 changes: 57 additions & 27 deletions clang/include/clang/ExtractAPI/DeclarationFragments.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Lex/MacroInfo.h"
#include <iterator>
#include <utility>
#include <vector>

namespace clang {
Expand Down Expand Up @@ -113,28 +115,26 @@ class DeclarationFragments {

ConstFragmentIterator cend() const { return Fragments.cend(); }

// Add a new Fragment at an arbitrary offset.
DeclarationFragments &insert(FragmentIterator It, StringRef Spelling,
FragmentKind Kind,
StringRef PreciseIdentifier = "",
const Decl *Declaration = nullptr) {
Fragments.insert(It,
Fragment(Spelling, Kind, PreciseIdentifier, Declaration));
return *this;
/// Prepend another DeclarationFragments to the beginning.
///
/// \returns a reference to the DeclarationFragments object itself after
/// appending to chain up consecutive operations.
DeclarationFragments &prepend(DeclarationFragments Other) {
return insert(begin(), std::move(Other));
}

DeclarationFragments &insert(FragmentIterator It,
DeclarationFragments &&Other) {
Fragments.insert(It, std::make_move_iterator(Other.Fragments.begin()),
std::make_move_iterator(Other.Fragments.end()));
Other.Fragments.clear();
return *this;
/// Append another DeclarationFragments to the end.
///
/// \returns a reference to the DeclarationFragments object itself after
/// appending to chain up consecutive operations.
DeclarationFragments &append(DeclarationFragments Other) {
return insert(end(), std::move(Other));
}

/// Append a new Fragment to the end of the Fragments.
///
/// \returns a reference to the DeclarationFragments object itself after
/// appending to chain up consecutive appends.
/// appending to chain up consecutive operations.
DeclarationFragments &append(StringRef Spelling, FragmentKind Kind,
StringRef PreciseIdentifier = "",
const Decl *Declaration = nullptr) {
Expand All @@ -149,18 +149,48 @@ class DeclarationFragments {
return *this;
}

/// Append another DeclarationFragments to the end.
///
/// Note: \p Other is moved from and cannot be used after a call to this
/// method.
/// Inserts another DeclarationFragments at \p It.
///
/// \returns a reference to the DeclarationFragments object itself after
/// appending to chain up consecutive appends.
DeclarationFragments &append(DeclarationFragments &&Other) {
Fragments.insert(Fragments.end(),
std::make_move_iterator(Other.Fragments.begin()),
std::make_move_iterator(Other.Fragments.end()));
Other.Fragments.clear();
/// appending to chain up consecutive operations.
DeclarationFragments &insert(FragmentIterator It,
DeclarationFragments Other) {
if (Other.Fragments.empty())
return *this;

if (Fragments.empty()) {
Fragments = std::move(Other.Fragments);
return *this;
}

const auto &OtherFrags = Other.Fragments;
auto ToInsertBegin = std::make_move_iterator(Other.begin());
auto ToInsertEnd = std::make_move_iterator(Other.end());

// If we aren't inserting at the end let's make sure that we merge their
// last fragment with It if both are text fragments.
if (It != end() && It->Kind == FragmentKind::Text &&
OtherFrags.back().Kind == FragmentKind::Text) {
auto &TheirBackSpelling = OtherFrags.back().Spelling;
It->Spelling.reserve(It->Spelling.size() + TheirBackSpelling.size());
It->Spelling.insert(It->Spelling.begin(), TheirBackSpelling.begin(),
TheirBackSpelling.end());
--ToInsertEnd;
}

// If we aren't inserting at the beginning we want to merge their first
// fragment with the fragment before It if both are text fragments.
if (It != begin() && std::prev(It)->Kind == FragmentKind::Text &&
OtherFrags.front().Kind == FragmentKind::Text) {
auto PrevIt = std::prev(It);
auto &TheirFrontSpelling = OtherFrags.front().Spelling;
PrevIt->Spelling.reserve(PrevIt->Spelling.size() +
TheirFrontSpelling.size());
PrevIt->Spelling.append(TheirFrontSpelling);
++ToInsertBegin;
}

Fragments.insert(It, ToInsertBegin, ToInsertEnd);
return *this;
}

Expand All @@ -177,13 +207,13 @@ class DeclarationFragments {
/// Append a text Fragment of a space character.
///
/// \returns a reference to the DeclarationFragments object itself after
/// appending to chain up consecutive appends.
/// appending to chain up consecutive operations.
DeclarationFragments &appendSpace();

/// Append a text Fragment of a semicolon character.
///
/// \returns a reference to the DeclarationFragments object itself after
/// appending to chain up consecutive appends.
/// appending to chain up consecutive operations.
DeclarationFragments &appendSemicolon();

/// Removes a trailing semicolon character if present.
Expand Down
76 changes: 53 additions & 23 deletions clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,29 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {

return API.createSymbolReference(Name, USR, getOwningModuleName(D));
}

bool isEmbeddedInVarDeclarator(const TagDecl &D) {
return D.getName().empty() && getTypedefName(&D).empty() &&
D.isEmbeddedInDeclarator();
}

void maybeMergeWithAnonymousTag(const DeclaratorDecl &D,
RecordContext *NewRecordContext) {
if (!NewRecordContext)
return;
auto *Tag = D.getType()->getAsTagDecl();
SmallString<128> TagUSR;
clang::index::generateUSRForDecl(Tag, TagUSR);
if (auto *Record = llvm::dyn_cast_if_present<TagRecord>(
API.findRecordForUSR(TagUSR))) {
if (Record->IsEmbeddedInVarDeclarator) {
NewRecordContext->stealRecordChain(*Record);
auto *NewRecord = cast<APIRecord>(NewRecordContext);
if (NewRecord->Comment.empty())
NewRecord->Comment = Record->Comment;
}
}
}
};

template <typename Derived>
Expand Down Expand Up @@ -273,12 +296,18 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarDecl(const VarDecl *Decl) {
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
SubHeading, Access, isInSystemHeader(Decl));
} else
} else {
// Add the global variable record to the API set.
API.createRecord<GlobalVariableRecord>(
auto *NewRecord = API.createRecord<GlobalVariableRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
SubHeading, isInSystemHeader(Decl));

// If this global variable has a non typedef'd anonymous tag type let's
// pretend the type's child records are under us in the hierarchy.
maybeMergeWithAnonymousTag(*Decl, NewRecord);
}

return true;
}

Expand Down Expand Up @@ -364,7 +393,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitEnumDecl(const EnumDecl *Decl) {
if (Name.empty()) {
llvm::raw_svector_ostream OS(QualifiedNameBuffer);
Decl->printQualifiedName(OS);
Name = QualifiedNameBuffer.str();
Name = QualifiedNameBuffer;
}

SmallString<128> USR;
Expand All @@ -385,7 +414,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitEnumDecl(const EnumDecl *Decl) {
auto *ER = API.createRecord<EnumRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
isInSystemHeader(Decl));
isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl));

// Now collect information about the enumerators in this enum.
getDerivedExtractAPIVisitor().recordEnumConstants(ER, Decl->enumerators());
Expand Down Expand Up @@ -510,16 +539,10 @@ bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) {
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
return true;

SmallString<128> QualifiedNameBuffer;
// Collect symbol information.
StringRef Name = Decl->getName();
if (Name.empty())
Name = getTypedefName(Decl);
if (Name.empty()) {
llvm::raw_svector_ostream OS(QualifiedNameBuffer);
Decl->printQualifiedName(OS);
Name = QualifiedNameBuffer.str();
}

SmallString<128> USR;
index::generateUSRForDecl(Decl, USR);
Expand All @@ -541,12 +564,12 @@ bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) {
API.createRecord<UnionRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
SubHeading, isInSystemHeader(Decl));
SubHeading, isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl));
else
API.createRecord<StructRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
SubHeading, isInSystemHeader(Decl));
SubHeading, isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl));

return true;
}
Expand All @@ -559,6 +582,9 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
return true;

StringRef Name = Decl->getName();
if (Name.empty())
Name = getTypedefName(Decl);

SmallString<128> USR;
index::generateUSRForDecl(Decl, USR);
PresumedLoc Loc =
Expand All @@ -585,8 +611,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
CXXClassRecord *Record;
if (Decl->getDescribedClassTemplate()) {
// Inject template fragments before class fragments.
Declaration.insert(
Declaration.begin(),
Declaration.prepend(
DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
Decl->getDescribedClassTemplate()));
Record = API.createRecord<ClassTemplateRecord>(
Expand All @@ -598,7 +623,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
Record = API.createRecord<CXXClassRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
SubHeading, Kind, Access, isInSystemHeader(Decl));
SubHeading, Kind, Access, isInSystemHeader(Decl),
isEmbeddedInVarDeclarator(*Decl));

Record->Bases = getBases(Decl);

Expand Down Expand Up @@ -1075,18 +1101,17 @@ bool ExtractAPIVisitorBase<Derived>::VisitTypedefNameDecl(
// If the underlying type was defined as part of the typedef modify it's
// fragments directly and pretend the typedef doesn't exist.
if (auto *TagDecl = Decl->getUnderlyingType()->getAsTagDecl()) {
if (TagDecl->getName() == Decl->getName() &&
TagDecl->isEmbeddedInDeclarator() && TagDecl->isCompleteDefinition()) {
if (TagDecl->isEmbeddedInDeclarator() && TagDecl->isCompleteDefinition() &&
Decl->getName() == TagDecl->getName()) {
SmallString<128> TagUSR;
index::generateUSRForDecl(TagDecl, TagUSR);
if (auto *Record = API.findRecordForUSR(TagUSR)) {
DeclarationFragments LeadingFragments;
LeadingFragments.append("typedef",
DeclarationFragments::FragmentKind::Keyword, "",
nullptr);
DeclarationFragments::FragmentKind::Keyword);
LeadingFragments.appendSpace();
Record->Declaration.removeTrailingSemicolon()
.insert(Record->Declaration.begin(), std::move(LeadingFragments))
.prepend(std::move(LeadingFragments))
.append(" { ... } ", DeclarationFragments::FragmentKind::Text)
.append(Name, DeclarationFragments::FragmentKind::Identifier)
.appendSemicolon();
Expand Down Expand Up @@ -1221,26 +1246,31 @@ bool ExtractAPIVisitorBase<Derived>::VisitFieldDecl(const FieldDecl *Decl) {
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);

RecordContext *NewRecord = nullptr;
if (isa<CXXRecordDecl>(Decl->getDeclContext())) {
AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);

API.createRecord<CXXFieldRecord>(
NewRecord = API.createRecord<CXXFieldRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
SubHeading, Access, isInSystemHeader(Decl));
} else if (auto *RD = dyn_cast<RecordDecl>(Decl->getDeclContext())) {
if (RD->isUnion())
API.createRecord<UnionFieldRecord>(
NewRecord = API.createRecord<UnionFieldRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
SubHeading, isInSystemHeader(Decl));
else
API.createRecord<StructFieldRecord>(
NewRecord = API.createRecord<StructFieldRecord>(
USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
SubHeading, isInSystemHeader(Decl));
}

// If this field has a non typedef'd anonymous tag type let's pretend the
// type's child records are under us in the hierarchy.
maybeMergeWithAnonymousTag(*Decl, NewRecord);

return true;
}

Expand Down
15 changes: 10 additions & 5 deletions clang/include/clang/InstallAPI/DylibVerifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ class DylibVerifier : llvm::MachO::RecordVisitor {
DylibVerifier() = default;

DylibVerifier(llvm::MachO::Records &&Dylib, ReexportedInterfaces &&Reexports,
DiagnosticsEngine *Diag, VerificationMode Mode, bool Zippered,
bool Demangle, StringRef DSYMPath)
: Dylib(std::move(Dylib)), Reexports(std::move(Reexports)), Mode(Mode),
Zippered(Zippered), Demangle(Demangle), DSYMPath(DSYMPath),
AliasMap Aliases, DiagnosticsEngine *Diag,
VerificationMode Mode, bool Zippered, bool Demangle,
StringRef DSYMPath)
: Dylib(std::move(Dylib)), Reexports(std::move(Reexports)),
Aliases(std::move(Aliases)), Mode(Mode), Zippered(Zippered),
Demangle(Demangle), DSYMPath(DSYMPath),
Exports(std::make_unique<SymbolSet>()), Ctx(VerifierContext{Diag}) {}

Result verify(GlobalRecord *R, const FrontendAttrs *FA);
Expand All @@ -104,7 +106,7 @@ class DylibVerifier : llvm::MachO::RecordVisitor {
void setTarget(const Target &T);

/// Release ownership over exports.
std::unique_ptr<SymbolSet> getExports() { return std::move(Exports); }
std::unique_ptr<SymbolSet> takeExports();

/// Get result of verification.
Result getState() const { return Ctx.FrontendState; }
Expand Down Expand Up @@ -189,6 +191,9 @@ class DylibVerifier : llvm::MachO::RecordVisitor {
// Reexported interfaces apart of the library.
ReexportedInterfaces Reexports;

// Symbol aliases.
AliasMap Aliases;

// Controls what class of violations to report.
VerificationMode Mode = VerificationMode::Invalid;

Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/InstallAPI/MachO.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "llvm/TextAPI/TextAPIWriter.h"
#include "llvm/TextAPI/Utils.h"

using AliasMap = llvm::MachO::AliasMap;
using Architecture = llvm::MachO::Architecture;
using ArchitectureSet = llvm::MachO::ArchitectureSet;
using SymbolFlags = llvm::MachO::SymbolFlags;
Expand Down
14 changes: 10 additions & 4 deletions clang/include/clang/Lex/HeaderSearch.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ class TargetInfo;
/// The preprocessor keeps track of this information for each
/// file that is \#included.
struct HeaderFileInfo {
// TODO: Whether the file was included is not a property of the file itself.
// It's a preprocessor state, move it there.
/// True if this file has been included (or imported) **locally**.
LLVM_PREFERRED_TYPE(bool)
unsigned IsLocallyIncluded : 1;

// TODO: Whether the file was imported is not a property of the file itself.
// It's a preprocessor state, move it there.
/// True if this is a \#import'd file.
Expand Down Expand Up @@ -135,10 +141,10 @@ struct HeaderFileInfo {
StringRef Framework;

HeaderFileInfo()
: isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
External(false), isModuleHeader(false), isTextualModuleHeader(false),
isCompilingModuleHeader(false), Resolved(false),
IndexHeaderMapHeader(false), IsValid(false) {}
: IsLocallyIncluded(false), isImport(false), isPragmaOnce(false),
DirInfo(SrcMgr::C_User), External(false), isModuleHeader(false),
isTextualModuleHeader(false), isCompilingModuleHeader(false),
Resolved(false), IndexHeaderMapHeader(false), IsValid(false) {}

/// Retrieve the controlling macro for this header file, if
/// any.
Expand Down
7 changes: 6 additions & 1 deletion clang/include/clang/Lex/HeaderSearchOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,10 @@ class HeaderSearchOptions {
LLVM_PREFERRED_TYPE(bool)
unsigned ModulesSkipPragmaDiagnosticMappings : 1;

/// Whether to prune non-affecting module map files from PCM files.
LLVM_PREFERRED_TYPE(bool)
unsigned ModulesPruneNonAffectingModuleMaps : 1;

LLVM_PREFERRED_TYPE(bool)
unsigned ModulesHashContent : 1;

Expand Down Expand Up @@ -280,7 +284,8 @@ class HeaderSearchOptions {
ModulesValidateDiagnosticOptions(true),
ModulesSkipDiagnosticOptions(false),
ModulesSkipHeaderSearchPaths(false),
ModulesSkipPragmaDiagnosticMappings(false), ModulesHashContent(false),
ModulesSkipPragmaDiagnosticMappings(false),
ModulesPruneNonAffectingModuleMaps(true), ModulesHashContent(false),
ModulesStrictContextHash(false), ModulesIncludeVFSUsage(false) {}

/// AddPath - Add the \p Path path to the specified \p Group list.
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
65 changes: 51 additions & 14 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 @@ -3640,13 +3664,26 @@ class Parser : public CodeCompletionHandler {
/// Parses the clause-list for an OpenACC directive.
SmallVector<OpenACCClause *>
ParseOpenACCClauseList(OpenACCDirectiveKind DirKind);
bool ParseOpenACCWaitArgument();
bool ParseOpenACCWaitArgument(SourceLocation Loc, bool IsDirective);
/// 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();
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 All @@ -3657,9 +3694,9 @@ class Parser : public CodeCompletionHandler {
/// Parses a comma delimited list of 'size-expr's.
bool ParseOpenACCSizeExprList();
/// Parses a 'gang-arg-list', used for the 'gang' clause.
bool ParseOpenACCGangArgList();
bool ParseOpenACCGangArgList(SourceLocation GangLoc);
/// Parses a 'gang-arg', used for the 'gang' clause.
bool ParseOpenACCGangArg();
bool ParseOpenACCGangArg(SourceLocation GangLoc);
/// Parses a 'condition' expr, ensuring it results in a
ExprResult ParseOpenACCConditionExpr();

Expand Down
43 changes: 23 additions & 20 deletions clang/include/clang/Sema/Lookup.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,28 +153,30 @@ class LookupResult {

using iterator = UnresolvedSetImpl::iterator;

LookupResult(Sema &SemaRef, const DeclarationNameInfo &NameInfo,
Sema::LookupNameKind LookupKind,
Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
LookupResult(
Sema &SemaRef, const DeclarationNameInfo &NameInfo,
Sema::LookupNameKind LookupKind,
RedeclarationKind Redecl = RedeclarationKind::NotForRedeclaration)
: SemaPtr(&SemaRef), NameInfo(NameInfo), LookupKind(LookupKind),
Redecl(Redecl != Sema::NotForRedeclaration),
ExternalRedecl(Redecl == Sema::ForExternalRedeclaration),
DiagnoseAccess(Redecl == Sema::NotForRedeclaration),
DiagnoseAmbiguous(Redecl == Sema::NotForRedeclaration) {
Redecl(Redecl != RedeclarationKind::NotForRedeclaration),
ExternalRedecl(Redecl == RedeclarationKind::ForExternalRedeclaration),
DiagnoseAccess(Redecl == RedeclarationKind::NotForRedeclaration),
DiagnoseAmbiguous(Redecl == RedeclarationKind::NotForRedeclaration) {
configure();
}

// TODO: consider whether this constructor should be restricted to take
// as input a const IdentifierInfo* (instead of Name),
// forcing other cases towards the constructor taking a DNInfo.
LookupResult(Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc,
Sema::LookupNameKind LookupKind,
Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
LookupResult(
Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc,
Sema::LookupNameKind LookupKind,
RedeclarationKind Redecl = RedeclarationKind::NotForRedeclaration)
: SemaPtr(&SemaRef), NameInfo(Name, NameLoc), LookupKind(LookupKind),
Redecl(Redecl != Sema::NotForRedeclaration),
ExternalRedecl(Redecl == Sema::ForExternalRedeclaration),
DiagnoseAccess(Redecl == Sema::NotForRedeclaration),
DiagnoseAmbiguous(Redecl == Sema::NotForRedeclaration) {
Redecl(Redecl != RedeclarationKind::NotForRedeclaration),
ExternalRedecl(Redecl == RedeclarationKind::ForExternalRedeclaration),
DiagnoseAccess(Redecl == RedeclarationKind::NotForRedeclaration),
DiagnoseAmbiguous(Redecl == RedeclarationKind::NotForRedeclaration) {
configure();
}

Expand Down Expand Up @@ -285,9 +287,10 @@ class LookupResult {
return ExternalRedecl;
}

Sema::RedeclarationKind redeclarationKind() const {
return ExternalRedecl ? Sema::ForExternalRedeclaration :
Redecl ? Sema::ForVisibleRedeclaration : Sema::NotForRedeclaration;
RedeclarationKind redeclarationKind() const {
return ExternalRedecl ? RedeclarationKind::ForExternalRedeclaration
: Redecl ? RedeclarationKind::ForVisibleRedeclaration
: RedeclarationKind::NotForRedeclaration;
}

/// Specify whether hidden declarations are visible, e.g.,
Expand Down Expand Up @@ -615,9 +618,9 @@ class LookupResult {
}

/// Change this lookup's redeclaration kind.
void setRedeclarationKind(Sema::RedeclarationKind RK) {
Redecl = (RK != Sema::NotForRedeclaration);
ExternalRedecl = (RK == Sema::ForExternalRedeclaration);
void setRedeclarationKind(RedeclarationKind RK) {
Redecl = (RK != RedeclarationKind::NotForRedeclaration);
ExternalRedecl = (RK == RedeclarationKind::ForExternalRedeclaration);
configure();
}

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
7 changes: 1 addition & 6 deletions clang/include/clang/Sema/ParsedAttr.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ struct PropertyData {
: GetterId(getterId), SetterId(setterId) {}
};

} // namespace
} // namespace detail

/// Wraps an identifier and optional source location for the identifier.
struct IdentifierLoc {
Expand Down Expand Up @@ -743,11 +743,6 @@ class AttributePool {
IdentifierInfo *scopeName, SourceLocation scopeLoc,
ArgsUnion *args, unsigned numArgs, ParsedAttr::Form form,
SourceLocation ellipsisLoc = SourceLocation()) {
size_t temp =
ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
detail::TypeTagForDatatypeData, ParsedType,
detail::PropertyData>(numArgs, 0, 0, 0, 0);
(void)temp;
void *memory = allocate(
ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
detail::TypeTagForDatatypeData, ParsedType,
Expand Down
31 changes: 31 additions & 0 deletions clang/include/clang/Sema/Redeclaration.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//===- Redeclaration.h - Redeclarations--------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines RedeclarationKind enum.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SEMA_REDECLARATION_H
#define LLVM_CLANG_SEMA_REDECLARATION_H

/// Specifies whether (or how) name lookup is being performed for a
/// redeclaration (vs. a reference).
enum class RedeclarationKind {
/// The lookup is a reference to this name that is not for the
/// purpose of redeclaring the name.
NotForRedeclaration = 0,
/// The lookup results will be used for redeclaration of a name,
/// if an entity by that name already exists and is visible.
ForVisibleRedeclaration,
/// The lookup results will be used for redeclaration of a name
/// with external linkage; non-visible lookup results with external linkage
/// may also be found.
ForExternalRedeclaration
};

#endif // LLVM_CLANG_SEMA_REDECLARATION_H
6 changes: 6 additions & 0 deletions clang/include/clang/Sema/Scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ class Scope {
/// This is the scope of an OpenACC Compute Construct, which restricts
/// jumping into/out of it.
OpenACCComputeConstructScope = 0x10000000,

/// This is a scope of type alias declaration.
TypeAliasScope = 0x20000000,
};

private:
Expand Down Expand Up @@ -580,6 +583,9 @@ class Scope {
/// if/switch/while/for statement.
bool isControlScope() const { return getFlags() & Scope::ControlScope; }

/// Determine whether this scope is a type alias scope.
bool isTypeAliasScope() const { return getFlags() & Scope::TypeAliasScope; }

/// Returns if rhs has a higher scope depth than this.
///
/// The caller is responsible for calling this only if one of the two scopes
Expand Down
137 changes: 68 additions & 69 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
#include "clang/Sema/IdentifierResolver.h"
#include "clang/Sema/ObjCMethodList.h"
#include "clang/Sema/Ownership.h"
#include "clang/Sema/Redeclaration.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaBase.h"
#include "clang/Sema/SemaConcept.h"
Expand Down Expand Up @@ -352,6 +353,14 @@ class PreferredTypeBuilder {
llvm::function_ref<QualType()> ComputeType;
};

struct SkipBodyInfo {
SkipBodyInfo() = default;
bool ShouldSkip = false;
bool CheckSameAsPrevious = false;
NamedDecl *Previous = nullptr;
NamedDecl *New = nullptr;
};

/// Describes the result of template argument deduction.
///
/// The TemplateDeductionResult enumeration describes the result of
Expand Down Expand Up @@ -429,6 +438,20 @@ enum class CXXSpecialMemberKind {
Invalid
};

/// The kind of conversion being performed.
enum class CheckedConversionKind {
/// An implicit conversion.
Implicit,
/// A C-style cast.
CStyleCast,
/// A functional-style cast.
FunctionalCast,
/// A cast other than a C-style cast.
OtherCast,
/// A conversion for an operand of a builtin overloaded operator.
ForBuiltinOverloadedOp
};

/// Sema - This implements semantic analysis and AST building for C.
/// \nosubgrouping
class Sema final : public SemaBase {
Expand Down Expand Up @@ -692,28 +715,27 @@ class Sema final : public SemaBase {
void checkTypeSupport(QualType Ty, SourceLocation Loc,
ValueDecl *D = nullptr);

/// The kind of conversion being performed.
enum CheckedConversionKind {
/// An implicit conversion.
CCK_ImplicitConversion,
/// A C-style cast.
CCK_CStyleCast,
/// A functional-style cast.
CCK_FunctionalCast,
/// A cast other than a C-style cast.
CCK_OtherCast,
/// A conversion for an operand of a builtin overloaded operator.
CCK_ForBuiltinOverloadedOp
};
// /// The kind of conversion being performed.
// enum CheckedConversionKind {
// /// An implicit conversion.
// CCK_ImplicitConversion,
// /// A C-style cast.
// CCK_CStyleCast,
// /// A functional-style cast.
// CCK_FunctionalCast,
// /// A cast other than a C-style cast.
// CCK_OtherCast,
// /// A conversion for an operand of a builtin overloaded operator.
// CCK_ForBuiltinOverloadedOp
// };

/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit
/// cast. If there is already an implicit cast, merge into the existing one.
/// If isLvalue, the result of the cast is an lvalue.
ExprResult
ImpCastExprToType(Expr *E, QualType Type, CastKind CK,
ExprValueKind VK = VK_PRValue,
const CXXCastPath *BasePath = nullptr,
CheckedConversionKind CCK = CCK_ImplicitConversion);
ExprResult ImpCastExprToType(
Expr *E, QualType Type, CastKind CK, ExprValueKind VK = VK_PRValue,
const CXXCastPath *BasePath = nullptr,
CheckedConversionKind CCK = CheckedConversionKind::Implicit);

/// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding
/// to the conversion from scalar type ScalarTy to the Boolean type.
Expand Down Expand Up @@ -1773,8 +1795,9 @@ class Sema final : public SemaBase {

public:
static bool isCast(CheckedConversionKind CCK) {
return CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast ||
CCK == CCK_OtherCast;
return CCK == CheckedConversionKind::CStyleCast ||
CCK == CheckedConversionKind::FunctionalCast ||
CCK == CheckedConversionKind::OtherCast;
}

/// ActOnCXXNamedCast - Parse
Expand Down Expand Up @@ -2627,14 +2650,6 @@ class Sema final : public SemaBase {
return Entity->getOwningModule();
}

struct SkipBodyInfo {
SkipBodyInfo() = default;
bool ShouldSkip = false;
bool CheckSameAsPrevious = false;
NamedDecl *Previous = nullptr;
NamedDecl *New = nullptr;
};

DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr);

ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
Expand Down Expand Up @@ -3069,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 Expand Up @@ -5430,7 +5446,7 @@ class Sema final : public SemaBase {
ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind);
ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val);

bool CheckLoopHintExpr(Expr *E, SourceLocation Loc);
bool CheckLoopHintExpr(Expr *E, SourceLocation Loc, bool AllowZero);

ExprResult ActOnNumericConstant(const Token &Tok, Scope *UDLScope = nullptr);
ExprResult ActOnCharacterConstant(const Token &Tok,
Expand Down Expand Up @@ -6512,7 +6528,10 @@ class Sema final : public SemaBase {
SourceLocation RParenLoc);

//// ActOnCXXThis - Parse 'this' pointer.
ExprResult ActOnCXXThis(SourceLocation loc);
ExprResult ActOnCXXThis(SourceLocation Loc);

/// Check whether the type of 'this' is valid in the current context.
bool CheckCXXThisType(SourceLocation Loc, QualType Type);

/// Build a CXXThisExpr and mark it referenced in the current context.
Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit);
Expand Down Expand Up @@ -6739,11 +6758,10 @@ class Sema final : public SemaBase {

bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType);

ExprResult
PerformImplicitConversion(Expr *From, QualType ToType,
const ImplicitConversionSequence &ICS,
AssignmentAction Action,
CheckedConversionKind CCK = CCK_ImplicitConversion);
ExprResult PerformImplicitConversion(
Expr *From, QualType ToType, const ImplicitConversionSequence &ICS,
AssignmentAction Action,
CheckedConversionKind CCK = CheckedConversionKind::Implicit);
ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
const StandardConversionSequence &SCS,
AssignmentAction Action,
Expand Down Expand Up @@ -6935,10 +6953,14 @@ class Sema final : public SemaBase {
///@{

public:
/// Check whether an expression might be an implicit class member access.
bool isPotentialImplicitMemberAccess(const CXXScopeSpec &SS, LookupResult &R,
bool IsAddressOfOperand);

ExprResult BuildPossibleImplicitMemberExpr(
const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
UnresolvedLookupExpr *AsULE = nullptr);
const TemplateArgumentListInfo *TemplateArgs, const Scope *S);

ExprResult
BuildImplicitMemberExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
LookupResult &R,
Expand Down Expand Up @@ -7064,7 +7086,7 @@ class Sema final : public SemaBase {

ExprResult PerformQualificationConversion(
Expr *E, QualType Ty, ExprValueKind VK = VK_PRValue,
CheckedConversionKind CCK = CCK_ImplicitConversion);
CheckedConversionKind CCK = CheckedConversionKind::Implicit);

bool CanPerformCopyInitialization(const InitializedEntity &Entity,
ExprResult Init);
Expand Down Expand Up @@ -7430,40 +7452,17 @@ class Sema final : public SemaBase {
typedef std::function<ExprResult(Sema &, TypoExpr *, TypoCorrection)>
TypoRecoveryCallback;

/// Specifies whether (or how) name lookup is being performed for a
/// redeclaration (vs. a reference).
enum RedeclarationKind {
/// The lookup is a reference to this name that is not for the
/// purpose of redeclaring the name.
NotForRedeclaration = 0,
/// The lookup results will be used for redeclaration of a name,
/// if an entity by that name already exists and is visible.
ForVisibleRedeclaration,
/// The lookup results will be used for redeclaration of a name
/// with external linkage; non-visible lookup results with external linkage
/// may also be found.
ForExternalRedeclaration
};

RedeclarationKind forRedeclarationInCurContext() const {
// A declaration with an owning module for linkage can never link against
// anything that is not visible. We don't need to check linkage here; if
// the context has internal linkage, redeclaration lookup won't find things
// from other TUs, and we can't safely compute linkage yet in general.
if (cast<Decl>(CurContext)
->getOwningModuleForLinkage(/*IgnoreLinkage*/ true))
return ForVisibleRedeclaration;
return ForExternalRedeclaration;
}
RedeclarationKind forRedeclarationInCurContext() const;

/// Look up a name, looking for a single declaration. Return
/// null if the results were absent, ambiguous, or overloaded.
///
/// It is preferable to use the elaborated form and explicitly handle
/// ambiguity and overloaded.
NamedDecl *LookupSingleName(Scope *S, DeclarationName Name,
SourceLocation Loc, LookupNameKind NameKind,
RedeclarationKind Redecl = NotForRedeclaration);
NamedDecl *LookupSingleName(
Scope *S, DeclarationName Name, SourceLocation Loc,
LookupNameKind NameKind,
RedeclarationKind Redecl = RedeclarationKind::NotForRedeclaration);
bool LookupBuiltin(LookupResult &R);
void LookupNecessaryTypesForBuiltin(Scope *S, unsigned ID);
bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation = false,
Expand All @@ -7475,9 +7474,9 @@ class Sema final : public SemaBase {
bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
bool AllowBuiltinCreation = false,
bool EnteringContext = false);
ObjCProtocolDecl *
LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc,
RedeclarationKind Redecl = NotForRedeclaration);
ObjCProtocolDecl *LookupProtocol(
IdentifierInfo *II, SourceLocation IdLoc,
RedeclarationKind Redecl = RedeclarationKind::NotForRedeclaration);
bool LookupInSuper(LookupResult &R, CXXRecordDecl *Class);

void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
Expand Down
49 changes: 47 additions & 2 deletions clang/include/clang/Sema/SemaOpenACC.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,13 @@ class SemaOpenACC : public SemaBase {
Expr *ConditionExpr;
};

std::variant<std::monostate, DefaultDetails, ConditionDetails> Details =
std::monostate{};
struct IntExprDetails {
SmallVector<Expr *> IntExprs;
};

std::variant<std::monostate, DefaultDetails, ConditionDetails,
IntExprDetails>
Details = std::monostate{};

public:
OpenACCParsedClause(OpenACCDirectiveKind DirKind,
Expand Down Expand Up @@ -87,6 +92,26 @@ class SemaOpenACC : public SemaBase {
return std::get<ConditionDetails>(Details).ConditionExpr;
}

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

ArrayRef<Expr *> getIntExprs() const {
return const_cast<OpenACCParsedClause *>(this)->getIntExprs();
}

void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; }
void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); }

Expand All @@ -109,6 +134,21 @@ class SemaOpenACC : public SemaBase {

Details = ConditionDetails{ConditionExpr};
}

void setIntExprDetails(ArrayRef<Expr *> IntExprs) {
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 Expand Up @@ -148,6 +188,11 @@ class SemaOpenACC : public SemaBase {
/// Called after the directive has been completely parsed, including the
/// declaration group or associated statement.
DeclGroupRef ActOnEndDeclDirective();

/// Called when encountering an 'int-expr' for OpenACC, and manages
/// conversions and diagnostics to 'int'.
ExprResult ActOnIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
SourceLocation Loc, Expr *IntExpr);
};

} // namespace clang
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
Loading