[clang] Rough first stab at addressing #85120 (PR #85147)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 13 16:06:47 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Doug Wyatt (dougsonos)
<details>
<summary>Changes</summary>
I pointed out this issue in the review for nolock/noalloc, and @<!-- -->Sirraide opened #<!-- -->85120
Here are some (very rough) bits of code I'd written to try to address the loss of type sugar, plus a subsequent crash involving lambdas (can't remember details now, and the crash may not exist any more on main).
Just in case it helps.
---
Full diff: https://github.com/llvm/llvm-project/pull/85147.diff
4 Files Affected:
- (modified) clang/include/clang/AST/ASTContext.h (+5)
- (modified) clang/lib/AST/ASTContext.cpp (+60-2)
- (modified) clang/lib/Sema/SemaExpr.cpp (+1-1)
- (modified) clang/lib/Sema/TreeTransform.h (+59-2)
``````````diff
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index ff6b64c7f72d57..ca90417c9bf70b 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1301,6 +1301,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// Change the result type of a function type once it is deduced.
void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType);
+ /// Transform a function type to have the provided result type, preserving
+ /// AttributedType and MacroQualifiedType sugar.
+ QualType getFunctionTypeWithResultType(QualType OrigFuncType, QualType ResultType,
+ const FunctionProtoType::ExtProtoInfo &EPI) const;
+
/// Get a function type and produce the equivalent function type with the
/// specified exception specification. Type sugar that can be present on a
/// declaration of a function with an exception specification is permitted
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 5a8fae76a43a4d..035dc19ba7011d 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -3140,13 +3140,71 @@ const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T,
return cast<FunctionType>(Result.getTypePtr());
}
+// EPI is provided by the caller because in the case of adjustDeducedFunctionResultType, it
+// is copied entirely from the previous FunctionType, but with a block (ActOnBlockStmtExpr),
+// it is more complicated...
+QualType ASTContext::getFunctionTypeWithResultType(QualType OrigFuncType, QualType ResultType,
+ const FunctionProtoType::ExtProtoInfo &EPI) const
+{
+ // Might be wrapped in a macro qualified type.
+ if (const auto *MQT = dyn_cast<MacroQualifiedType>(OrigFuncType)) {
+ return getMacroQualifiedType(
+ getFunctionTypeWithResultType(MQT->getUnderlyingType(), ResultType, EPI),
+ MQT->getMacroIdentifier());
+ }
+
+ // Might have a calling-convention attribute.
+ if (const auto *AT = dyn_cast<AttributedType>(OrigFuncType)) {
+ return getAttributedType(
+ AT->getAttrKind(),
+ getFunctionTypeWithResultType(AT->getModifiedType(), ResultType, EPI),
+ getFunctionTypeWithResultType(AT->getEquivalentType(), ResultType, EPI));
+ }
+
+ // Anything else must be a function type. Rebuild it with the new return value.
+ const auto *FPT = OrigFuncType->castAs<FunctionProtoType>();
+ return getFunctionType(ResultType, FPT->getParamTypes(), EPI);
+}
+
+#if 0
+static void examineType(const char* prefix, QualType QT, const char* term)
+{
+ llvm::outs() << prefix;
+ if (const auto *MQT = dyn_cast<MacroQualifiedType>(QT)) {
+ examineType( "MacroQualifiedType <", MQT->getUnderlyingType(), ">");
+ } else if (const auto *AT = dyn_cast<AttributedType>(QT)) {
+ examineType("AttributedType <", AT->getEquivalentType(), ">");
+ } else {
+ const auto *FPT = QT->castAs<FunctionProtoType>();
+ assert(FPT);
+ llvm::outs() << QT;
+ }
+ llvm::outs() << term;
+}
+#endif
+
void ASTContext::adjustDeducedFunctionResultType(FunctionDecl *FD,
QualType ResultType) {
FD = FD->getMostRecentDecl();
while (true) {
- const auto *FPT = FD->getType()->castAs<FunctionProtoType>();
+ QualType OrigFuncType = FD->getType();
+ const auto *FPT = OrigFuncType->castAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
- FD->setType(getFunctionType(ResultType, FPT->getParamTypes(), EPI));
+#if 1 // my new way
+ QualType NewFuncType = getFunctionTypeWithResultType(OrigFuncType, ResultType, EPI);
+#else // original way
+ QualType NewFuncType = getFunctionType(ResultType, FPT->getParamTypes(), EPI);
+#endif
+ /*llvm::outs() << "transform " << OrigFuncType << " -> " << NewFuncType << "\n";
+ llvm::outs() << " isConstQualified " << OrigFuncType.isConstQualified() << NewFuncType.isConstQualified() << "\n";
+ llvm::outs() << " isLocalConstQualified " << OrigFuncType.isLocalConstQualified() << NewFuncType.isLocalConstQualified() << "\n";
+ llvm::outs() << " const method " << FPT->isConst() << NewFuncType->castAs<FunctionProtoType>()->isConst() << "\n";
+ llvm::outs() << " canonical " << NewFuncType.getCanonicalType() << "\n";*/
+
+ /*examineType("original ", OrigFuncType, "\n");
+ examineType("deduced ", NewFuncType, "\n");*/
+
+ FD->setType(NewFuncType);
if (FunctionDecl *Next = FD->getPreviousDecl())
FD = Next;
else
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 93f82e68ab6440..651136d7c1b1b8 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -17161,7 +17161,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.TypeQuals = Qualifiers();
EPI.ExtInfo = Ext;
- BlockTy = Context.getFunctionType(RetTy, FPT->getParamTypes(), EPI);
+ BlockTy = Context.getFunctionTypeWithResultType(BSI->FunctionType, RetTy, EPI);
}
// If we don't have a function type, just build one from nothing.
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 2d22692f3ab750..9a8dac2258c1a0 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -13830,6 +13830,33 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
getSema().AddTemplateParametersToLambdaCallOperator(NewCallOperator, Class,
TPL);
+#if 0
+// Conflicting old bug fix attempt
+
+@@ -13719,10 +13719,23 @@
+ // it introduces a mapping of the original to the newly created
+ // transformed parameters.
+ TypeSourceInfo *NewCallOpTSI = nullptr;
++ // <rdar://117704214> Crash involving AttributedTypeLoc on lambda.
++ // Hack of a fix adapted from https://github.com/llvm/llvm-project/issues/58366
++ FunctionProtoTypeLoc NewCallOpFPTL;
+ {
+ TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo();
+ auto OldCallOpFPTL =
+ OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
++ AttributedTypeLoc OldCallOpATTL;
++ bool IsAttributed = false;
++ if (!OldCallOpFPTL) {
++ OldCallOpATTL = OldCallOpTSI->getTypeLoc().getAs<AttributedTypeLoc>();
++ assert(OldCallOpATTL);
++ OldCallOpFPTL =
++ OldCallOpATTL.getModifiedLoc().getAs<FunctionProtoTypeLoc>();
++ assert(OldCallOpFPTL);
++ IsAttributed = true;
++ }
+#endif
+
+
// Transform the type of the original lambda's call operator.
// The transformation MUST be done in the CurrentInstantiationScope since
// it introduces a mapping of the original to the newly created
@@ -13867,8 +13894,38 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
if (NewCallOpType.isNull())
return ExprError();
- NewCallOpTSI =
- NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, NewCallOpType);
+
+ // NewCallOpTSI =
+ // NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, NewCallOpType);
+ if (IsAttributed) {
+ const AttributedType *oldType = OldCallOpATTL.getTypePtr();
+
+ const Attr *newAttr = getDerived().TransformAttr(OldCallOpATTL.getAttr());
+ if (!newAttr)
+ return ExprError();
+
+ QualType equivalentType =
+ getDerived().TransformType(oldType->getEquivalentType());
+ if (equivalentType.isNull())
+ return ExprError();
+ QualType result = SemaRef.Context.getAttributedType(
+ OldCallOpATTL.getAttrKind(), NewCallOpType, equivalentType);
+
+ AttributedTypeLoc newTL =
+ NewCallOpTLBuilder.push<AttributedTypeLoc>(result);
+ newTL.setAttr(newAttr);
+
+ NewCallOpTSI =
+ NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, result);
+ NewCallOpFPTL = NewCallOpTSI->getTypeLoc()
+ .castAs<AttributedTypeLoc>()
+ .getModifiedLoc()
+ .castAs<FunctionProtoTypeLoc>();
+ } else {
+ NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context,
+ NewCallOpType);
+ NewCallOpFPTL = NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>();
+ }
}
ArrayRef<ParmVarDecl *> Params;
``````````
</details>
https://github.com/llvm/llvm-project/pull/85147
More information about the cfe-commits
mailing list