Skip to content

Commit 8060245

Browse files
committed
Add MergeMSVCCompatibleFunctionDecls function to Sema class
1 parent 744a605 commit 8060245

File tree

2 files changed

+81
-0
lines changed

2 files changed

+81
-0
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3749,6 +3749,8 @@ class Sema final {
37493749
bool MergeTypeWithOld, bool NewDeclIsDefn);
37503750
bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
37513751
Scope *S, bool MergeTypeWithOld);
3752+
bool MergeMSVCCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
3753+
Scope *S, bool MergeTypeWithOld);
37523754
void mergeObjCMethodDecls(ObjCMethodDecl *New, ObjCMethodDecl *Old);
37533755
void MergeVarDecl(VarDecl *New, LookupResult &Previous);
37543756
void MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool MergeTypeWithOld);

clang/lib/Sema/SemaDecl.cpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4418,6 +4418,85 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
44184418
return false;
44194419
}
44204420

4421+
// The same as MergeCompatibleFunctionDecls, but for MSVC-compatible
4422+
bool Sema::MergeMSVCCompatibleFunctionDecls(FunctionDecl *New,
4423+
FunctionDecl *Old, Scope *S,
4424+
bool MergeTypeWithOld) {
4425+
QualType OldQType = Context.getCanonicalType(Old->getType());
4426+
QualType NewQType = Context.getCanonicalType(New->getType());
4427+
4428+
const FunctionType *OldFuncType = OldQType->getAs<FunctionType>();
4429+
const FunctionType *NewFuncType = NewQType->getAs<FunctionType>();
4430+
4431+
const FunctionProtoType *OldProto = nullptr;
4432+
const FunctionProtoType *NewProto = nullptr;
4433+
4434+
// If the types are not funtion types, do not merge the declarations.
4435+
if (!((NewProto = dyn_cast<FunctionProtoType>(NewFuncType)) &&
4436+
(OldProto = dyn_cast<FunctionProtoType>(OldFuncType))))
4437+
return true;
4438+
4439+
// If the parameter types are different, do not merge the declarations.
4440+
if (OldProto->param_types().size() != NewProto->param_types().size())
4441+
return true;
4442+
4443+
// Check parameter types if we can merge the declarations.
4444+
bool CanMerge = false;
4445+
if (OldProto->param_types().size() != 0) {
4446+
for (size_t i = 0; i < OldProto->param_types().size(); ++i) {
4447+
QualType OldParamType = OldProto->param_types()[i];
4448+
QualType NewParamType = NewProto->param_types()[i];
4449+
4450+
// Remove local const/volatile qualifiers from the parameter types.
4451+
OldParamType.removeLocalConst();
4452+
NewParamType.removeLocalConst();
4453+
OldParamType.removeLocalVolatile();
4454+
NewParamType.removeLocalVolatile();
4455+
4456+
// If the parameter types are different, we need to check if we can
4457+
// merge the declarations.
4458+
if (OldParamType.getAsString() != NewParamType.getAsString()) {
4459+
// If the parameter types are PointerType, we can merge the
4460+
// declarations.
4461+
if (isa<PointerType>(OldParamType) &&
4462+
isa<PointerType>(NewParamType)) {
4463+
CanMerge = true;
4464+
continue;
4465+
}
4466+
CanMerge = false;
4467+
break;
4468+
}
4469+
}
4470+
}
4471+
if (!CanMerge)
4472+
return true;
4473+
4474+
if (MergeTypeWithOld) {
4475+
// The old declaration provided a function prototype, but the
4476+
// new declaration does not. Merge in the prototype.
4477+
assert(!OldProto->hasExceptionSpec() && "Exception spec in C");
4478+
NewQType = Context.getFunctionType(NewFuncType->getReturnType(),
4479+
OldProto->getParamTypes(),
4480+
OldProto->getExtProtoInfo());
4481+
New->setType(NewQType);
4482+
New->setHasInheritedPrototype();
4483+
4484+
// Synthesize parameters with the same types.
4485+
SmallVector<ParmVarDecl *, 16> Params;
4486+
for (const auto &ParamType : OldProto->param_types()) {
4487+
ParmVarDecl *Param = ParmVarDecl::Create(
4488+
Context, New, SourceLocation(), SourceLocation(), nullptr,
4489+
ParamType, /*TInfo=*/nullptr, SC_None, nullptr);
4490+
Param->setScopeInfo(0, Params.size());
4491+
Param->setImplicit();
4492+
Params.push_back(Param);
4493+
}
4494+
4495+
New->setParams(Params);
4496+
}
4497+
return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld);
4498+
}
4499+
44214500
void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
44224501
ObjCMethodDecl *oldMethod) {
44234502
// Merge the attributes, including deprecated/unavailable

0 commit comments

Comments
 (0)