25 changes: 23 additions & 2 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1481,6 +1481,23 @@ bool Sema::IsFunctionConversion(QualType FromType, QualType ToType,
.getTypePtr());
Changed = true;
}

// Convert FromFPT's ExtParameterInfo if necessary. The conversion is valid
// only if the ExtParameterInfo lists of the two function prototypes can be
// merged and the merged list is identical to ToFPT's ExtParameterInfo list.
SmallVector<FunctionProtoType::ExtParameterInfo, 4> NewParamInfos;
bool CanUseToFPT, CanUseFromFPT;
if (Context.mergeExtParameterInfo(ToFPT, FromFPT, CanUseToFPT,
CanUseFromFPT, NewParamInfos) &&
CanUseToFPT && !CanUseFromFPT) {
FunctionProtoType::ExtProtoInfo ExtInfo = FromFPT->getExtProtoInfo();
ExtInfo.ExtParameterInfos =
NewParamInfos.empty() ? nullptr : NewParamInfos.data();
QualType QT = Context.getFunctionType(FromFPT->getReturnType(),
FromFPT->getParamTypes(), ExtInfo);
FromFn = QT->getAs<FunctionType>();
Changed = true;
}
}

if (!Changed)
Expand Down Expand Up @@ -2663,8 +2680,12 @@ bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType,
// Argument types are too different. Abort.
return false;
}
if (!Context.doFunctionTypesMatchOnExtParameterInfos(FromFunctionType,
ToFunctionType))

SmallVector<FunctionProtoType::ExtParameterInfo, 4> NewParamInfos;
bool CanUseToFPT, CanUseFromFPT;
if (!Context.mergeExtParameterInfo(ToFunctionType, FromFunctionType,
CanUseToFPT, CanUseFromFPT,
NewParamInfos))
return false;

ConvertedType = ToType;
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4479,6 +4479,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
HasAnyInterestingExtParameterInfos = true;
}

if (Param->hasAttr<NoEscapeAttr>()) {
ExtParameterInfos[i] = ExtParameterInfos[i].withIsNoEscape(true);
HasAnyInterestingExtParameterInfos = true;
}

ParamTys.push_back(ParamTy);
}

Expand Down
8 changes: 8 additions & 0 deletions clang/test/Misc/ast-dump-attr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,14 @@ __attribute__((external_source_symbol(generated_declaration, defined_in="module"
// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr5
// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module" GeneratedDeclaration

namespace TestNoEscape {
void noescapeFunc(int *p0, __attribute__((noescape)) int *p1) {}
// CHECK: `-FunctionDecl{{.*}} noescapeFunc 'void (int *, __attribute__((noescape)) int *)'
// CHECK-NEXT: ParmVarDecl
// CHECK-NEXT: ParmVarDecl
// CHECK-NEXT: NoEscapeAttr
}

namespace TestSuppress {
[[gsl::suppress("at-namespace")]];
// CHECK: NamespaceDecl{{.*}} TestSuppress
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

// The number of supported attributes should never go down!

// CHECK: #pragma clang attribute supports 64 attributes:
// CHECK: #pragma clang attribute supports 65 attributes:
// CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function)
// CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function)
// CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function)
Expand Down Expand Up @@ -35,6 +35,7 @@
// CHECK-NEXT: MipsShortCall (SubjectMatchRule_function)
// CHECK-NEXT: NoDebug (SubjectMatchRule_hasType_functionType, SubjectMatchRule_objc_method, SubjectMatchRule_variable_not_is_parameter)
// CHECK-NEXT: NoDuplicate (SubjectMatchRule_function)
// CHECK-NEXT: NoEscape (SubjectMatchRule_variable_is_parameter)
// CHECK-NEXT: NoMicroMips (SubjectMatchRule_function)
// CHECK-NEXT: NoSanitize (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global)
// CHECK-NEXT: NoSanitizeSpecific (SubjectMatchRule_function, SubjectMatchRule_variable_is_global)
Expand Down