summaryrefslogtreecommitdiffstats
path: root/lib/AST
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2010-01-15 15:39:40 +0000
committerrdivacky <rdivacky@FreeBSD.org>2010-01-15 15:39:40 +0000
commita3fa5c7f1b5e2ba4d6ec033dc0e2376326b05824 (patch)
treea6082d4d1d1e9ddaea09a6a04bb4a47da95d642d /lib/AST
parentbb1e3bc1e0be2b8f891db46457a8943451bf4d8b (diff)
downloadFreeBSD-src-a3fa5c7f1b5e2ba4d6ec033dc0e2376326b05824.zip
FreeBSD-src-a3fa5c7f1b5e2ba4d6ec033dc0e2376326b05824.tar.gz
Update clang to r93512.
Diffstat (limited to 'lib/AST')
-rw-r--r--lib/AST/APValue.cpp33
-rw-r--r--lib/AST/ASTContext.cpp62
-rw-r--r--lib/AST/AttrImpl.cpp143
-rw-r--r--lib/AST/CMakeLists.txt1
-rw-r--r--lib/AST/Decl.cpp11
-rw-r--r--lib/AST/DeclCXX.cpp35
-rw-r--r--lib/AST/DeclarationName.cpp51
-rw-r--r--lib/AST/Expr.cpp30
-rw-r--r--lib/AST/ExprConstant.cpp108
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp11
-rw-r--r--lib/AST/Stmt.cpp4
-rw-r--r--lib/AST/StmtPrinter.cpp12
-rw-r--r--lib/AST/TypeLoc.cpp12
-rw-r--r--lib/AST/TypePrinter.cpp9
14 files changed, 396 insertions, 126 deletions
diff --git a/lib/AST/APValue.cpp b/lib/AST/APValue.cpp
index 772a884..50a6e0a 100644
--- a/lib/AST/APValue.cpp
+++ b/lib/AST/APValue.cpp
@@ -12,9 +12,20 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/APValue.h"
+#include "clang/AST/CharUnits.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
+namespace {
+ struct LV {
+ Expr* Base;
+ CharUnits Offset;
+ };
+}
+
+APValue::APValue(Expr* B) : Kind(Uninitialized) {
+ MakeLValue(); setLValue(B, CharUnits::Zero());
+}
const APValue &APValue::operator=(const APValue &RHS) {
if (Kind != RHS.Kind) {
@@ -106,3 +117,25 @@ void APValue::print(llvm::raw_ostream &OS) const {
}
}
+Expr* APValue::getLValueBase() const {
+ assert(isLValue() && "Invalid accessor");
+ return ((const LV*)(const void*)Data)->Base;
+}
+
+CharUnits APValue::getLValueOffset() const {
+ assert(isLValue() && "Invalid accessor");
+ return ((const LV*)(const void*)Data)->Offset;
+}
+
+void APValue::setLValue(Expr *B, const CharUnits &O) {
+ assert(isLValue() && "Invalid accessor");
+ ((LV*)(char*)Data)->Base = B;
+ ((LV*)(char*)Data)->Offset = O;
+}
+
+void APValue::MakeLValue() {
+ assert(isUninit() && "Bad state change");
+ new ((void*)(char*)Data) LV();
+ Kind = LValue;
+}
+
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 74e74e7..76ec852 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -814,10 +814,10 @@ ASTContext::getTypeInfo(const Type *T) {
/// getTypeSizeInChars - Return the size of the specified type, in characters.
/// This method does not work on incomplete types.
CharUnits ASTContext::getTypeSizeInChars(QualType T) {
- return CharUnits::fromRaw(getTypeSize(T) / getCharWidth());
+ return CharUnits::fromQuantity(getTypeSize(T) / getCharWidth());
}
CharUnits ASTContext::getTypeSizeInChars(const Type *T) {
- return CharUnits::fromRaw(getTypeSize(T) / getCharWidth());
+ return CharUnits::fromQuantity(getTypeSize(T) / getCharWidth());
}
/// getPreferredTypeAlign - Return the "preferred" alignment of the specified
@@ -2374,16 +2374,14 @@ CanQualType ASTContext::getCanonicalType(QualType T) {
QualType ASTContext::getUnqualifiedArrayType(QualType T,
Qualifiers &Quals) {
- assert(T.isCanonical() && "Only operates on canonical types");
+ Quals = T.getQualifiers();
if (!isa<ArrayType>(T)) {
- Quals = T.getLocalQualifiers();
- return T.getLocalUnqualifiedType();
+ return T.getUnqualifiedType();
}
- assert(!T.hasQualifiers() && "canonical array type has qualifiers!");
const ArrayType *AT = cast<ArrayType>(T);
QualType Elt = AT->getElementType();
- QualType UnqualElt = getUnqualifiedArrayType(getCanonicalType(Elt), Quals);
+ QualType UnqualElt = getUnqualifiedArrayType(Elt, Quals);
if (Elt == UnqualElt)
return T;
@@ -2396,12 +2394,6 @@ QualType ASTContext::getUnqualifiedArrayType(QualType T,
return getIncompleteArrayType(UnqualElt, IAT->getSizeModifier(), 0);
}
- if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(T)) {
- return getVariableArrayType(UnqualElt, VAT->getSizeExpr()->Retain(),
- VAT->getSizeModifier(), 0,
- SourceRange());
- }
-
const DependentSizedArrayType *DSAT = cast<DependentSizedArrayType>(T);
return getDependentSizedArrayType(UnqualElt, DSAT->getSizeExpr()->Retain(),
DSAT->getSizeModifier(), 0,
@@ -3143,16 +3135,21 @@ static bool isTypeTypedefedAsBOOL(QualType T) {
/// getObjCEncodingTypeSize returns size of type for objective-c encoding
/// purpose.
-int ASTContext::getObjCEncodingTypeSize(QualType type) {
- uint64_t sz = getTypeSize(type);
+CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) {
+ CharUnits sz = getTypeSizeInChars(type);
// Make all integer and enum types at least as large as an int
- if (sz > 0 && type->isIntegralType())
- sz = std::max(sz, getTypeSize(IntTy));
+ if (sz.isPositive() && type->isIntegralType())
+ sz = std::max(sz, getTypeSizeInChars(IntTy));
// Treat arrays as pointers, since that's how they're passed in.
else if (type->isArrayType())
- sz = getTypeSize(VoidPtrTy);
- return sz / getTypeSize(CharTy);
+ sz = getTypeSizeInChars(VoidPtrTy);
+ return sz;
+}
+
+static inline
+std::string charUnitsToString(const CharUnits &CU) {
+ return llvm::itostr(CU.getQuantity());
}
/// getObjCEncodingForBlockDecl - Return the encoded type for this method
@@ -3168,17 +3165,17 @@ void ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr,
// Start with computing size of a pointer in number of bytes.
// FIXME: There might(should) be a better way of doing this computation!
SourceLocation Loc;
- int PtrSize = getTypeSize(VoidPtrTy) / getTypeSize(CharTy);
- int ParmOffset = PtrSize;
+ CharUnits PtrSize = getTypeSizeInChars(VoidPtrTy);
+ CharUnits ParmOffset = PtrSize;
for (ObjCMethodDecl::param_iterator PI = Decl->param_begin(),
E = Decl->param_end(); PI != E; ++PI) {
QualType PType = (*PI)->getType();
- int sz = getObjCEncodingTypeSize(PType);
- assert (sz > 0 && "BlockExpr - Incomplete param type");
+ CharUnits sz = getObjCEncodingTypeSize(PType);
+ assert (sz.isPositive() && "BlockExpr - Incomplete param type");
ParmOffset += sz;
}
// Size of the argument frame
- S += llvm::utostr(ParmOffset);
+ S += charUnitsToString(ParmOffset);
// Block pointer and offset.
S += "@?0";
ParmOffset = PtrSize;
@@ -3198,7 +3195,7 @@ void ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr,
} else if (PType->isFunctionType())
PType = PVDecl->getType();
getObjCEncodingForType(PType, S);
- S += llvm::utostr(ParmOffset);
+ S += charUnitsToString(ParmOffset);
ParmOffset += getObjCEncodingTypeSize(PType);
}
}
@@ -3216,20 +3213,21 @@ void ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
// Start with computing size of a pointer in number of bytes.
// FIXME: There might(should) be a better way of doing this computation!
SourceLocation Loc;
- int PtrSize = getTypeSize(VoidPtrTy) / getTypeSize(CharTy);
+ CharUnits PtrSize = getTypeSizeInChars(VoidPtrTy);
// The first two arguments (self and _cmd) are pointers; account for
// their size.
- int ParmOffset = 2 * PtrSize;
+ CharUnits ParmOffset = 2 * PtrSize;
for (ObjCMethodDecl::param_iterator PI = Decl->param_begin(),
E = Decl->param_end(); PI != E; ++PI) {
QualType PType = (*PI)->getType();
- int sz = getObjCEncodingTypeSize(PType);
- assert (sz > 0 && "getObjCEncodingForMethodDecl - Incomplete param type");
+ CharUnits sz = getObjCEncodingTypeSize(PType);
+ assert (sz.isPositive() &&
+ "getObjCEncodingForMethodDecl - Incomplete param type");
ParmOffset += sz;
}
- S += llvm::utostr(ParmOffset);
+ S += charUnitsToString(ParmOffset);
S += "@0:";
- S += llvm::utostr(PtrSize);
+ S += charUnitsToString(PtrSize);
// Argument types.
ParmOffset = 2 * PtrSize;
@@ -3249,7 +3247,7 @@ void ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
// 'in', 'inout', etc.
getObjCEncodingForTypeQualifier(PVDecl->getObjCDeclQualifier(), S);
getObjCEncodingForType(PType, S);
- S += llvm::utostr(ParmOffset);
+ S += charUnitsToString(ParmOffset);
ParmOffset += getObjCEncodingTypeSize(PType);
}
}
diff --git a/lib/AST/AttrImpl.cpp b/lib/AST/AttrImpl.cpp
new file mode 100644
index 0000000..02c70b6
--- /dev/null
+++ b/lib/AST/AttrImpl.cpp
@@ -0,0 +1,143 @@
+//===--- AttrImpl.cpp - Classes for representing attributes -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains out-of-line virtual methods for Attr classes.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "clang/AST/Attr.h"
+#include "clang/AST/ASTContext.h"
+using namespace clang;
+
+#define DEF_SIMPLE_ATTR_CLONE(ATTR) \
+ Attr *ATTR##Attr::clone(ASTContext &C) const { \
+ return ::new (C) ATTR##Attr; \
+ }
+
+// FIXME: Can we use variadic macro to define DEF_SIMPLE_ATTR_CLONE for
+// "non-simple" classes?
+
+DEF_SIMPLE_ATTR_CLONE(Packed)
+DEF_SIMPLE_ATTR_CLONE(AlwaysInline)
+DEF_SIMPLE_ATTR_CLONE(Malloc)
+DEF_SIMPLE_ATTR_CLONE(NoReturn)
+DEF_SIMPLE_ATTR_CLONE(AnalyzerNoReturn)
+DEF_SIMPLE_ATTR_CLONE(Deprecated)
+DEF_SIMPLE_ATTR_CLONE(Final)
+DEF_SIMPLE_ATTR_CLONE(Unavailable)
+DEF_SIMPLE_ATTR_CLONE(Unused)
+DEF_SIMPLE_ATTR_CLONE(Used)
+DEF_SIMPLE_ATTR_CLONE(Weak)
+DEF_SIMPLE_ATTR_CLONE(WeakImport)
+DEF_SIMPLE_ATTR_CLONE(NoThrow)
+DEF_SIMPLE_ATTR_CLONE(Const)
+DEF_SIMPLE_ATTR_CLONE(Pure)
+DEF_SIMPLE_ATTR_CLONE(FastCall)
+DEF_SIMPLE_ATTR_CLONE(StdCall)
+DEF_SIMPLE_ATTR_CLONE(CDecl)
+DEF_SIMPLE_ATTR_CLONE(TransparentUnion)
+DEF_SIMPLE_ATTR_CLONE(ObjCNSObject)
+DEF_SIMPLE_ATTR_CLONE(ObjCException)
+DEF_SIMPLE_ATTR_CLONE(NoDebug)
+DEF_SIMPLE_ATTR_CLONE(WarnUnusedResult)
+DEF_SIMPLE_ATTR_CLONE(NoInline)
+DEF_SIMPLE_ATTR_CLONE(CFReturnsRetained)
+DEF_SIMPLE_ATTR_CLONE(NSReturnsRetained)
+DEF_SIMPLE_ATTR_CLONE(BaseCheck)
+DEF_SIMPLE_ATTR_CLONE(Hiding)
+DEF_SIMPLE_ATTR_CLONE(Override)
+DEF_SIMPLE_ATTR_CLONE(DLLImport)
+DEF_SIMPLE_ATTR_CLONE(DLLExport)
+
+Attr* PragmaPackAttr::clone(ASTContext &C) const {
+ return ::new (C) PragmaPackAttr(Alignment);
+}
+
+Attr* AlignedAttr::clone(ASTContext &C) const {
+ return ::new (C) AlignedAttr(Alignment);
+}
+
+Attr* AnnotateAttr::clone(ASTContext &C) const {
+ return ::new (C) AnnotateAttr(Annotation);
+}
+
+Attr *AsmLabelAttr::clone(ASTContext &C) const {
+ return ::new (C) AsmLabelAttr(Label);
+}
+
+Attr *AliasAttr::clone(ASTContext &C) const {
+ return ::new (C) AliasAttr(Aliasee);
+}
+
+Attr *ConstructorAttr::clone(ASTContext &C) const {
+ return ::new (C) ConstructorAttr(priority);
+}
+
+Attr *DestructorAttr::clone(ASTContext &C) const {
+ return ::new (C) DestructorAttr(priority);
+}
+
+Attr *IBOutletAttr::clone(ASTContext &C) const {
+ return ::new (C) IBOutletAttr;
+}
+
+Attr *GNUInlineAttr::clone(ASTContext &C) const {
+ return ::new (C) GNUInlineAttr;
+}
+
+Attr *SectionAttr::clone(ASTContext &C) const {
+ return ::new (C) SectionAttr(Name);
+}
+
+Attr *NonNullAttr::clone(ASTContext &C) const {
+ return ::new (C) NonNullAttr(ArgNums, Size);
+}
+
+Attr *FormatAttr::clone(ASTContext &C) const {
+ return ::new (C) FormatAttr(Type, formatIdx, firstArg);
+}
+
+Attr *FormatArgAttr::clone(ASTContext &C) const {
+ return ::new (C) FormatArgAttr(formatIdx);
+}
+
+Attr *SentinelAttr::clone(ASTContext &C) const {
+ return ::new (C) SentinelAttr(sentinel, NullPos);
+}
+
+Attr *VisibilityAttr::clone(ASTContext &C) const {
+ return ::new (C) VisibilityAttr(VisibilityType);
+}
+
+Attr *OverloadableAttr::clone(ASTContext &C) const {
+ return ::new (C) OverloadableAttr;
+}
+
+Attr *BlocksAttr::clone(ASTContext &C) const {
+ return ::new (C) BlocksAttr(BlocksAttrType);
+}
+
+Attr *CleanupAttr::clone(ASTContext &C) const {
+ return ::new (C) CleanupAttr(FD);
+}
+
+Attr *RegparmAttr::clone(ASTContext &C) const {
+ return ::new (C) RegparmAttr(NumParams);
+}
+
+Attr *ReqdWorkGroupSizeAttr::clone(ASTContext &C) const {
+ return ::new (C) ReqdWorkGroupSizeAttr(X, Y, Z);
+}
+
+Attr *MSP430InterruptAttr::clone(ASTContext &C) const {
+ return ::new (C) MSP430InterruptAttr(Number);
+}
+
+
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index 5aecf87..dea96e7 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -4,6 +4,7 @@ add_clang_library(clangAST
APValue.cpp
ASTConsumer.cpp
ASTContext.cpp
+ AttrImpl.cpp
CXXInheritance.cpp
Decl.cpp
DeclBase.cpp
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index e112fa3..e77661a 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -957,7 +957,7 @@ bool FunctionDecl::isInlined() const {
/// "externally" visible to other translation units in the program.
///
/// In C99, inline definitions are not externally visible by default. However,
-/// if even one of the globa-scope declarations is marked "extern inline", the
+/// if even one of the global-scope declarations is marked "extern inline", the
/// inline definition becomes externally visible (C99 6.7.4p6).
///
/// In GNU89 mode, or if the gnu_inline attribute is attached to the function
@@ -1039,6 +1039,15 @@ OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
return OO_None;
}
+/// getLiteralIdentifier - The literal suffix identifier this function
+/// represents, if any.
+const IdentifierInfo *FunctionDecl::getLiteralIdentifier() const {
+ if (getDeclName().getNameKind() == DeclarationName::CXXLiteralOperatorName)
+ return getDeclName().getCXXLiteralIdentifier();
+ else
+ return 0;
+}
+
FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const {
if (MemberSpecializationInfo *Info = getMemberSpecializationInfo())
return cast<FunctionDecl>(Info->getInstantiatedFrom());
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index bbbb19a..1cce35c 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -144,6 +144,19 @@ CXXRecordDecl::setBases(ASTContext &C,
}
}
+/// Callback function for CXXRecordDecl::forallBases that acknowledges
+/// that it saw a base class.
+static bool SawBase(const CXXRecordDecl *, void *) {
+ return true;
+}
+
+bool CXXRecordDecl::hasAnyDependentBases() const {
+ if (!isDependentContext())
+ return false;
+
+ return !forallBases(SawBase, 0);
+}
+
bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
return getCopyConstructor(Context, Qualifiers::Const) != 0;
}
@@ -643,23 +656,15 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const {
return C.getPointerType(ClassTy);
}
-static bool MethodHasBody(const CXXMethodDecl *MD, const FunctionDecl *&fn) {
- // Simple case: function has a body
- if (MD->getBody(fn))
- return true;
-
- // Complex case: function is an instantiation of a function which has a
- // body, but the definition hasn't been instantiated.
- const FunctionDecl *PatternDecl = MD->getTemplateInstantiationPattern();
- if (PatternDecl && PatternDecl->getBody(fn))
- return true;
-
- return false;
-}
-
bool CXXMethodDecl::hasInlineBody() const {
+ // If this function is a template instantiation, look at the template from
+ // which it was instantiated.
+ const FunctionDecl *CheckFn = getTemplateInstantiationPattern();
+ if (!CheckFn)
+ CheckFn = this;
+
const FunctionDecl *fn;
- return MethodHasBody(this, fn) && !fn->isOutOfLine();
+ return CheckFn->getBody(fn) && !fn->isOutOfLine();
}
CXXBaseOrMemberInitializer::
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index 60c40e2..ff81073 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -56,9 +56,14 @@ public:
/// This identifier is stored here rather than directly in DeclarationName so as
/// to allow Objective-C selectors, which are about a million times more common,
/// to consume minimal memory.
-class CXXLiteralOperatorIdName : public DeclarationNameExtra {
+class CXXLiteralOperatorIdName
+ : public DeclarationNameExtra, public llvm::FoldingSetNode {
public:
IdentifierInfo *ID;
+
+ void Profile(llvm::FoldingSetNodeID &FSID) {
+ FSID.AddPointer(ID);
+ }
};
bool operator<(DeclarationName LHS, DeclarationName RHS) {
@@ -180,6 +185,11 @@ DeclarationName::NameKind DeclarationName::getNameKind() const {
return Identifier;
}
+bool DeclarationName::isDependentName() const {
+ QualType T = getCXXNameType();
+ return !T.isNull() && T->isDependentType();
+}
+
std::string DeclarationName::getAsString() const {
switch (getNameKind()) {
case Identifier:
@@ -353,6 +363,7 @@ void DeclarationName::dump() const {
DeclarationNameTable::DeclarationNameTable() {
CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
+ CXXLiteralOperatorNames = new llvm::FoldingSet<CXXLiteralOperatorIdName>;
// Initialize the overloaded operator names.
CXXOperatorNames = new CXXOperatorIdName[NUM_OVERLOADED_OPERATORS];
@@ -364,16 +375,30 @@ DeclarationNameTable::DeclarationNameTable() {
}
DeclarationNameTable::~DeclarationNameTable() {
- llvm::FoldingSet<CXXSpecialName> *set =
+ llvm::FoldingSet<CXXSpecialName> *SpecialNames =
static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
- llvm::FoldingSetIterator<CXXSpecialName> I = set->begin(), E = set->end();
+ llvm::FoldingSetIterator<CXXSpecialName>
+ SI = SpecialNames->begin(), SE = SpecialNames->end();
+
+ while (SI != SE) {
+ CXXSpecialName *n = &*SI++;
+ delete n;
+ }
- while (I != E) {
- CXXSpecialName *n = &*I++;
+
+ llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
+ = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
+ (CXXLiteralOperatorNames);
+ llvm::FoldingSetIterator<CXXLiteralOperatorIdName>
+ LI = LiteralNames->begin(), LE = LiteralNames->end();
+
+ while (LI != LE) {
+ CXXLiteralOperatorIdName *n = &*LI++;
delete n;
}
- delete set;
+ delete SpecialNames;
+ delete LiteralNames;
delete [] CXXOperatorNames;
}
@@ -428,9 +453,23 @@ DeclarationNameTable::getCXXOperatorName(OverloadedOperatorKind Op) {
DeclarationName
DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
+ llvm::FoldingSet<CXXLiteralOperatorIdName> *LiteralNames
+ = static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
+ (CXXLiteralOperatorNames);
+
+ llvm::FoldingSetNodeID ID;
+ ID.AddPointer(II);
+
+ void *InsertPos = 0;
+ if (CXXLiteralOperatorIdName *Name =
+ LiteralNames->FindNodeOrInsertPos(ID, InsertPos))
+ return DeclarationName (Name);
+
CXXLiteralOperatorIdName *LiteralName = new CXXLiteralOperatorIdName;
LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
LiteralName->ID = II;
+
+ LiteralNames->InsertNode(LiteralName, InsertPos);
return DeclarationName(LiteralName);
}
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 04a6abc..4c3046b 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -2154,7 +2154,8 @@ IdentifierInfo *DesignatedInitExpr::Designator::getFieldName() {
return getField()->getIdentifier();
}
-DesignatedInitExpr::DesignatedInitExpr(QualType Ty, unsigned NumDesignators,
+DesignatedInitExpr::DesignatedInitExpr(ASTContext &C, QualType Ty,
+ unsigned NumDesignators,
const Designator *Designators,
SourceLocation EqualOrColonLoc,
bool GNUSyntax,
@@ -2165,7 +2166,7 @@ DesignatedInitExpr::DesignatedInitExpr(QualType Ty, unsigned NumDesignators,
Init->isTypeDependent(), Init->isValueDependent()),
EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax),
NumDesignators(NumDesignators), NumSubExprs(NumIndexExprs + 1) {
- this->Designators = new Designator[NumDesignators];
+ this->Designators = new (C) Designator[NumDesignators];
// Record the initializer itself.
child_iterator Child = child_begin();
@@ -2210,7 +2211,7 @@ DesignatedInitExpr::Create(ASTContext &C, Designator *Designators,
bool UsesColonSyntax, Expr *Init) {
void *Mem = C.Allocate(sizeof(DesignatedInitExpr) +
sizeof(Stmt *) * (NumIndexExprs + 1), 8);
- return new (Mem) DesignatedInitExpr(C.VoidTy, NumDesignators, Designators,
+ return new (Mem) DesignatedInitExpr(C, C.VoidTy, NumDesignators, Designators,
ColonOrEqualLoc, UsesColonSyntax,
IndexExprs, NumIndexExprs, Init);
}
@@ -2222,12 +2223,12 @@ DesignatedInitExpr *DesignatedInitExpr::CreateEmpty(ASTContext &C,
return new (Mem) DesignatedInitExpr(NumIndexExprs + 1);
}
-void DesignatedInitExpr::setDesignators(const Designator *Desigs,
+void DesignatedInitExpr::setDesignators(ASTContext &C,
+ const Designator *Desigs,
unsigned NumDesigs) {
- if (Designators)
- delete [] Designators;
+ DestroyDesignators(C);
- Designators = new Designator[NumDesigs];
+ Designators = new (C) Designator[NumDesigs];
NumDesignators = NumDesigs;
for (unsigned I = 0; I != NumDesigs; ++I)
Designators[I] = Desigs[I];
@@ -2276,7 +2277,7 @@ Expr *DesignatedInitExpr::getArrayRangeEnd(const Designator& D) {
/// \brief Replaces the designator at index @p Idx with the series
/// of designators in [First, Last).
-void DesignatedInitExpr::ExpandDesignator(unsigned Idx,
+void DesignatedInitExpr::ExpandDesignator(ASTContext &C, unsigned Idx,
const Designator *First,
const Designator *Last) {
unsigned NumNewDesignators = Last - First;
@@ -2292,21 +2293,28 @@ void DesignatedInitExpr::ExpandDesignator(unsigned Idx,
}
Designator *NewDesignators
- = new Designator[NumDesignators - 1 + NumNewDesignators];
+ = new (C) Designator[NumDesignators - 1 + NumNewDesignators];
std::copy(Designators, Designators + Idx, NewDesignators);
std::copy(First, Last, NewDesignators + Idx);
std::copy(Designators + Idx + 1, Designators + NumDesignators,
NewDesignators + Idx + NumNewDesignators);
- delete [] Designators;
+ DestroyDesignators(C);
Designators = NewDesignators;
NumDesignators = NumDesignators - 1 + NumNewDesignators;
}
void DesignatedInitExpr::DoDestroy(ASTContext &C) {
- delete [] Designators;
+ DestroyDesignators(C);
Expr::DoDestroy(C);
}
+void DesignatedInitExpr::DestroyDesignators(ASTContext &C) {
+ for (unsigned I = 0; I != NumDesignators; ++I)
+ Designators[I].~Designator();
+ C.Deallocate(Designators);
+ Designators = 0;
+}
+
ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc,
Expr **exprs, unsigned nexprs,
SourceLocation rparenloc)
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 06afec7..dfff209 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -13,6 +13,7 @@
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/ASTDiagnostic.h"
@@ -69,11 +70,12 @@ static bool EvaluateComplex(const Expr *E, APValue &Result, EvalInfo &Info);
static bool EvalPointerValueAsBool(APValue& Value, bool& Result) {
// FIXME: Is this accurate for all kinds of bases? If not, what would
// the check look like?
- Result = Value.getLValueBase() || Value.getLValueOffset();
+ Result = Value.getLValueBase() || !Value.getLValueOffset().isZero();
return true;
}
-static bool HandleConversionToBool(Expr* E, bool& Result, EvalInfo &Info) {
+static bool HandleConversionToBool(const Expr* E, bool& Result,
+ EvalInfo &Info) {
if (E->getType()->isIntegralType()) {
APSInt IntResult;
if (!EvaluateInteger(E, IntResult, Info))
@@ -222,11 +224,11 @@ public:
APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
APValue VisitDeclRefExpr(DeclRefExpr *E);
- APValue VisitPredefinedExpr(PredefinedExpr *E) { return APValue(E, 0); }
+ APValue VisitPredefinedExpr(PredefinedExpr *E) { return APValue(E); }
APValue VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
APValue VisitMemberExpr(MemberExpr *E);
- APValue VisitStringLiteral(StringLiteral *E) { return APValue(E, 0); }
- APValue VisitObjCEncodeExpr(ObjCEncodeExpr *E) { return APValue(E, 0); }
+ APValue VisitStringLiteral(StringLiteral *E) { return APValue(E); }
+ APValue VisitObjCEncodeExpr(ObjCEncodeExpr *E) { return APValue(E); }
APValue VisitArraySubscriptExpr(ArraySubscriptExpr *E);
APValue VisitUnaryDeref(UnaryOperator *E);
APValue VisitUnaryExtension(const UnaryOperator *E)
@@ -254,12 +256,12 @@ static bool EvaluateLValue(const Expr* E, APValue& Result, EvalInfo &Info) {
APValue LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) {
if (isa<FunctionDecl>(E->getDecl())) {
- return APValue(E, 0);
+ return APValue(E);
} else if (VarDecl* VD = dyn_cast<VarDecl>(E->getDecl())) {
if (!Info.AnyLValue && !VD->hasGlobalStorage())
return APValue();
if (!VD->getType()->isReferenceType())
- return APValue(E, 0);
+ return APValue(E);
// FIXME: Check whether VD might be overridden!
const VarDecl *Def = 0;
if (const Expr *Init = VD->getDefinition(Def))
@@ -272,7 +274,7 @@ APValue LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) {
APValue LValueExprEvaluator::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
if (!Info.AnyLValue && !E->isFileScope())
return APValue();
- return APValue(E, 0);
+ return APValue(E);
}
APValue LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) {
@@ -309,7 +311,8 @@ APValue LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) {
}
result.setLValue(result.getLValueBase(),
- result.getLValueOffset() + RL.getFieldOffset(i) / 8);
+ result.getLValueOffset() +
+ CharUnits::fromQuantity(RL.getFieldOffset(i) / 8));
return result;
}
@@ -324,9 +327,9 @@ APValue LValueExprEvaluator::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
if (!EvaluateInteger(E->getIdx(), Index, Info))
return APValue();
- uint64_t ElementSize = Info.Ctx.getTypeSize(E->getType()) / 8;
+ CharUnits ElementSize = Info.Ctx.getTypeSizeInChars(E->getType());
- uint64_t Offset = Index.getSExtValue() * ElementSize;
+ CharUnits Offset = Index.getSExtValue() * ElementSize;
Result.setLValue(Result.getLValueBase(),
Result.getLValueOffset() + Offset);
return Result;
@@ -363,22 +366,22 @@ public:
{ return Visit(E->getSubExpr()); }
APValue VisitUnaryAddrOf(const UnaryOperator *E);
APValue VisitObjCStringLiteral(ObjCStringLiteral *E)
- { return APValue(E, 0); }
+ { return APValue(E); }
APValue VisitAddrLabelExpr(AddrLabelExpr *E)
- { return APValue(E, 0); }
+ { return APValue(E); }
APValue VisitCallExpr(CallExpr *E);
APValue VisitBlockExpr(BlockExpr *E) {
if (!E->hasBlockDeclRefExprs())
- return APValue(E, 0);
+ return APValue(E);
return APValue();
}
APValue VisitImplicitValueInitExpr(ImplicitValueInitExpr *E)
- { return APValue((Expr*)0, 0); }
+ { return APValue((Expr*)0); }
APValue VisitConditionalOperator(ConditionalOperator *E);
APValue VisitChooseExpr(ChooseExpr *E)
{ return Visit(E->getChosenSubExpr(Info.Ctx)); }
APValue VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E)
- { return APValue((Expr*)0, 0); }
+ { return APValue((Expr*)0); }
// FIXME: Missing: @protocol, @selector
};
} // end anonymous namespace
@@ -409,15 +412,15 @@ APValue PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
return APValue();
QualType PointeeType = PExp->getType()->getAs<PointerType>()->getPointeeType();
- uint64_t SizeOfPointee;
+ CharUnits SizeOfPointee;
// Explicitly handle GNU void* and function pointer arithmetic extensions.
if (PointeeType->isVoidType() || PointeeType->isFunctionType())
- SizeOfPointee = 1;
+ SizeOfPointee = CharUnits::One();
else
- SizeOfPointee = Info.Ctx.getTypeSize(PointeeType) / 8;
+ SizeOfPointee = Info.Ctx.getTypeSizeInChars(PointeeType);
- uint64_t Offset = ResultLValue.getLValueOffset();
+ CharUnits Offset = ResultLValue.getLValueOffset();
if (E->getOpcode() == BinaryOperator::Add)
Offset += AdditionalOffset.getLimitedValue() * SizeOfPointee;
@@ -459,7 +462,8 @@ APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
if (Result.isInt()) {
Result.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType()));
- return APValue(0, Result.getInt().getZExtValue());
+ return APValue(0,
+ CharUnits::fromQuantity(Result.getInt().getZExtValue()));
}
// Cast is of an lvalue, no need to change value.
@@ -481,7 +485,8 @@ APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
if (Result.isInt()) {
Result.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType()));
- return APValue(0, Result.getInt().getZExtValue());
+ return APValue(0,
+ CharUnits::fromQuantity(Result.getInt().getZExtValue()));
}
// Cast is of an lvalue, no need to change value.
@@ -502,7 +507,7 @@ APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
APValue PointerExprEvaluator::VisitCallExpr(CallExpr *E) {
if (E->isBuiltinCall(Info.Ctx) ==
Builtin::BI__builtin___CFStringMakeConstantString)
- return APValue(E, 0);
+ return APValue(E);
return APValue();
}
@@ -976,20 +981,20 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
&& VD->getType()->isObjectType()
&& !VD->getType()->isVariablyModifiedType()
&& !VD->getType()->isDependentType()) {
- uint64_t Size = Info.Ctx.getTypeSize(VD->getType()) / 8;
- uint64_t Offset = Base.Val.getLValueOffset();
- if (Offset <= Size)
- Size -= Base.Val.getLValueOffset();
+ CharUnits Size = Info.Ctx.getTypeSizeInChars(VD->getType());
+ CharUnits Offset = Base.Val.getLValueOffset();
+ if (!Offset.isNegative() && Offset <= Size)
+ Size -= Offset;
else
- Size = 0;
- return Success(Size, E);
+ Size = CharUnits::Zero();
+ return Success(Size.getQuantity(), E);
}
}
}
// TODO: Perhaps we should let LLVM lower this?
if (E->getArg(0)->HasSideEffects(Info.Ctx)) {
- if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() == 0)
+ if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() <= 1)
return Success(-1ULL, E);
return Success(0, E);
}
@@ -1151,7 +1156,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
if (LHSValue.getLValueBase()) {
if (!E->isEqualityOp())
return false;
- if (RHSValue.getLValueBase() || RHSValue.getLValueOffset())
+ if (RHSValue.getLValueBase() || !RHSValue.getLValueOffset().isZero())
return false;
bool bres;
if (!EvalPointerValueAsBool(LHSValue, bres))
@@ -1160,7 +1165,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
} else if (RHSValue.getLValueBase()) {
if (!E->isEqualityOp())
return false;
- if (LHSValue.getLValueBase() || LHSValue.getLValueOffset())
+ if (LHSValue.getLValueBase() || !LHSValue.getLValueOffset().isZero())
return false;
bool bres;
if (!EvalPointerValueAsBool(RHSValue, bres))
@@ -1172,11 +1177,13 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
const QualType Type = E->getLHS()->getType();
const QualType ElementType = Type->getAs<PointerType>()->getPointeeType();
- uint64_t D = LHSValue.getLValueOffset() - RHSValue.getLValueOffset();
+ CharUnits ElementSize = CharUnits::One();
if (!ElementType->isVoidType() && !ElementType->isFunctionType())
- D /= Info.Ctx.getTypeSize(ElementType) / 8;
+ ElementSize = Info.Ctx.getTypeSizeInChars(ElementType);
- return Success(D, E);
+ CharUnits Diff = LHSValue.getLValueOffset() -
+ RHSValue.getLValueOffset();
+ return Success(Diff / ElementSize, E);
}
bool Result;
if (E->getOpcode() == BinaryOperator::EQ) {
@@ -1204,21 +1211,23 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
// Handle cases like (unsigned long)&a + 4.
if (E->isAdditiveOp() && Result.isLValue() && RHSVal.isInt()) {
- uint64_t offset = Result.getLValueOffset();
+ CharUnits Offset = Result.getLValueOffset();
+ CharUnits AdditionalOffset = CharUnits::fromQuantity(
+ RHSVal.getInt().getZExtValue());
if (E->getOpcode() == BinaryOperator::Add)
- offset += RHSVal.getInt().getZExtValue();
+ Offset += AdditionalOffset;
else
- offset -= RHSVal.getInt().getZExtValue();
- Result = APValue(Result.getLValueBase(), offset);
+ Offset -= AdditionalOffset;
+ Result = APValue(Result.getLValueBase(), Offset);
return true;
}
// Handle cases like 4 + (unsigned long)&a
if (E->getOpcode() == BinaryOperator::Add &&
RHSVal.isLValue() && Result.isInt()) {
- uint64_t offset = RHSVal.getLValueOffset();
- offset += Result.getInt().getZExtValue();
- Result = APValue(RHSVal.getLValueBase(), offset);
+ CharUnits Offset = RHSVal.getLValueOffset();
+ Offset += CharUnits::fromQuantity(Result.getInt().getZExtValue());
+ Result = APValue(RHSVal.getLValueBase(), Offset);
return true;
}
@@ -1334,8 +1343,7 @@ bool IntExprEvaluator::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) {
return false;
// Get information about the size.
- unsigned BitWidth = Info.Ctx.getTypeSize(SrcTy);
- return Success(BitWidth / Info.Ctx.Target.getCharWidth(), E);
+ return Success(Info.Ctx.getTypeSizeInChars(SrcTy).getQuantity(), E);
}
bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
@@ -1349,7 +1357,7 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
return false;
if (LV.getLValueBase())
return false;
- return Success(LV.getLValueOffset(), E);
+ return Success(LV.getLValueOffset().getQuantity(), E);
}
if (E->getOpcode() == UnaryOperator::LNot) {
@@ -1432,7 +1440,8 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) {
return true;
}
- APSInt AsInt = Info.Ctx.MakeIntValue(LV.getLValueOffset(), SrcType);
+ APSInt AsInt = Info.Ctx.MakeIntValue(LV.getLValueOffset().getQuantity(),
+ SrcType);
return Success(HandleIntToIntCast(DestType, SrcType, AsInt, Info.Ctx), E);
}
@@ -1978,6 +1987,13 @@ bool Expr::EvaluateAsAny(EvalResult &Result, ASTContext &Ctx) const {
return true;
}
+bool Expr::EvaluateAsBooleanCondition(bool &Result, ASTContext &Ctx) const {
+ EvalResult Scratch;
+ EvalInfo Info(Ctx, Scratch);
+
+ return HandleConversionToBool(this, Result, Info);
+}
+
bool Expr::EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const {
EvalInfo Info(Ctx, Result);
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index c914f3f..cfd89ea 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -719,11 +719,6 @@ ASTRecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) {
// If a class isnt' polymorphic it doesn't have a key function.
if (!RD->isPolymorphic())
return 0;
-
- // A class template specialization or instantation does not have a key
- // function.
- if (RD->getTemplateSpecializationKind() != TSK_Undeclared)
- return 0;
// A class inside an anonymous namespace doesn't have a key function. (Or
// at least, there's no point to assigning a key function to such a class;
@@ -741,13 +736,13 @@ ASTRecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) {
if (MD->isPure())
continue;
- if (MD->isInlineSpecified())
- continue;
-
// Ignore implicit member functions, they are always marked as inline, but
// they don't have a body until they're defined.
if (MD->isImplicit())
continue;
+
+ if (MD->isInlineSpecified())
+ continue;
if (MD->hasInlineBody())
continue;
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 7c7aeb8..104e336 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -337,12 +337,12 @@ unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces,
//===----------------------------------------------------------------------===//
AsmStmt::AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile,
- unsigned numoutputs, unsigned numinputs,
+ bool msasm, unsigned numoutputs, unsigned numinputs,
std::string *names, StringLiteral **constraints,
Expr **exprs, StringLiteral *asmstr, unsigned numclobbers,
StringLiteral **clobbers, SourceLocation rparenloc)
: Stmt(AsmStmtClass), AsmLoc(asmloc), RParenLoc(rparenloc), AsmStr(asmstr)
- , IsSimple(issimple), IsVolatile(isvolatile)
+ , IsSimple(issimple), IsVolatile(isvolatile), MSAsm(msasm)
, NumOutputs(numoutputs), NumInputs(numinputs) {
for (unsigned i = 0, e = numinputs + numoutputs; i != e; i++) {
Names.push_back(names[i]);
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index a7e42af..bbb904d 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -739,9 +739,10 @@ void StmtPrinter::VisitCallExpr(CallExpr *Call) {
void StmtPrinter::VisitMemberExpr(MemberExpr *Node) {
// FIXME: Suppress printing implicit bases (like "this")
PrintExpr(Node->getBase());
+ if (FieldDecl *FD = dyn_cast<FieldDecl>(Node->getMemberDecl()))
+ if (FD->isAnonymousStructOrUnion())
+ return;
OS << (Node->isArrow() ? "->" : ".");
- // FIXME: Suppress printing references to unnamed objects
- // representing anonymous unions/structs
if (NestedNameSpecifier *Qualifier = Node->getQualifier())
Qualifier->print(OS, Policy);
@@ -1120,6 +1121,13 @@ void StmtPrinter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
}
void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) {
+ // FIXME. For now we just print a trivial constructor call expression,
+ // constructing its first argument object.
+ if (E->getNumArgs() == 1) {
+ CXXConstructorDecl *CD = E->getConstructor();
+ if (CD->isTrivial())
+ PrintExpr(E->getArg(0));
+ }
// Nothing to print.
}
diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp
index 3ccb7a9..0840c52 100644
--- a/lib/AST/TypeLoc.cpp
+++ b/lib/AST/TypeLoc.cpp
@@ -13,6 +13,7 @@
#include "llvm/Support/raw_ostream.h"
#include "clang/AST/TypeLocVisitor.h"
+#include "clang/AST/Expr.h"
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -123,3 +124,14 @@ bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
if (TL->getType().hasLocalQualifiers()) return false;
return TSTChecker().Visit(*TL);
}
+
+// Reimplemented to account for GNU/C++ extension
+// typeof unary-expression
+// where there are no parentheses.
+SourceRange TypeOfExprTypeLoc::getSourceRange() const {
+ if (getRParenLoc().isValid())
+ return SourceRange(getTypeofLoc(), getRParenLoc());
+ else
+ return SourceRange(getTypeofLoc(),
+ getUnderlyingExpr()->getSourceRange().getEnd());
+}
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 818657c..00b74bc 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -271,6 +271,10 @@ void TypePrinter::PrintFunctionProto(const FunctionProtoType *T,
S += ")";
+ if (T->getNoReturnAttr())
+ S += " __attribute__((noreturn))";
+
+
if (T->hasExceptionSpec()) {
S += " throw(";
if (T->hasAnyExceptionSpec())
@@ -287,10 +291,9 @@ void TypePrinter::PrintFunctionProto(const FunctionProtoType *T,
S += ")";
}
- if (T->getNoReturnAttr())
- S += " __attribute__((noreturn))";
- Print(T->getResultType(), S);
+ AppendTypeQualList(S, T->getTypeQuals());
+ Print(T->getResultType(), S);
}
void TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T,
OpenPOWER on IntegriCloud