Add noreturn as a type attribute, handle printing for them and handle
calls to noreturn function pointers when CFG building.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77089 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 4684a80..27c8a81 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -965,7 +965,7 @@
// Check if we've already instantiated this type.
llvm::FoldingSetNodeID ID;
- ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr);
+ ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr);
void *InsertPos = 0;
if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(EXTQy, CVRQuals);
@@ -1007,17 +1007,17 @@
unsigned AddressSpace = 0;
if (ExtQualType *EQT = dyn_cast<ExtQualType>(TypeNode)) {
- // If this type already has an address space specified, it cannot get
+ // If this type already has an ObjCGC specified, it cannot get
// another one.
assert(EQT->getObjCGCAttr() == QualType::GCNone &&
- "Type cannot be in multiple addr spaces!");
+ "Type cannot have multiple ObjCGCs!");
AddressSpace = EQT->getAddressSpace();
TypeNode = EQT->getBaseType();
}
// Check if we've already instantiated an gc qual'd type of this type.
llvm::FoldingSetNodeID ID;
- ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr);
+ ExtQualType::Profile(ID, TypeNode, AddressSpace, GCAttr);
void *InsertPos = 0;
if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(EXTQy, CVRQuals);
@@ -1041,6 +1041,30 @@
return QualType(New, CVRQuals);
}
+QualType ASTContext::getNoReturnType(QualType T) {
+ if (T->isPointerType()) {
+ QualType Pointee = T->getAsPointerType()->getPointeeType();
+ QualType ResultType = getNoReturnType(Pointee);
+ return getPointerType(ResultType);
+ }
+ if (T->isBlockPointerType()) {
+ QualType Pointee = T->getAsBlockPointerType()->getPointeeType();
+ QualType ResultType = getNoReturnType(Pointee);
+ return getBlockPointerType(ResultType);
+ }
+ if (!T->isFunctionType())
+ assert(0 && "can't noreturn qualify non-pointer to function or block type");
+
+ if (const FunctionNoProtoType *F = dyn_cast<FunctionNoProtoType>(T)) {
+ return getFunctionNoProtoType(F->getResultType(), true);
+ }
+ const FunctionProtoType *F = cast<FunctionProtoType>(T);
+ return getFunctionType(F->getResultType(), F->arg_type_begin(),
+ F->getNumArgs(), F->isVariadic(), F->getTypeQuals(),
+ F->hasExceptionSpec(), F->hasAnyExceptionSpec(),
+ F->getNumExceptions(), F->exception_begin(), true);
+}
+
/// getComplexType - Return the uniqued reference to the type for a complex
/// number with the specified element type.
QualType ASTContext::getComplexType(QualType T) {
@@ -1474,11 +1498,11 @@
/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
///
-QualType ASTContext::getFunctionNoProtoType(QualType ResultTy) {
+QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool NoReturn) {
// Unique functions, to guarantee there is only one function of a particular
// structure.
llvm::FoldingSetNodeID ID;
- FunctionNoProtoType::Profile(ID, ResultTy);
+ FunctionNoProtoType::Profile(ID, ResultTy, NoReturn);
void *InsertPos = 0;
if (FunctionNoProtoType *FT =
@@ -1487,7 +1511,7 @@
QualType Canonical;
if (!ResultTy->isCanonical()) {
- Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy));
+ Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy), NoReturn);
// Get the new insert position for the node we care about.
FunctionNoProtoType *NewIP =
@@ -1495,7 +1519,8 @@
assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP;
}
- FunctionNoProtoType *New =new(*this,8)FunctionNoProtoType(ResultTy,Canonical);
+ FunctionNoProtoType *New
+ = new (*this,8) FunctionNoProtoType(ResultTy, Canonical, NoReturn);
Types.push_back(New);
FunctionNoProtoTypes.InsertNode(New, InsertPos);
return QualType(New, 0);
@@ -1507,13 +1532,13 @@
unsigned NumArgs, bool isVariadic,
unsigned TypeQuals, bool hasExceptionSpec,
bool hasAnyExceptionSpec, unsigned NumExs,
- const QualType *ExArray) {
+ const QualType *ExArray, bool NoReturn) {
// Unique functions, to guarantee there is only one function of a particular
// structure.
llvm::FoldingSetNodeID ID;
FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, isVariadic,
TypeQuals, hasExceptionSpec, hasAnyExceptionSpec,
- NumExs, ExArray);
+ NumExs, ExArray, NoReturn);
void *InsertPos = 0;
if (FunctionProtoType *FTP =
@@ -1539,7 +1564,7 @@
Canonical = getFunctionType(getCanonicalType(ResultTy),
CanonicalArgs.data(), NumArgs,
- isVariadic, TypeQuals);
+ isVariadic, TypeQuals, NoReturn);
// Get the new insert position for the node we care about.
FunctionProtoType *NewIP =
@@ -1556,7 +1581,7 @@
NumExs*sizeof(QualType), 8);
new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, isVariadic,
TypeQuals, hasExceptionSpec, hasAnyExceptionSpec,
- ExArray, NumExs, Canonical);
+ ExArray, NumExs, Canonical, NoReturn);
Types.push_back(FTP);
FunctionProtoTypes.InsertNode(FTP, InsertPos);
return QualType(FTP, 0);
@@ -3344,7 +3369,12 @@
allLTypes = false;
if (getCanonicalType(retType) != getCanonicalType(rbase->getResultType()))
allRTypes = false;
-
+ bool NoReturn = lbase->getNoReturnAttr() || rbase->getNoReturnAttr();
+ if (NoReturn != lbase->getNoReturnAttr())
+ allLTypes = false;
+ if (NoReturn != rbase->getNoReturnAttr())
+ allRTypes = false;
+
if (lproto && rproto) { // two C99 style function prototypes
assert(!lproto->hasExceptionSpec() && !rproto->hasExceptionSpec() &&
"C++ shouldn't be here");
@@ -3378,7 +3408,8 @@
if (allLTypes) return lhs;
if (allRTypes) return rhs;
return getFunctionType(retType, types.begin(), types.size(),
- lproto->isVariadic(), lproto->getTypeQuals());
+ lproto->isVariadic(), lproto->getTypeQuals(),
+ NoReturn);
}
if (lproto) allRTypes = false;
@@ -3405,12 +3436,12 @@
if (allRTypes) return rhs;
return getFunctionType(retType, proto->arg_type_begin(),
proto->getNumArgs(), lproto->isVariadic(),
- lproto->getTypeQuals());
+ lproto->getTypeQuals(), NoReturn);
}
if (allLTypes) return lhs;
if (allRTypes) return rhs;
- return getFunctionNoProtoType(retType);
+ return getFunctionNoProtoType(retType, NoReturn);
}
QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index c3bb29b..ef75b2b 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -904,7 +904,7 @@
unsigned NumArgs, bool isVariadic,
unsigned TypeQuals, bool hasExceptionSpec,
bool anyExceptionSpec, unsigned NumExceptions,
- exception_iterator Exs) {
+ exception_iterator Exs, bool NoReturn) {
ID.AddPointer(Result.getAsOpaquePtr());
for (unsigned i = 0; i != NumArgs; ++i)
ID.AddPointer(ArgTys[i].getAsOpaquePtr());
@@ -916,12 +916,13 @@
for(unsigned i = 0; i != NumExceptions; ++i)
ID.AddPointer(Exs[i].getAsOpaquePtr());
}
+ ID.AddInteger(NoReturn);
}
void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getResultType(), arg_type_begin(), NumArgs, isVariadic(),
getTypeQuals(), hasExceptionSpec(), hasAnyExceptionSpec(),
- getNumExceptions(), exception_begin());
+ getNumExceptions(), exception_begin(), getNoReturnAttr());
}
void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID,
@@ -1082,7 +1083,7 @@
if (EQT->getObjCGCAttr())
GCAttrType = EQT->getObjCGCAttr();
return EQT->getBaseType();
- }else {
+ } else {
// Use the sugared type unless desugaring found extra qualifiers.
return (DT.getCVRQualifiers() ? DT.getTypePtr() : T);
}
@@ -1413,6 +1414,8 @@
S = "(" + S + ")";
S += "()";
+ if (getNoReturnAttr())
+ S += " __attribute__((noreturn))";
getResultType().getAsStringInternal(S, Policy);
}
@@ -1442,6 +1445,8 @@
}
S += ")";
+ if (getNoReturnAttr())
+ S += " __attribute__((noreturn))";
getResultType().getAsStringInternal(S, Policy);
}