summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/ASTContext.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2016-03-01 00:49:02 +0000
committerJohn McCall <rjmccall@apple.com>2016-03-01 00:49:02 +0000
commit18afab762a6c22de74f1ef714178fb9d1da159b1 (patch)
tree21e7d816b503992dffbc593f54cca2b040e6bb6f /clang/lib/AST/ASTContext.cpp
parent6d0c8a036e1f6eabae4962b711836920f1a354e3 (diff)
downloadbcm5719-llvm-18afab762a6c22de74f1ef714178fb9d1da159b1.tar.gz
bcm5719-llvm-18afab762a6c22de74f1ef714178fb9d1da159b1.zip
Generalize the consumed-parameter array on FunctionProtoType
to allow arbitrary data to be associated with a parameter. Also, fix a bug where we apparently haven't been serializing this information for the last N years. llvm-svn: 262278
Diffstat (limited to 'clang/lib/AST/ASTContext.cpp')
-rw-r--r--clang/lib/AST/ASTContext.cpp75
1 files changed, 43 insertions, 32 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index c6f5374d5c0..dad6d1a9d4f 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -2992,13 +2992,18 @@ ASTContext::getDependentSizedExtVectorType(QualType vecType,
return QualType(New, 0);
}
+/// \brief Determine whether \p T is canonical as the result type of a function.
+static bool isCanonicalResultType(QualType T) {
+ return T.isCanonical() &&
+ (T.getObjCLifetime() == Qualifiers::OCL_None ||
+ T.getObjCLifetime() == Qualifiers::OCL_ExplicitNone);
+}
+
/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
///
QualType
ASTContext::getFunctionNoProtoType(QualType ResultTy,
const FunctionType::ExtInfo &Info) const {
- const CallingConv CallConv = Info.getCC();
-
// Unique functions, to guarantee there is only one function of a particular
// structure.
llvm::FoldingSetNodeID ID;
@@ -3010,8 +3015,9 @@ ASTContext::getFunctionNoProtoType(QualType ResultTy,
return QualType(FT, 0);
QualType Canonical;
- if (!ResultTy.isCanonical()) {
- Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy), Info);
+ if (!isCanonicalResultType(ResultTy)) {
+ Canonical =
+ getFunctionNoProtoType(getCanonicalFunctionResultType(ResultTy), Info);
// Get the new insert position for the node we care about.
FunctionNoProtoType *NewIP =
@@ -3019,21 +3025,13 @@ ASTContext::getFunctionNoProtoType(QualType ResultTy,
assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
- FunctionProtoType::ExtInfo newInfo = Info.withCallingConv(CallConv);
FunctionNoProtoType *New = new (*this, TypeAlignment)
- FunctionNoProtoType(ResultTy, Canonical, newInfo);
+ FunctionNoProtoType(ResultTy, Canonical, Info);
Types.push_back(New);
FunctionNoProtoTypes.InsertNode(New, InsertPos);
return QualType(New, 0);
}
-/// \brief Determine whether \p T is canonical as the result type of a function.
-static bool isCanonicalResultType(QualType T) {
- return T.isCanonical() &&
- (T.getObjCLifetime() == Qualifiers::OCL_None ||
- T.getObjCLifetime() == Qualifiers::OCL_ExplicitNone);
-}
-
CanQualType
ASTContext::getCanonicalFunctionResultType(QualType ResultType) const {
CanQualType CanResultType = getCanonicalType(ResultType);
@@ -3100,12 +3098,13 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
// them for three variable size arrays at the end:
// - parameter types
// - exception types
- // - consumed-arguments flags
+ // - extended parameter information
// Instead of the exception types, there could be a noexcept
// expression, or information used to resolve the exception
// specification.
size_t Size = sizeof(FunctionProtoType) +
NumArgs * sizeof(QualType);
+
if (EPI.ExceptionSpec.Type == EST_Dynamic) {
Size += EPI.ExceptionSpec.Exceptions.size() * sizeof(QualType);
} else if (EPI.ExceptionSpec.Type == EST_ComputedNoexcept) {
@@ -3115,8 +3114,16 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
} else if (EPI.ExceptionSpec.Type == EST_Unevaluated) {
Size += sizeof(FunctionDecl*);
}
- if (EPI.ConsumedParameters)
- Size += NumArgs * sizeof(bool);
+
+ // Put the ExtParameterInfos last. If all were equal, it would make
+ // more sense to put these before the exception specification, because
+ // it's much easier to skip past them compared to the elaborate switch
+ // required to skip the exception specification. However, all is not
+ // equal; ExtParameterInfos are used to model very uncommon features,
+ // and it's better not to burden the more common paths.
+ if (EPI.ExtParameterInfos) {
+ Size += NumArgs * sizeof(FunctionProtoType::ExtParameterInfo);
+ }
FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment);
FunctionProtoType::ExtProtoInfo newEPI = EPI;
@@ -7489,8 +7496,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
if (lproto->getTypeQuals() != rproto->getTypeQuals())
return QualType();
- if (LangOpts.ObjCAutoRefCount &&
- !FunctionTypesMatchOnNSConsumedAttrs(rproto, lproto))
+ if (!doFunctionTypesMatchOnExtParameterInfos(rproto, lproto))
return QualType();
// Check parameter type compatibility
@@ -7878,21 +7884,26 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
llvm_unreachable("Invalid Type::Class!");
}
-bool ASTContext::FunctionTypesMatchOnNSConsumedAttrs(
- const FunctionProtoType *FromFunctionType,
- const FunctionProtoType *ToFunctionType) {
- if (FromFunctionType->hasAnyConsumedParams() !=
- ToFunctionType->hasAnyConsumedParams())
+bool ASTContext::doFunctionTypesMatchOnExtParameterInfos(
+ const FunctionProtoType *firstFnType,
+ const FunctionProtoType *secondFnType) {
+ // Fast path: if the first type doesn't have ext parameter infos,
+ // we match if and only if they second type also doesn't have them.
+ if (!firstFnType->hasExtParameterInfos())
+ return !secondFnType->hasExtParameterInfos();
+
+ // Otherwise, we can only match if the second type has them.
+ if (!secondFnType->hasExtParameterInfos())
return false;
- FunctionProtoType::ExtProtoInfo FromEPI =
- FromFunctionType->getExtProtoInfo();
- FunctionProtoType::ExtProtoInfo ToEPI =
- ToFunctionType->getExtProtoInfo();
- if (FromEPI.ConsumedParameters && ToEPI.ConsumedParameters)
- for (unsigned i = 0, n = FromFunctionType->getNumParams(); i != n; ++i) {
- if (FromEPI.ConsumedParameters[i] != ToEPI.ConsumedParameters[i])
- return false;
- }
+
+ auto firstEPI = firstFnType->getExtParameterInfos();
+ auto secondEPI = secondFnType->getExtParameterInfos();
+ assert(firstEPI.size() == secondEPI.size());
+
+ for (size_t i = 0, n = firstEPI.size(); i != n; ++i) {
+ if (firstEPI[i] != secondEPI[i])
+ return false;
+ }
return true;
}
OpenPOWER on IntegriCloud