[clang] [lldb] [BoundsSafety] Support counted by on function params (PR #213305)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 31 09:32:46 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clangir
Author: Mohammed Ashraf (Holo-xy)
<details>
<summary>Changes</summary>
---
Patch is 84.61 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/213305.diff
31 Files Affected:
- (modified) clang/include/clang/AST/ASTContext.h (+6)
- (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+6)
- (modified) clang/include/clang/AST/TypeBase.h (+35)
- (modified) clang/include/clang/AST/TypeLoc.h (+31)
- (modified) clang/include/clang/AST/TypeProperties.td (+6)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+6)
- (modified) clang/include/clang/Basic/TypeNodes.td (+1)
- (modified) clang/include/clang/Parse/Parser.h (+17-1)
- (modified) clang/include/clang/Sema/DeclSpec.h (+5-1)
- (modified) clang/include/clang/Sema/Sema.h (+65)
- (modified) clang/lib/AST/ASTContext.cpp (+18)
- (modified) clang/lib/AST/ASTImporter.cpp (+5)
- (modified) clang/lib/AST/ASTStructuralEquivalence.cpp (+7)
- (modified) clang/lib/AST/ItaniumMangle.cpp (+1)
- (modified) clang/lib/AST/TypePrinter.cpp (+15)
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.cpp (+1)
- (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+1)
- (modified) clang/lib/CodeGen/CodeGenFunction.cpp (+1)
- (modified) clang/lib/Parse/ParseDecl.cpp (+75-7)
- (modified) clang/lib/Parse/Parser.cpp (+5)
- (modified) clang/lib/Sema/SemaBoundsSafety.cpp (+462-67)
- (modified) clang/lib/Sema/SemaExpr.cpp (+1)
- (modified) clang/lib/Sema/SemaType.cpp (+39)
- (modified) clang/lib/Sema/TreeTransform.h (+20)
- (modified) clang/lib/Serialization/ASTReader.cpp (+5)
- (modified) clang/lib/Serialization/ASTWriter.cpp (+8)
- (added) clang/test/AST/attr-counted-by-function-params.c (+40)
- (added) clang/test/Sema/attr-counted-by-function-params.c (+329)
- (modified) clang/test/Sema/warn-thread-safety-analysis.c (+5)
- (modified) clang/tools/libclang/CIndex.cpp (+4)
- (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp (+9)
``````````diff
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index a4ed852d36442..2095bc1a1df67 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1630,6 +1630,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
bool OrNull,
ArrayRef<TypeCoupledDeclRefInfo> DependentDecls) const;
+ /// Return a placeholder type for a late-parsed type attribute.
+ /// This type wraps another type and holds the LateParsedAttribute
+ /// that will be parsed later.
+ QualType getLateParsedAttrType(QualType Wrapped,
+ LateParsedTypeAttribute *LateParsedAttr) const;
+
/// Return the uniqued reference to a type adjusted from the original
/// type to a new type.
QualType getAdjustedType(QualType Orig, QualType New) const;
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 529d657fc01f5..5a72ef0f17785 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1164,6 +1164,9 @@ DEF_TRAVERSE_TYPE(CountAttributedType, {
TRY_TO(TraverseType(T->desugar()));
})
+DEF_TRAVERSE_TYPE(LateParsedAttrType,
+ { TRY_TO(TraverseType(T->getWrappedType())); })
+
DEF_TRAVERSE_TYPE(BTFTagAttributedType,
{ TRY_TO(TraverseType(T->getWrappedType())); })
@@ -1522,6 +1525,9 @@ DEF_TRAVERSE_TYPELOC(AttributedType,
DEF_TRAVERSE_TYPELOC(CountAttributedType,
{ TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); })
+DEF_TRAVERSE_TYPELOC(LateParsedAttrType,
+ { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); })
+
DEF_TRAVERSE_TYPELOC(BTFTagAttributedType,
{ TRY_TO(TraverseTypeLoc(TL.getWrappedLoc())); })
diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h
index e3844d0cefa78..663ccb5a8a446 100644
--- a/clang/include/clang/AST/TypeBase.h
+++ b/clang/include/clang/AST/TypeBase.h
@@ -70,6 +70,7 @@ class TagDecl;
class TemplateParameterList;
class Type;
class Attr;
+struct LateParsedTypeAttribute;
enum {
TypeAlignmentInBits = 4,
@@ -3545,6 +3546,40 @@ class CountAttributedType final
StringRef getAttributeName(bool WithMacroPrefix) const;
};
+/// Represents a placeholder type for late-parsed type attributes.
+/// This type wraps another type and holds an opaque pointer to a
+/// LateParsedTypeAttribute that will be parsed later (e.g., in ActOnFields).
+/// Once parsed, this type is replaced with the appropriate attributed type
+/// (e.g., CountAttributedType for `__counted_by`).
+///
+/// Its canonical type is that of the wrapped type, so a consumer walking the
+/// AST during late parsing must treat this as "attribute unresolved", not "no
+/// attribute here".
+class LateParsedAttrType : public Type {
+ friend class ASTContext; // ASTContext creates these.
+
+ QualType WrappedTy;
+ LateParsedTypeAttribute *LateParsedTypeAttr;
+
+ LateParsedAttrType(QualType Wrapped, QualType Canon,
+ LateParsedTypeAttribute *Attr)
+ : Type(LateParsedAttr, Canon, Wrapped->getDependence()),
+ WrappedTy(Wrapped), LateParsedTypeAttr(Attr) {}
+
+public:
+ QualType getWrappedType() const { return WrappedTy; }
+ LateParsedTypeAttribute *getLateParsedAttribute() const {
+ return LateParsedTypeAttr;
+ }
+
+ bool isSugared() const { return true; }
+ QualType desugar() const { return WrappedTy; }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == LateParsedAttr;
+ }
+};
+
/// Represents a type which was implicitly adjusted by the semantic
/// engine for arbitrary reasons. For example, array and function types can
/// decay, and function types can have their calling conventions adjusted.
diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index 24df18dbaace4..2648806ac687a 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -1358,6 +1358,37 @@ class CountAttributedTypeLoc final
SourceRange getLocalSourceRange() const;
};
+struct LateParsedAttrLocInfo {
+ SourceLocation AttrNameLoc;
+};
+
+class LateParsedAttrTypeLoc
+ : public ConcreteTypeLoc<UnqualTypeLoc, LateParsedAttrTypeLoc,
+ LateParsedAttrType, LateParsedAttrLocInfo> {
+public:
+ TypeLoc getInnerLoc() const { return getInnerTypeLoc(); }
+
+ SourceLocation getAttrNameLoc() const { return getLocalData()->AttrNameLoc; }
+
+ void setAttrNameLoc(SourceLocation Loc) { getLocalData()->AttrNameLoc = Loc; }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getAttrNameLoc(), getAttrNameLoc());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setAttrNameLoc(Loc);
+ }
+
+ unsigned getLocalDataSize() const { return sizeof(LateParsedAttrLocInfo); }
+
+ QualType getInnerType() const { return getTypePtr()->getWrappedType(); }
+
+ LateParsedTypeAttribute *getLateParsedAttribute() const {
+ return getTypePtr()->getLateParsedAttribute();
+ }
+};
+
struct MacroQualifiedLocInfo {
SourceLocation ExpansionLoc;
};
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index f16c10da430f9..c5402a1925d99 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -44,6 +44,12 @@ let Class = CountAttributedType in {
def : Creator<[{ return ctx.getCountAttributedType(WrappedTy, CountExpr, CountInBytes, OrNull, CoupledDecls); }]>;
}
+let Class = LateParsedAttrType in {
+ // Note: LateParsedAttrType is a transient placeholder type that should
+ // normally be replaced before serialization. So this won't be serialized.
+ def : Creator<[{ (void)ctx; llvm_unreachable("unreachable for serialization"); }]>;
+}
+
let Class = AdjustedType in {
def : Property<"originalType", QualType> {
let Read = [{ node->getOriginalType() }];
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 8097800e6744a..8039ac7b8cc18 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7131,6 +7131,12 @@ def err_counted_by_attr_refer_to_itself : Error<
"'counted_by' cannot refer to the flexible array member %0">;
def err_count_attr_must_be_in_structure : Error<
"field %0 in '%select{counted_by|sized_by|counted_by_or_null|sized_by_or_null}1' not inside structure">;
+def err_count_attr_not_param_of_same_function : Error<
+ "'%select{counted_by|sized_by|counted_by_or_null|sized_by_or_null}1' argument %0 is not a parameter of the same function as the annotated pointer">;
+def err_count_attr_on_nested_type : Error<
+ "'%select{counted_by|sized_by|counted_by_or_null|sized_by_or_null}0' is not supported on "
+ "%select{a nested pointer|an array element}1; it must apply to the "
+ "annotated declaration's own type">;
def err_count_attr_argument_not_integer : Error<
"'%select{counted_by|sized_by|counted_by_or_null|sized_by_or_null}0' requires a non-boolean integer type argument">;
def err_count_attr_only_support_simple_decl_reference : Error<
diff --git a/clang/include/clang/Basic/TypeNodes.td b/clang/include/clang/Basic/TypeNodes.td
index a9965a4a89aa1..700a73f669690 100644
--- a/clang/include/clang/Basic/TypeNodes.td
+++ b/clang/include/clang/Basic/TypeNodes.td
@@ -105,6 +105,7 @@ def ObjCInterfaceType : TypeNode<ObjCObjectType>, AlwaysCanonical;
def ObjCObjectPointerType : TypeNode<Type>;
def BoundsAttributedType : TypeNode<Type, 1>;
def CountAttributedType : TypeNode<BoundsAttributedType>, NeverCanonical;
+def LateParsedAttrType : TypeNode<Type>, NeverCanonical;
def PipeType : TypeNode<Type>;
def AtomicType : TypeNode<Type>;
def BitIntType : TypeNode<Type>;
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 5e7af97feeb6c..7c72b1c307ea0 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2670,7 +2670,8 @@ class Parser : public CodeCompletionHandler {
void ParseTypeQualifierListOpt(
DeclSpec &DS, unsigned AttrReqs = AR_AllAttributesParsed,
bool AtomicOrPtrauthAllowed = true, bool IdentifierRequired = false,
- llvm::function_ref<void()> CodeCompletionHandler = {});
+ llvm::function_ref<void()> CodeCompletionHandler = {},
+ LateParsedAttrList *LateAttrs = nullptr);
/// ParseDirectDeclarator
/// \verbatim
@@ -8090,6 +8091,21 @@ class Parser : public CodeCompletionHandler {
static void LateTemplateParserCallback(void *P, LateParsedTemplate &LPT);
+ /// Parse the cached tokens of \p LTA into \p OutAttrs. Takes ownership of
+ /// \p LTA.
+ static void ParseLateParsedTypeAttributeCallback(LateParsedTypeAttribute *LTA,
+ ParsedAttributes *OutAttrs);
+
+ /// Validate \p LA against \p type and, if it applies, wrap \p type in a
+ /// \c LateParsedAttrType placeholder. Returns false if the attribute is
+ /// invalid for \p type.
+ static bool ProcessLateParsedTypeAttrCallback(LateParsedAttribute *LA,
+ QualType &type);
+
+ /// Return the source location of the attribute name stored in \p LTA.
+ static SourceLocation
+ GetLateParsedAttributeLocationCallback(const LateParsedTypeAttribute *LTA);
+
/// We've parsed something that could plausibly be intended to be a template
/// name (\p LHS) followed by a '<' token, and the following code can't
/// possibly be an expression. Determine if this is likely to be a template-id
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index 6e7f9cd6e3d38..dac4c9f498f63 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -1303,6 +1303,7 @@ struct DeclaratorChunk {
}
ParsedAttributesView AttrList;
+ LateParsedAttrList LateAttrList;
struct PointerTypeInfo {
/// The type qualifiers: const/volatile/restrict/unaligned/atomic.
@@ -2403,13 +2404,16 @@ class Declarator {
/// This function takes attrs by R-Value reference because it takes ownership
/// of those attributes from the parameter.
void AddTypeInfo(const DeclaratorChunk &TI, ParsedAttributes &&attrs,
- SourceLocation EndLoc) {
+ SourceLocation EndLoc,
+ const LateParsedAttrList &LateAttrs = {}) {
DeclTypeInfo.push_back(TI);
DeclTypeInfo.back().getAttrs().prepend(attrs.begin(), attrs.end());
getAttributePool().takeAllFrom(attrs.getPool());
if (!EndLoc.isInvalid())
SetRangeEnd(EndLoc);
+
+ DeclTypeInfo.back().LateAttrList.append(LateAttrs);
}
/// AddTypeInfo - Add a chunk to this declarator. Also extend the range to
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b8d760e7e0975..ca0ccb9cac29d 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -143,6 +143,8 @@ class InitializationKind;
class InitializationSequence;
class InitializedEntity;
enum class LangAS : unsigned int;
+struct LateParsedAttribute;
+struct LateParsedTypeAttribute;
class LocalInstantiationScope;
class LookupResult;
class MangleNumberingContext;
@@ -1356,6 +1358,69 @@ class Sema final : public SemaBase {
OpaqueParser = P;
}
+ /// Parse the cached tokens of \p LTA into \p OutAttrs. Takes ownership of
+ /// \p LTA.
+ typedef void ParseLateParsedTypeAttributeCB(LateParsedTypeAttribute *LTA,
+ ParsedAttributes *OutAttrs);
+
+ /// Validate \p LA against \p type and, if it applies, wrap \p type in a
+ /// \c LateParsedAttrType placeholder. Returns false if the attribute is
+ /// invalid for \p type.
+ typedef bool ProcessLateParsedTypeAttrCB(LateParsedAttribute *LA,
+ QualType &type);
+ ProcessLateParsedTypeAttrCB *ProcessLateParsedTypeAttrCallback = nullptr;
+
+ /// Return the source location of the attribute name stored in \p LTA.
+ typedef SourceLocation
+ GetLateParsedAttributeLocationCB(const LateParsedTypeAttribute *LTA);
+ GetLateParsedAttributeLocationCB *GetLateParsedAttributeLocationCallback =
+ nullptr;
+
+ /// Wrap \p type in a LateParsedAttrType placeholder for \p LTA, after
+ /// checking that the attribute is applicable to \p type at all. Returns
+ /// false if the attribute should be dropped.
+ bool ActOnLateParsedTypeAttr(ParsedAttr::Kind AttrKind,
+ SourceLocation AttrNameLoc, QualType &type,
+ LateParsedTypeAttribute *LTA);
+
+ /// RAII object that pushes a function prototype scope holding \p Params and
+ /// restores the previous scope on destruction.
+ ///
+ /// A count expression written inside a *nested* function prototype, as in
+ ///
+ /// \code
+ /// void f(int *__counted_by(len) (*cb)(int len));
+ /// \endcode
+ ///
+ /// names a parameter of that inner prototype, whose scope has already been
+ /// popped by the time the attribute's tokens are parsed. Re-creating the
+ /// scope lets ordinary name lookup resolve the count at any nesting depth.
+ class FunctionPrototypeScopeRAII {
+ Sema &S;
+ Scope ProtoScope;
+
+ public:
+ FunctionPrototypeScopeRAII(Sema &S, ArrayRef<Decl *> Params);
+ ~FunctionPrototypeScopeRAII();
+
+ FunctionPrototypeScopeRAII(const FunctionPrototypeScopeRAII &) = delete;
+ FunctionPrototypeScopeRAII &
+ operator=(const FunctionPrototypeScopeRAII &) = delete;
+ };
+
+ /// Resolve late-parsed type attributes in the types of \p Params.
+ ///
+ /// Called once the whole parameter clause has been parsed, so that a count
+ /// expression may refer to any parameter of the function, including one
+ /// declared after the annotated parameter.
+ ///
+ /// This pushes its own prototype scope for \p Params, so it does not require
+ /// the caller's prototype scope to still be open. It does need *some* scope
+ /// to be current, since lookup has to be able to reach file scope to
+ /// diagnose a count that names a global.
+ void ProcessLateParsedTypeAttributesForParams(
+ ArrayRef<Decl *> Params, ParseLateParsedTypeAttributeCB *ParseCB);
+
/// Callback to the parser to parse a type expressed as a string.
std::function<TypeResult(StringRef, StringRef, SourceLocation)>
ParseTypeFromStringCallback;
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index abf0cd5e18c2b..562694ffc2b8c 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -2581,6 +2581,9 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
case Type::CountAttributed:
return getTypeInfo(cast<CountAttributedType>(T)->desugar().getTypePtr());
+ case Type::LateParsedAttr:
+ return getTypeInfo(cast<LateParsedAttrType>(T)->desugar().getTypePtr());
+
case Type::BTFTagAttributed:
return getTypeInfo(
cast<BTFTagAttributedType>(T)->getWrappedType().getTypePtr());
@@ -3751,6 +3754,17 @@ QualType ASTContext::getCountAttributedType(
return QualType(CATy, 0);
}
+QualType ASTContext::getLateParsedAttrType(
+ QualType WrappedTy, LateParsedTypeAttribute *LateParsedAttr) const {
+ QualType CanonTy = getCanonicalType(WrappedTy);
+
+ auto *LPATy = new (*this, alignof(LateParsedAttrType))
+ LateParsedAttrType(WrappedTy, CanonTy, LateParsedAttr);
+
+ Types.push_back(LPATy);
+ return QualType(LPATy, 0);
+}
+
QualType
ASTContext::adjustType(QualType Orig,
llvm::function_ref<QualType(QualType)> Adjust) const {
@@ -14920,6 +14934,10 @@ static QualType getCommonSugarTypeNode(const ASTContext &Ctx, const Type *X,
DX->isCountInBytes(), DX->isOrNull(),
CDX);
}
+
+ case Type::LateParsedAttr:
+ return QualType();
+
case Type::PredefinedSugar:
assert(cast<PredefinedSugarType>(X)->getKind() !=
cast<PredefinedSugarType>(Y)->getKind());
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index f5848d154f49e..9c45fd3ffd185 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -1842,6 +1842,11 @@ ASTNodeImporter::VisitCountAttributedType(const CountAttributedType *T) {
ArrayRef(CoupledDecls));
}
+ExpectedType
+ASTNodeImporter::VisitLateParsedAttrType(const LateParsedAttrType *T) {
+ llvm_unreachable("should be replaced with a concrete type before AST import");
+}
+
ExpectedType ASTNodeImporter::VisitTemplateTypeParmType(
const TemplateTypeParmType *T) {
Expected<TemplateTypeParmDecl *> ToDeclOrErr = import(T->getDecl());
diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp
index e0b62591a6a73..d8bbfbe5dac72 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -1208,6 +1208,13 @@ bool ASTStructuralEquivalence::isEquivalent(
return false;
break;
+ case Type::LateParsedAttr:
+ if (!IsStructurallyEquivalent(
+ Context, cast<LateParsedAttrType>(T1)->getWrappedType(),
+ cast<LateParsedAttrType>(T2)->getWrappedType()))
+ return false;
+ break;
+
case Type::BTFTagAttributed:
if (!IsStructurallyEquivalent(
Context, cast<BTFTagAttributedType>(T1)->getWrappedType(),
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index e5cdd6f31c507..60e77b66d92cf 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -2472,6 +2472,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
case Type::BitInt:
case Type::DependentBitInt:
case Type::CountAttributed:
+ case Type::LateParsedAttr:
llvm_unreachable("type is illegal as a nested name specifier");
case Type::SubstBuiltinTemplatePack:
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 53b869e019074..ae9838413ab44 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -288,6 +288,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
case Type::MacroQualified:
case Type::OverflowBehavior:
case Type::CountAttributed:
+ case Type::LateParsedAttr:
CanPrefixQualifiers = false;
break;
@@ -1832,6 +1833,20 @@ void TypePrinter::printCountAttributedAfter(const CountAttributedType *T,
printCountAttributedImpl(T, OS, Policy);
}
+void TypePrinter::printLateParsedAttrBefore(const LateParsedAttrType *T,
+ raw_ostream &OS) {
+ // LateParsedAttrType is a transient placeholder that should not appear
+ // in user-facing output. Just print the wrapped type.
+ printBefore(T->getWrappedType(), OS);
+}
+
+void TypePrinter::printLateParsedAttrAfter(const LateParsedAttrType *T,
+ raw_ostream &OS) {
+ // LateParsedAttrType is a transient placeholder that should not appear
+ // in user-facing output. Just print the wrapped type.
+ printAfter(T->getWrappedType(), OS);
+}
+
void TypePrinter::printAttributedBefore(const AttributedType *T,
raw_ostream &OS) {
// FIXME: Generate this with TableGen.
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 4b020c96964a7..7489a315af98c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -1642,6 +1642,7 @@ void CIRGenFunction::emitVariablyModifiedType(QualType type) {
case Type::HLSLAttributedResource:
case Type::HLSLInlineSpirv:
case Type::PredefinedSugar:
+ case Type::LateParsedAttr:
cgm.errorNYI("CIRGenFunction::emitVariablyModifiedType");
break;
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 3d429d0d78e82..6305c3a115dd4 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -4332,6 +4332,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
case Type::PredefinedSugar:
return getOrCreateType(cast<PredefinedSugarType>(Ty)-...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/213305
More information about the cfe-commits
mailing list