diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -2611,16 +2611,19 @@ bool canBindObjCObjectType(QualType To, QualType From); // Functions for calculating composite types - QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false, - bool Unqualified = false, bool BlockReturnType = false); - QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, + QualType mergeTypes(QualType, QualType, bool OfBlockPointer = false, + bool Unqualified = false, bool BlockReturnType = false, + bool AllowCXX = false); + QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer = false, bool Unqualified = false, bool AllowCXX = false); QualType mergeFunctionParameterTypes(QualType, QualType, bool OfBlockPointer = false, - bool Unqualified = false); + bool Unqualified = false, + bool AllowCXX = false); QualType mergeTransparentUnionType(QualType, QualType, - bool OfBlockPointer=false, - bool Unqualified = false); + bool OfBlockPointer = false, + bool Unqualified = false, + bool AllowCXX = false); QualType mergeObjCGCQualifiers(QualType, QualType); diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -9179,13 +9179,15 @@ /// QualType() QualType ASTContext::mergeTransparentUnionType(QualType T, QualType SubType, bool OfBlockPointer, - bool Unqualified) { + bool Unqualified, + bool AllowCXX) { if (const RecordType *UT = T->getAsUnionType()) { RecordDecl *UD = UT->getDecl(); if (UD->hasAttr()) { for (const auto *I : UD->fields()) { QualType ET = I->getType().getUnqualifiedType(); - QualType MT = mergeTypes(ET, SubType, OfBlockPointer, Unqualified); + QualType MT = mergeTypes(ET, SubType, OfBlockPointer, Unqualified, + /* BlockReturnType */ false, AllowCXX); if (!MT.isNull()) return MT; } @@ -9199,21 +9201,23 @@ /// parameter types QualType ASTContext::mergeFunctionParameterTypes(QualType lhs, QualType rhs, bool OfBlockPointer, - bool Unqualified) { + bool Unqualified, + bool AllowCXX) { // GNU extension: two types are compatible if they appear as a function // argument, one of the types is a transparent union type and the other // type is compatible with a union member QualType lmerge = mergeTransparentUnionType(lhs, rhs, OfBlockPointer, - Unqualified); + Unqualified, AllowCXX); if (!lmerge.isNull()) return lmerge; QualType rmerge = mergeTransparentUnionType(rhs, lhs, OfBlockPointer, - Unqualified); + Unqualified, AllowCXX); if (!rmerge.isNull()) return rmerge; - return mergeTypes(lhs, rhs, OfBlockPointer, Unqualified); + return mergeTypes(lhs, rhs, OfBlockPointer, Unqualified, + /* BlockReturnType */ false, AllowCXX); } QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, @@ -9234,11 +9238,11 @@ bool UnqualifiedResult = Unqualified; if (!UnqualifiedResult) UnqualifiedResult = (!RHS.hasQualifiers() && LHS.hasQualifiers()); - retType = mergeTypes(LHS, RHS, true, UnqualifiedResult, true); - } - else + retType = mergeTypes(LHS, RHS, true, UnqualifiedResult, + /* BlockReturnType */ true, AllowCXX); + } else retType = mergeTypes(lbase->getReturnType(), rbase->getReturnType(), false, - Unqualified); + Unqualified, /* BlockReturnType */ false, AllowCXX); if (retType.isNull()) return {}; @@ -9323,7 +9327,7 @@ QualType lParamType = lproto->getParamType(i).getUnqualifiedType(); QualType rParamType = rproto->getParamType(i).getUnqualifiedType(); QualType paramType = mergeFunctionParameterTypes( - lParamType, rParamType, OfBlockPointer, Unqualified); + lParamType, rParamType, OfBlockPointer, Unqualified, AllowCXX); if (paramType.isNull()) return {}; @@ -9416,9 +9420,18 @@ return {}; } -QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, - bool OfBlockPointer, - bool Unqualified, bool BlockReturnType) { +QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, bool OfBlockPointer, + bool Unqualified, bool BlockReturnType, + bool AllowCXX) { + // If AllowCXX is specifically set we strip reference types on demand. + assert((AllowCXX || + (!LHS->getAs() && !RHS->getAs())) && + "C++ references should have been stripped"); + if (const ReferenceType *lRT = LHS->getAs()) + LHS = lRT->getPointeeType(); + if (const ReferenceType *rRT = RHS->getAs()) + RHS = rRT->getPointeeType(); + // C++ [expr]: If an expression initially has the type "reference to T", the // type is adjusted to "T" prior to any further analysis, the expression // designates the object or function denoted by the reference, and the @@ -9550,8 +9563,8 @@ LHSPointee = LHSPointee.getUnqualifiedType(); RHSPointee = RHSPointee.getUnqualifiedType(); } - QualType ResultType = mergeTypes(LHSPointee, RHSPointee, false, - Unqualified); + QualType ResultType = mergeTypes(LHSPointee, RHSPointee, false, Unqualified, + BlockReturnType, AllowCXX); if (ResultType.isNull()) return {}; if (getCanonicalType(LHSPointee) == getCanonicalType(ResultType)) @@ -9584,7 +9597,7 @@ QualType(RHSPointee.getTypePtr(), RHSPteeQual.getAsOpaqueValue()); } QualType ResultType = mergeTypes(LHSPointee, RHSPointee, OfBlockPointer, - Unqualified); + Unqualified, BlockReturnType, AllowCXX); if (ResultType.isNull()) return {}; if (getCanonicalType(LHSPointee) == getCanonicalType(ResultType)) @@ -9602,8 +9615,8 @@ LHSValue = LHSValue.getUnqualifiedType(); RHSValue = RHSValue.getUnqualifiedType(); } - QualType ResultType = mergeTypes(LHSValue, RHSValue, false, - Unqualified); + QualType ResultType = mergeTypes(LHSValue, RHSValue, false, Unqualified, + BlockReturnType, AllowCXX); if (ResultType.isNull()) return {}; if (getCanonicalType(LHSValue) == getCanonicalType(ResultType)) @@ -9626,7 +9639,8 @@ RHSElem = RHSElem.getUnqualifiedType(); } - QualType ResultType = mergeTypes(LHSElem, RHSElem, false, Unqualified); + QualType ResultType = mergeTypes(LHSElem, RHSElem, false, Unqualified, + BlockReturnType, AllowCXX); if (ResultType.isNull()) return {};