2006-11-10 14:34:16 +08:00
|
|
|
//===--- ASTContext.cpp - Context to hold long-lived AST nodes ------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 03:59:25 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2006-11-10 14:34:16 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the ASTContext interface.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/AST/ASTContext.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "CXXABI.h"
|
2012-12-01 23:09:41 +08:00
|
|
|
#include "clang/AST/ASTMutationListener.h"
|
|
|
|
#include "clang/AST/Attr.h"
|
2009-12-22 22:23:30 +08:00
|
|
|
#include "clang/AST/CharUnits.h"
|
2012-12-01 23:09:41 +08:00
|
|
|
#include "clang/AST/Comment.h"
|
2012-08-09 08:03:17 +08:00
|
|
|
#include "clang/AST/CommentCommandTraits.h"
|
2008-08-08 04:55:28 +08:00
|
|
|
#include "clang/AST/DeclCXX.h"
|
2007-10-02 03:00:59 +08:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
2009-02-05 03:02:06 +08:00
|
|
|
#include "clang/AST/DeclTemplate.h"
|
2008-08-11 12:54:23 +08:00
|
|
|
#include "clang/AST/Expr.h"
|
2010-05-20 09:18:31 +08:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
2009-04-10 06:27:44 +08:00
|
|
|
#include "clang/AST/ExternalASTSource.h"
|
2011-01-14 02:57:25 +08:00
|
|
|
#include "clang/AST/Mangle.h"
|
2012-12-01 23:09:41 +08:00
|
|
|
#include "clang/AST/RecordLayout.h"
|
|
|
|
#include "clang/AST/TypeLoc.h"
|
2009-06-14 09:54:56 +08:00
|
|
|
#include "clang/Basic/Builtins.h"
|
2009-03-28 11:45:20 +08:00
|
|
|
#include "clang/Basic/SourceManager.h"
|
2007-05-21 07:50:58 +08:00
|
|
|
#include "clang/Basic/TargetInfo.h"
|
2009-10-24 17:57:09 +08:00
|
|
|
#include "llvm/ADT/SmallString.h"
|
2007-10-29 13:01:08 +08:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2012-12-01 23:09:41 +08:00
|
|
|
#include "llvm/Support/Capacity.h"
|
2009-01-18 14:42:49 +08:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2009-10-24 17:57:09 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2011-05-17 08:46:38 +08:00
|
|
|
#include <map>
|
2009-07-19 05:19:52 +08:00
|
|
|
|
2006-11-10 14:34:16 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
2010-07-03 08:47:00 +08:00
|
|
|
unsigned ASTContext::NumImplicitDefaultConstructors;
|
|
|
|
unsigned ASTContext::NumImplicitDefaultConstructorsDeclared;
|
2010-07-03 07:41:54 +08:00
|
|
|
unsigned ASTContext::NumImplicitCopyConstructors;
|
|
|
|
unsigned ASTContext::NumImplicitCopyConstructorsDeclared;
|
2011-05-26 04:50:04 +08:00
|
|
|
unsigned ASTContext::NumImplicitMoveConstructors;
|
|
|
|
unsigned ASTContext::NumImplicitMoveConstructorsDeclared;
|
2010-07-03 05:50:04 +08:00
|
|
|
unsigned ASTContext::NumImplicitCopyAssignmentOperators;
|
|
|
|
unsigned ASTContext::NumImplicitCopyAssignmentOperatorsDeclared;
|
2011-05-26 04:50:04 +08:00
|
|
|
unsigned ASTContext::NumImplicitMoveAssignmentOperators;
|
|
|
|
unsigned ASTContext::NumImplicitMoveAssignmentOperatorsDeclared;
|
2010-07-03 04:37:36 +08:00
|
|
|
unsigned ASTContext::NumImplicitDestructors;
|
|
|
|
unsigned ASTContext::NumImplicitDestructorsDeclared;
|
|
|
|
|
2007-04-28 05:51:21 +08:00
|
|
|
enum FloatingRank {
|
2011-10-15 07:23:15 +08:00
|
|
|
HalfRank, FloatRank, DoubleRank, LongDoubleRank
|
2007-04-28 05:51:21 +08:00
|
|
|
};
|
|
|
|
|
2012-07-12 05:38:39 +08:00
|
|
|
RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const {
|
2012-06-20 08:34:58 +08:00
|
|
|
if (!CommentsLoaded && ExternalSource) {
|
|
|
|
ExternalSource->ReadComments();
|
|
|
|
CommentsLoaded = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(D);
|
|
|
|
|
2012-06-29 00:19:39 +08:00
|
|
|
// User can not attach documentation to implicit declarations.
|
|
|
|
if (D->isImplicit())
|
|
|
|
return NULL;
|
|
|
|
|
2012-08-15 01:17:18 +08:00
|
|
|
// User can not attach documentation to implicit instantiations.
|
|
|
|
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
|
|
|
if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-21 06:36:31 +08:00
|
|
|
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
|
|
|
|
if (VD->isStaticDataMember() &&
|
|
|
|
VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) {
|
|
|
|
if (CRD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-01-28 05:18:39 +08:00
|
|
|
if (const ClassTemplateSpecializationDecl *CTSD =
|
|
|
|
dyn_cast<ClassTemplateSpecializationDecl>(D)) {
|
|
|
|
TemplateSpecializationKind TSK = CTSD->getSpecializationKind();
|
|
|
|
if (TSK == TSK_ImplicitInstantiation ||
|
|
|
|
TSK == TSK_Undeclared)
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-21 06:36:31 +08:00
|
|
|
if (const EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
|
|
|
|
if (ED->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-06-20 08:34:58 +08:00
|
|
|
// TODO: handle comments for function parameters properly.
|
|
|
|
if (isa<ParmVarDecl>(D))
|
|
|
|
return NULL;
|
|
|
|
|
2012-08-01 06:37:06 +08:00
|
|
|
// TODO: we could look up template parameter documentation in the template
|
|
|
|
// documentation.
|
|
|
|
if (isa<TemplateTypeParmDecl>(D) ||
|
|
|
|
isa<NonTypeTemplateParmDecl>(D) ||
|
|
|
|
isa<TemplateTemplateParmDecl>(D))
|
|
|
|
return NULL;
|
|
|
|
|
2012-07-07 02:19:34 +08:00
|
|
|
ArrayRef<RawComment *> RawComments = Comments.getComments();
|
2012-06-20 08:34:58 +08:00
|
|
|
|
|
|
|
// If there are no comments anywhere, we won't find anything.
|
|
|
|
if (RawComments.empty())
|
|
|
|
return NULL;
|
|
|
|
|
2012-07-13 09:06:46 +08:00
|
|
|
// Find declaration location.
|
|
|
|
// For Objective-C declarations we generally don't expect to have multiple
|
|
|
|
// declarators, thus use declaration starting location as the "declaration
|
|
|
|
// location".
|
|
|
|
// For all other declarations multiple declarators are used quite frequently,
|
|
|
|
// so we use the location of the identifier as the "declaration location".
|
|
|
|
SourceLocation DeclLoc;
|
|
|
|
if (isa<ObjCMethodDecl>(D) || isa<ObjCContainerDecl>(D) ||
|
2012-08-01 06:37:06 +08:00
|
|
|
isa<ObjCPropertyDecl>(D) ||
|
2012-08-03 04:49:51 +08:00
|
|
|
isa<RedeclarableTemplateDecl>(D) ||
|
|
|
|
isa<ClassTemplateSpecializationDecl>(D))
|
2012-07-13 09:06:46 +08:00
|
|
|
DeclLoc = D->getLocStart();
|
|
|
|
else
|
|
|
|
DeclLoc = D->getLocation();
|
|
|
|
|
2012-06-20 08:34:58 +08:00
|
|
|
// If the declaration doesn't map directly to a location in a file, we
|
|
|
|
// can't find the comment.
|
|
|
|
if (DeclLoc.isInvalid() || !DeclLoc.isFileID())
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
// Find the comment that occurs just after this declaration.
|
2012-07-18 06:01:09 +08:00
|
|
|
ArrayRef<RawComment *>::iterator Comment;
|
|
|
|
{
|
|
|
|
// When searching for comments during parsing, the comment we are looking
|
|
|
|
// for is usually among the last two comments we parsed -- check them
|
|
|
|
// first.
|
|
|
|
RawComment CommentAtDeclLoc(SourceMgr, SourceRange(DeclLoc));
|
|
|
|
BeforeThanCompare<RawComment> Compare(SourceMgr);
|
|
|
|
ArrayRef<RawComment *>::iterator MaybeBeforeDecl = RawComments.end() - 1;
|
|
|
|
bool Found = Compare(*MaybeBeforeDecl, &CommentAtDeclLoc);
|
|
|
|
if (!Found && RawComments.size() >= 2) {
|
|
|
|
MaybeBeforeDecl--;
|
|
|
|
Found = Compare(*MaybeBeforeDecl, &CommentAtDeclLoc);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Found) {
|
|
|
|
Comment = MaybeBeforeDecl + 1;
|
|
|
|
assert(Comment == std::lower_bound(RawComments.begin(), RawComments.end(),
|
|
|
|
&CommentAtDeclLoc, Compare));
|
|
|
|
} else {
|
|
|
|
// Slow path.
|
|
|
|
Comment = std::lower_bound(RawComments.begin(), RawComments.end(),
|
|
|
|
&CommentAtDeclLoc, Compare);
|
|
|
|
}
|
|
|
|
}
|
2012-06-20 08:34:58 +08:00
|
|
|
|
|
|
|
// Decompose the location for the declaration and find the beginning of the
|
|
|
|
// file buffer.
|
|
|
|
std::pair<FileID, unsigned> DeclLocDecomp = SourceMgr.getDecomposedLoc(DeclLoc);
|
|
|
|
|
|
|
|
// First check whether we have a trailing comment.
|
|
|
|
if (Comment != RawComments.end() &&
|
2012-07-07 02:19:34 +08:00
|
|
|
(*Comment)->isDocumentation() && (*Comment)->isTrailingComment() &&
|
2012-07-07 07:27:33 +08:00
|
|
|
(isa<FieldDecl>(D) || isa<EnumConstantDecl>(D) || isa<VarDecl>(D))) {
|
2012-06-20 08:34:58 +08:00
|
|
|
std::pair<FileID, unsigned> CommentBeginDecomp
|
2012-07-07 02:19:34 +08:00
|
|
|
= SourceMgr.getDecomposedLoc((*Comment)->getSourceRange().getBegin());
|
2012-06-20 08:34:58 +08:00
|
|
|
// Check that Doxygen trailing comment comes after the declaration, starts
|
|
|
|
// on the same line and in the same file as the declaration.
|
|
|
|
if (DeclLocDecomp.first == CommentBeginDecomp.first &&
|
|
|
|
SourceMgr.getLineNumber(DeclLocDecomp.first, DeclLocDecomp.second)
|
|
|
|
== SourceMgr.getLineNumber(CommentBeginDecomp.first,
|
|
|
|
CommentBeginDecomp.second)) {
|
2012-07-07 02:19:34 +08:00
|
|
|
return *Comment;
|
2012-06-20 08:34:58 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// The comment just after the declaration was not a trailing comment.
|
|
|
|
// Let's look at the previous comment.
|
|
|
|
if (Comment == RawComments.begin())
|
|
|
|
return NULL;
|
|
|
|
--Comment;
|
|
|
|
|
|
|
|
// Check that we actually have a non-member Doxygen comment.
|
2012-07-07 02:19:34 +08:00
|
|
|
if (!(*Comment)->isDocumentation() || (*Comment)->isTrailingComment())
|
2012-06-20 08:34:58 +08:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
// Decompose the end of the comment.
|
|
|
|
std::pair<FileID, unsigned> CommentEndDecomp
|
2012-07-07 02:19:34 +08:00
|
|
|
= SourceMgr.getDecomposedLoc((*Comment)->getSourceRange().getEnd());
|
2012-06-20 08:34:58 +08:00
|
|
|
|
|
|
|
// If the comment and the declaration aren't in the same file, then they
|
|
|
|
// aren't related.
|
|
|
|
if (DeclLocDecomp.first != CommentEndDecomp.first)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
// Get the corresponding buffer.
|
|
|
|
bool Invalid = false;
|
|
|
|
const char *Buffer = SourceMgr.getBufferData(DeclLocDecomp.first,
|
|
|
|
&Invalid).data();
|
|
|
|
if (Invalid)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
// Extract text between the comment and declaration.
|
|
|
|
StringRef Text(Buffer + CommentEndDecomp.second,
|
|
|
|
DeclLocDecomp.second - CommentEndDecomp.second);
|
|
|
|
|
2012-06-28 07:43:37 +08:00
|
|
|
// There should be no other declarations or preprocessor directives between
|
|
|
|
// comment and declaration.
|
2012-07-13 09:06:46 +08:00
|
|
|
if (Text.find_first_of(",;{}#@") != StringRef::npos)
|
2012-06-20 08:34:58 +08:00
|
|
|
return NULL;
|
|
|
|
|
2012-07-07 02:19:34 +08:00
|
|
|
return *Comment;
|
2012-06-20 08:34:58 +08:00
|
|
|
}
|
|
|
|
|
2012-08-15 01:17:18 +08:00
|
|
|
namespace {
|
|
|
|
/// If we have a 'templated' declaration for a template, adjust 'D' to
|
|
|
|
/// refer to the actual template.
|
2012-08-23 01:44:32 +08:00
|
|
|
/// If we have an implicit instantiation, adjust 'D' to refer to template.
|
2012-08-15 01:17:18 +08:00
|
|
|
const Decl *adjustDeclToTemplate(const Decl *D) {
|
2012-08-14 00:37:30 +08:00
|
|
|
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
2012-08-23 01:44:32 +08:00
|
|
|
// Is this function declaration part of a function template?
|
2012-08-14 00:37:30 +08:00
|
|
|
if (const FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate())
|
2012-08-23 01:44:32 +08:00
|
|
|
return FTD;
|
|
|
|
|
|
|
|
// Nothing to do if function is not an implicit instantiation.
|
|
|
|
if (FD->getTemplateSpecializationKind() != TSK_ImplicitInstantiation)
|
|
|
|
return D;
|
|
|
|
|
|
|
|
// Function is an implicit instantiation of a function template?
|
|
|
|
if (const FunctionTemplateDecl *FTD = FD->getPrimaryTemplate())
|
|
|
|
return FTD;
|
|
|
|
|
|
|
|
// Function is instantiated from a member definition of a class template?
|
|
|
|
if (const FunctionDecl *MemberDecl =
|
|
|
|
FD->getInstantiatedFromMemberFunction())
|
|
|
|
return MemberDecl;
|
|
|
|
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
|
|
|
|
// Static data member is instantiated from a member definition of a class
|
|
|
|
// template?
|
|
|
|
if (VD->isStaticDataMember())
|
|
|
|
if (const VarDecl *MemberDecl = VD->getInstantiatedFromStaticDataMember())
|
|
|
|
return MemberDecl;
|
|
|
|
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) {
|
|
|
|
// Is this class declaration part of a class template?
|
|
|
|
if (const ClassTemplateDecl *CTD = CRD->getDescribedClassTemplate())
|
|
|
|
return CTD;
|
|
|
|
|
|
|
|
// Class is an implicit instantiation of a class template or partial
|
|
|
|
// specialization?
|
|
|
|
if (const ClassTemplateSpecializationDecl *CTSD =
|
|
|
|
dyn_cast<ClassTemplateSpecializationDecl>(CRD)) {
|
|
|
|
if (CTSD->getSpecializationKind() != TSK_ImplicitInstantiation)
|
|
|
|
return D;
|
|
|
|
llvm::PointerUnion<ClassTemplateDecl *,
|
|
|
|
ClassTemplatePartialSpecializationDecl *>
|
|
|
|
PU = CTSD->getSpecializedTemplateOrPartial();
|
|
|
|
return PU.is<ClassTemplateDecl*>() ?
|
|
|
|
static_cast<const Decl*>(PU.get<ClassTemplateDecl *>()) :
|
|
|
|
static_cast<const Decl*>(
|
|
|
|
PU.get<ClassTemplatePartialSpecializationDecl *>());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Class is instantiated from a member definition of a class template?
|
|
|
|
if (const MemberSpecializationInfo *Info =
|
|
|
|
CRD->getMemberSpecializationInfo())
|
|
|
|
return Info->getInstantiatedFrom();
|
|
|
|
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
if (const EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
|
|
|
|
// Enum is instantiated from a member definition of a class template?
|
|
|
|
if (const EnumDecl *MemberDecl = ED->getInstantiatedFromMemberEnum())
|
|
|
|
return MemberDecl;
|
|
|
|
|
|
|
|
return D;
|
2012-08-14 00:37:30 +08:00
|
|
|
}
|
2012-08-23 01:44:32 +08:00
|
|
|
// FIXME: Adjust alias templates?
|
2012-08-15 01:17:18 +08:00
|
|
|
return D;
|
|
|
|
}
|
|
|
|
} // unnamed namespace
|
|
|
|
|
2012-08-17 02:19:43 +08:00
|
|
|
const RawComment *ASTContext::getRawCommentForAnyRedecl(
|
|
|
|
const Decl *D,
|
|
|
|
const Decl **OriginalDecl) const {
|
2012-08-15 01:17:18 +08:00
|
|
|
D = adjustDeclToTemplate(D);
|
2012-08-14 00:37:30 +08:00
|
|
|
|
2012-08-11 08:51:43 +08:00
|
|
|
// Check whether we have cached a comment for this declaration already.
|
|
|
|
{
|
|
|
|
llvm::DenseMap<const Decl *, RawCommentAndCacheFlags>::iterator Pos =
|
|
|
|
RedeclComments.find(D);
|
|
|
|
if (Pos != RedeclComments.end()) {
|
|
|
|
const RawCommentAndCacheFlags &Raw = Pos->second;
|
2012-08-17 02:19:43 +08:00
|
|
|
if (Raw.getKind() != RawCommentAndCacheFlags::NoCommentInDecl) {
|
|
|
|
if (OriginalDecl)
|
|
|
|
*OriginalDecl = Raw.getOriginalDecl();
|
2012-08-11 08:51:43 +08:00
|
|
|
return Raw.getRaw();
|
2012-08-17 02:19:43 +08:00
|
|
|
}
|
2012-08-11 08:51:43 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Search for comments attached to declarations in the redeclaration chain.
|
|
|
|
const RawComment *RC = NULL;
|
2012-08-17 02:19:43 +08:00
|
|
|
const Decl *OriginalDeclForRC = NULL;
|
2012-08-11 08:51:43 +08:00
|
|
|
for (Decl::redecl_iterator I = D->redecls_begin(),
|
|
|
|
E = D->redecls_end();
|
|
|
|
I != E; ++I) {
|
|
|
|
llvm::DenseMap<const Decl *, RawCommentAndCacheFlags>::iterator Pos =
|
|
|
|
RedeclComments.find(*I);
|
|
|
|
if (Pos != RedeclComments.end()) {
|
|
|
|
const RawCommentAndCacheFlags &Raw = Pos->second;
|
|
|
|
if (Raw.getKind() != RawCommentAndCacheFlags::NoCommentInDecl) {
|
|
|
|
RC = Raw.getRaw();
|
2012-08-17 02:19:43 +08:00
|
|
|
OriginalDeclForRC = Raw.getOriginalDecl();
|
2012-08-11 08:51:43 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
RC = getRawCommentForDeclNoCache(*I);
|
2012-08-17 02:19:43 +08:00
|
|
|
OriginalDeclForRC = *I;
|
2012-08-11 08:51:43 +08:00
|
|
|
RawCommentAndCacheFlags Raw;
|
|
|
|
if (RC) {
|
|
|
|
Raw.setRaw(RC);
|
|
|
|
Raw.setKind(RawCommentAndCacheFlags::FromDecl);
|
|
|
|
} else
|
|
|
|
Raw.setKind(RawCommentAndCacheFlags::NoCommentInDecl);
|
2012-08-17 02:19:43 +08:00
|
|
|
Raw.setOriginalDecl(*I);
|
2012-08-11 08:51:43 +08:00
|
|
|
RedeclComments[*I] = Raw;
|
|
|
|
if (RC)
|
|
|
|
break;
|
|
|
|
}
|
2012-07-06 08:28:32 +08:00
|
|
|
}
|
2012-06-20 08:34:58 +08:00
|
|
|
|
2012-06-29 00:25:36 +08:00
|
|
|
// If we found a comment, it should be a documentation comment.
|
|
|
|
assert(!RC || RC->isDocumentation());
|
2012-08-11 08:51:43 +08:00
|
|
|
|
2012-08-17 02:19:43 +08:00
|
|
|
if (OriginalDecl)
|
|
|
|
*OriginalDecl = OriginalDeclForRC;
|
|
|
|
|
2012-08-11 08:51:43 +08:00
|
|
|
// Update cache for every declaration in the redeclaration chain.
|
|
|
|
RawCommentAndCacheFlags Raw;
|
|
|
|
Raw.setRaw(RC);
|
|
|
|
Raw.setKind(RawCommentAndCacheFlags::FromRedecl);
|
2012-08-17 02:19:43 +08:00
|
|
|
Raw.setOriginalDecl(OriginalDeclForRC);
|
2012-08-11 08:51:43 +08:00
|
|
|
|
|
|
|
for (Decl::redecl_iterator I = D->redecls_begin(),
|
|
|
|
E = D->redecls_end();
|
|
|
|
I != E; ++I) {
|
|
|
|
RawCommentAndCacheFlags &R = RedeclComments[*I];
|
|
|
|
if (R.getKind() == RawCommentAndCacheFlags::NoCommentInDecl)
|
|
|
|
R = Raw;
|
|
|
|
}
|
|
|
|
|
2012-06-20 08:34:58 +08:00
|
|
|
return RC;
|
|
|
|
}
|
|
|
|
|
2012-10-11 02:34:52 +08:00
|
|
|
static void addRedeclaredMethods(const ObjCMethodDecl *ObjCMethod,
|
|
|
|
SmallVectorImpl<const NamedDecl *> &Redeclared) {
|
|
|
|
const DeclContext *DC = ObjCMethod->getDeclContext();
|
|
|
|
if (const ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(DC)) {
|
|
|
|
const ObjCInterfaceDecl *ID = IMD->getClassInterface();
|
|
|
|
if (!ID)
|
|
|
|
return;
|
|
|
|
// Add redeclared method here.
|
2013-01-17 07:00:23 +08:00
|
|
|
for (ObjCInterfaceDecl::known_extensions_iterator
|
|
|
|
Ext = ID->known_extensions_begin(),
|
|
|
|
ExtEnd = ID->known_extensions_end();
|
|
|
|
Ext != ExtEnd; ++Ext) {
|
2012-10-11 02:34:52 +08:00
|
|
|
if (ObjCMethodDecl *RedeclaredMethod =
|
2013-01-17 07:00:23 +08:00
|
|
|
Ext->getMethod(ObjCMethod->getSelector(),
|
2012-10-11 02:34:52 +08:00
|
|
|
ObjCMethod->isInstanceMethod()))
|
|
|
|
Redeclared.push_back(RedeclaredMethod);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-12 07:52:50 +08:00
|
|
|
comments::FullComment *ASTContext::cloneFullComment(comments::FullComment *FC,
|
|
|
|
const Decl *D) const {
|
|
|
|
comments::DeclInfo *ThisDeclInfo = new (*this) comments::DeclInfo;
|
|
|
|
ThisDeclInfo->CommentDecl = D;
|
|
|
|
ThisDeclInfo->IsFilled = false;
|
|
|
|
ThisDeclInfo->fill();
|
|
|
|
ThisDeclInfo->CommentDecl = FC->getDecl();
|
|
|
|
comments::FullComment *CFC =
|
|
|
|
new (*this) comments::FullComment(FC->getBlocks(),
|
|
|
|
ThisDeclInfo);
|
|
|
|
return CFC;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-09-29 19:40:46 +08:00
|
|
|
comments::FullComment *ASTContext::getCommentForDecl(
|
|
|
|
const Decl *D,
|
|
|
|
const Preprocessor *PP) const {
|
2012-08-15 01:17:18 +08:00
|
|
|
D = adjustDeclToTemplate(D);
|
2012-10-11 02:34:52 +08:00
|
|
|
|
2012-08-15 01:17:18 +08:00
|
|
|
const Decl *Canonical = D->getCanonicalDecl();
|
|
|
|
llvm::DenseMap<const Decl *, comments::FullComment *>::iterator Pos =
|
|
|
|
ParsedComments.find(Canonical);
|
2012-10-11 02:34:52 +08:00
|
|
|
|
|
|
|
if (Pos != ParsedComments.end()) {
|
2012-10-12 07:52:50 +08:00
|
|
|
if (Canonical != D) {
|
2012-10-11 02:34:52 +08:00
|
|
|
comments::FullComment *FC = Pos->second;
|
2012-10-12 07:52:50 +08:00
|
|
|
comments::FullComment *CFC = cloneFullComment(FC, D);
|
2012-10-11 02:34:52 +08:00
|
|
|
return CFC;
|
|
|
|
}
|
2012-08-15 01:17:18 +08:00
|
|
|
return Pos->second;
|
2012-10-11 02:34:52 +08:00
|
|
|
}
|
|
|
|
|
2012-08-17 02:19:43 +08:00
|
|
|
const Decl *OriginalDecl;
|
2012-10-11 02:34:52 +08:00
|
|
|
|
2012-08-17 02:19:43 +08:00
|
|
|
const RawComment *RC = getRawCommentForAnyRedecl(D, &OriginalDecl);
|
2012-10-11 02:34:52 +08:00
|
|
|
if (!RC) {
|
|
|
|
if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) {
|
2012-11-03 22:24:57 +08:00
|
|
|
SmallVector<const NamedDecl*, 8> Overridden;
|
2013-01-12 08:28:34 +08:00
|
|
|
const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D);
|
2013-01-26 07:08:39 +08:00
|
|
|
if (OMD && OMD->isPropertyAccessor())
|
|
|
|
if (const ObjCPropertyDecl *PDecl = OMD->findPropertyDecl())
|
|
|
|
if (comments::FullComment *FC = getCommentForDecl(PDecl, PP))
|
|
|
|
return cloneFullComment(FC, D);
|
2013-01-12 08:28:34 +08:00
|
|
|
if (OMD)
|
2012-11-03 22:24:57 +08:00
|
|
|
addRedeclaredMethods(OMD, Overridden);
|
|
|
|
getOverriddenMethods(dyn_cast<NamedDecl>(D), Overridden);
|
2013-01-26 07:08:39 +08:00
|
|
|
for (unsigned i = 0, e = Overridden.size(); i < e; i++)
|
|
|
|
if (comments::FullComment *FC = getCommentForDecl(Overridden[i], PP))
|
|
|
|
return cloneFullComment(FC, D);
|
2012-10-11 02:34:52 +08:00
|
|
|
}
|
2013-01-26 06:48:32 +08:00
|
|
|
else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
|
2013-01-28 05:18:39 +08:00
|
|
|
// Attach any tag type's documentation to its typedef if latter
|
2013-01-26 07:08:39 +08:00
|
|
|
// does not have one of its own.
|
2013-01-26 06:48:32 +08:00
|
|
|
QualType QT = TD->getUnderlyingType();
|
2013-01-28 05:18:39 +08:00
|
|
|
if (const TagType *TT = QT->getAs<TagType>())
|
|
|
|
if (const Decl *TD = TT->getDecl())
|
|
|
|
if (comments::FullComment *FC = getCommentForDecl(TD, PP))
|
2013-01-26 07:08:39 +08:00
|
|
|
return cloneFullComment(FC, D);
|
2013-01-26 06:48:32 +08:00
|
|
|
}
|
2012-07-06 08:28:32 +08:00
|
|
|
return NULL;
|
2012-10-11 02:34:52 +08:00
|
|
|
}
|
|
|
|
|
2012-08-23 02:12:19 +08:00
|
|
|
// If the RawComment was attached to other redeclaration of this Decl, we
|
|
|
|
// should parse the comment in context of that other Decl. This is important
|
|
|
|
// because comments can contain references to parameter names which can be
|
|
|
|
// different across redeclarations.
|
2012-08-17 02:19:43 +08:00
|
|
|
if (D != OriginalDecl)
|
2012-09-29 19:40:46 +08:00
|
|
|
return getCommentForDecl(OriginalDecl, PP);
|
2012-08-17 02:19:43 +08:00
|
|
|
|
2012-09-29 19:40:46 +08:00
|
|
|
comments::FullComment *FC = RC->parse(*this, PP, D);
|
2012-08-15 01:17:18 +08:00
|
|
|
ParsedComments[Canonical] = FC;
|
|
|
|
return FC;
|
2012-07-06 08:28:32 +08:00
|
|
|
}
|
|
|
|
|
2010-06-17 05:09:37 +08:00
|
|
|
void
|
|
|
|
ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID,
|
|
|
|
TemplateTemplateParmDecl *Parm) {
|
|
|
|
ID.AddInteger(Parm->getDepth());
|
|
|
|
ID.AddInteger(Parm->getPosition());
|
2011-01-05 23:48:55 +08:00
|
|
|
ID.AddBoolean(Parm->isParameterPack());
|
2010-06-17 05:09:37 +08:00
|
|
|
|
|
|
|
TemplateParameterList *Params = Parm->getTemplateParameters();
|
|
|
|
ID.AddInteger(Params->size());
|
|
|
|
for (TemplateParameterList::const_iterator P = Params->begin(),
|
|
|
|
PEnd = Params->end();
|
|
|
|
P != PEnd; ++P) {
|
|
|
|
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
|
|
|
|
ID.AddInteger(0);
|
|
|
|
ID.AddBoolean(TTP->isParameterPack());
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
|
|
|
|
ID.AddInteger(1);
|
2011-01-05 23:48:55 +08:00
|
|
|
ID.AddBoolean(NTTP->isParameterPack());
|
2012-03-07 09:09:33 +08:00
|
|
|
ID.AddPointer(NTTP->getType().getCanonicalType().getAsOpaquePtr());
|
2011-01-20 04:10:05 +08:00
|
|
|
if (NTTP->isExpandedParameterPack()) {
|
|
|
|
ID.AddBoolean(true);
|
|
|
|
ID.AddInteger(NTTP->getNumExpansionTypes());
|
2012-03-07 09:09:33 +08:00
|
|
|
for (unsigned I = 0, N = NTTP->getNumExpansionTypes(); I != N; ++I) {
|
|
|
|
QualType T = NTTP->getExpansionType(I);
|
|
|
|
ID.AddPointer(T.getCanonicalType().getAsOpaquePtr());
|
|
|
|
}
|
2011-01-20 04:10:05 +08:00
|
|
|
} else
|
|
|
|
ID.AddBoolean(false);
|
2010-06-17 05:09:37 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
|
|
|
|
ID.AddInteger(2);
|
|
|
|
Profile(ID, TTP);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateTemplateParmDecl *
|
|
|
|
ASTContext::getCanonicalTemplateTemplateParmDecl(
|
2011-01-12 17:06:06 +08:00
|
|
|
TemplateTemplateParmDecl *TTP) const {
|
2010-06-17 05:09:37 +08:00
|
|
|
// Check if we already have a canonical template template parameter.
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
CanonicalTemplateTemplateParm::Profile(ID, TTP);
|
|
|
|
void *InsertPos = 0;
|
|
|
|
CanonicalTemplateTemplateParm *Canonical
|
|
|
|
= CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
if (Canonical)
|
|
|
|
return Canonical->getParam();
|
|
|
|
|
|
|
|
// Build a canonical template parameter list.
|
|
|
|
TemplateParameterList *Params = TTP->getTemplateParameters();
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<NamedDecl *, 4> CanonParams;
|
2010-06-17 05:09:37 +08:00
|
|
|
CanonParams.reserve(Params->size());
|
|
|
|
for (TemplateParameterList::const_iterator P = Params->begin(),
|
|
|
|
PEnd = Params->end();
|
|
|
|
P != PEnd; ++P) {
|
|
|
|
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P))
|
|
|
|
CanonParams.push_back(
|
|
|
|
TemplateTypeParmDecl::Create(*this, getTranslationUnitDecl(),
|
2011-03-06 23:48:19 +08:00
|
|
|
SourceLocation(),
|
|
|
|
SourceLocation(),
|
|
|
|
TTP->getDepth(),
|
2010-06-17 05:09:37 +08:00
|
|
|
TTP->getIndex(), 0, false,
|
|
|
|
TTP->isParameterPack()));
|
|
|
|
else if (NonTypeTemplateParmDecl *NTTP
|
2011-01-20 04:10:05 +08:00
|
|
|
= dyn_cast<NonTypeTemplateParmDecl>(*P)) {
|
|
|
|
QualType T = getCanonicalType(NTTP->getType());
|
|
|
|
TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(T);
|
|
|
|
NonTypeTemplateParmDecl *Param;
|
|
|
|
if (NTTP->isExpandedParameterPack()) {
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<QualType, 2> ExpandedTypes;
|
|
|
|
SmallVector<TypeSourceInfo *, 2> ExpandedTInfos;
|
2011-01-20 04:10:05 +08:00
|
|
|
for (unsigned I = 0, N = NTTP->getNumExpansionTypes(); I != N; ++I) {
|
|
|
|
ExpandedTypes.push_back(getCanonicalType(NTTP->getExpansionType(I)));
|
|
|
|
ExpandedTInfos.push_back(
|
|
|
|
getTrivialTypeSourceInfo(ExpandedTypes.back()));
|
|
|
|
}
|
|
|
|
|
|
|
|
Param = NonTypeTemplateParmDecl::Create(*this, getTranslationUnitDecl(),
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation(),
|
|
|
|
SourceLocation(),
|
2011-01-20 04:10:05 +08:00
|
|
|
NTTP->getDepth(),
|
|
|
|
NTTP->getPosition(), 0,
|
|
|
|
T,
|
|
|
|
TInfo,
|
|
|
|
ExpandedTypes.data(),
|
|
|
|
ExpandedTypes.size(),
|
|
|
|
ExpandedTInfos.data());
|
|
|
|
} else {
|
|
|
|
Param = NonTypeTemplateParmDecl::Create(*this, getTranslationUnitDecl(),
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation(),
|
|
|
|
SourceLocation(),
|
2011-01-20 04:10:05 +08:00
|
|
|
NTTP->getDepth(),
|
|
|
|
NTTP->getPosition(), 0,
|
|
|
|
T,
|
|
|
|
NTTP->isParameterPack(),
|
|
|
|
TInfo);
|
|
|
|
}
|
|
|
|
CanonParams.push_back(Param);
|
|
|
|
|
|
|
|
} else
|
2010-06-17 05:09:37 +08:00
|
|
|
CanonParams.push_back(getCanonicalTemplateTemplateParmDecl(
|
|
|
|
cast<TemplateTemplateParmDecl>(*P)));
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateTemplateParmDecl *CanonTTP
|
|
|
|
= TemplateTemplateParmDecl::Create(*this, getTranslationUnitDecl(),
|
|
|
|
SourceLocation(), TTP->getDepth(),
|
2011-01-05 23:48:55 +08:00
|
|
|
TTP->getPosition(),
|
|
|
|
TTP->isParameterPack(),
|
|
|
|
0,
|
2010-06-17 05:09:37 +08:00
|
|
|
TemplateParameterList::Create(*this, SourceLocation(),
|
|
|
|
SourceLocation(),
|
|
|
|
CanonParams.data(),
|
|
|
|
CanonParams.size(),
|
|
|
|
SourceLocation()));
|
|
|
|
|
|
|
|
// Get the new insert position for the node we care about.
|
|
|
|
Canonical = CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
assert(Canonical == 0 && "Shouldn't be in the map!");
|
|
|
|
(void)Canonical;
|
|
|
|
|
|
|
|
// Create the canonical template template parameter entry.
|
|
|
|
Canonical = new (*this) CanonicalTemplateTemplateParm(CanonTTP);
|
|
|
|
CanonTemplateTemplateParms.InsertNode(Canonical, InsertPos);
|
|
|
|
return CanonTTP;
|
|
|
|
}
|
|
|
|
|
2010-08-16 11:33:14 +08:00
|
|
|
CXXABI *ASTContext::createCXXABI(const TargetInfo &T) {
|
2010-08-22 06:46:04 +08:00
|
|
|
if (!LangOpts.CPlusPlus) return 0;
|
|
|
|
|
2013-01-26 06:30:49 +08:00
|
|
|
switch (T.getCXXABI().getKind()) {
|
|
|
|
case TargetCXXABI::GenericARM:
|
|
|
|
case TargetCXXABI::iOS:
|
2010-08-22 06:46:04 +08:00
|
|
|
return CreateARMCXXABI(*this);
|
2013-01-31 20:13:10 +08:00
|
|
|
case TargetCXXABI::GenericAArch64: // Same as Itanium at this level
|
2013-01-26 06:30:49 +08:00
|
|
|
case TargetCXXABI::GenericItanium:
|
2010-08-16 11:33:14 +08:00
|
|
|
return CreateItaniumCXXABI(*this);
|
2013-01-26 06:30:49 +08:00
|
|
|
case TargetCXXABI::Microsoft:
|
2010-08-19 10:18:14 +08:00
|
|
|
return CreateMicrosoftCXXABI(*this);
|
|
|
|
}
|
2012-01-17 14:56:22 +08:00
|
|
|
llvm_unreachable("Invalid CXXABI type!");
|
2010-08-16 11:33:14 +08:00
|
|
|
}
|
|
|
|
|
2011-09-02 08:18:52 +08:00
|
|
|
static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T,
|
2011-03-19 06:38:29 +08:00
|
|
|
const LangOptions &LOpts) {
|
|
|
|
if (LOpts.FakeAddressSpaceMap) {
|
|
|
|
// The fake address space map must have a distinct entry for each
|
|
|
|
// language-specific address space.
|
|
|
|
static const unsigned FakeAddrSpaceMap[] = {
|
|
|
|
1, // opencl_global
|
|
|
|
2, // opencl_local
|
2012-05-21 05:08:35 +08:00
|
|
|
3, // opencl_constant
|
|
|
|
4, // cuda_device
|
|
|
|
5, // cuda_constant
|
|
|
|
6 // cuda_shared
|
2011-03-19 06:38:29 +08:00
|
|
|
};
|
2011-09-02 08:18:52 +08:00
|
|
|
return &FakeAddrSpaceMap;
|
2011-03-19 06:38:29 +08:00
|
|
|
} else {
|
2011-09-02 08:18:52 +08:00
|
|
|
return &T.getAddressSpaceMap();
|
2011-03-19 06:38:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-02 04:23:19 +08:00
|
|
|
ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM,
|
2011-09-02 08:18:52 +08:00
|
|
|
const TargetInfo *t,
|
2008-08-11 12:54:23 +08:00
|
|
|
IdentifierTable &idents, SelectorTable &sels,
|
2009-06-14 09:54:56 +08:00
|
|
|
Builtin::Context &builtins,
|
2011-09-02 08:18:52 +08:00
|
|
|
unsigned size_reserve,
|
|
|
|
bool DelayInitialization)
|
|
|
|
: FunctionProtoTypes(this_()),
|
|
|
|
TemplateSpecializationTypes(this_()),
|
|
|
|
DependentTemplateSpecializationTypes(this_()),
|
|
|
|
SubstTemplateTemplateParmPacks(this_()),
|
|
|
|
GlobalNestedNameSpecifier(0),
|
|
|
|
Int128Decl(0), UInt128Decl(0),
|
2012-06-16 11:34:49 +08:00
|
|
|
BuiltinVaListDecl(0),
|
2012-01-18 02:09:05 +08:00
|
|
|
ObjCIdDecl(0), ObjCSelDecl(0), ObjCClassDecl(0), ObjCProtocolClassDecl(0),
|
2012-08-31 02:49:41 +08:00
|
|
|
BOOLDecl(0),
|
2011-09-08 09:46:34 +08:00
|
|
|
CFConstantStringTypeDecl(0), ObjCInstanceTypeDecl(0),
|
2011-09-02 08:18:52 +08:00
|
|
|
FILEDecl(0),
|
2011-11-14 05:51:09 +08:00
|
|
|
jmp_bufDecl(0), sigjmp_bufDecl(0), ucontext_tDecl(0),
|
|
|
|
BlockDescriptorType(0), BlockDescriptorExtendedType(0),
|
|
|
|
cudaConfigureCallDecl(0),
|
2011-12-03 08:30:27 +08:00
|
|
|
NullTypeSourceInfo(QualType()),
|
|
|
|
FirstLocalImport(), LastLocalImport(),
|
2011-09-02 08:18:52 +08:00
|
|
|
SourceMgr(SM), LangOpts(LOpts),
|
2011-09-28 06:38:19 +08:00
|
|
|
AddrSpaceMap(0), Target(t), PrintingPolicy(LOpts),
|
2011-09-02 08:18:52 +08:00
|
|
|
Idents(idents), Selectors(sels),
|
|
|
|
BuiltinInfo(builtins),
|
|
|
|
DeclarationNames(*this),
|
2011-09-28 06:38:19 +08:00
|
|
|
ExternalSource(0), Listener(0),
|
2012-06-20 08:34:58 +08:00
|
|
|
Comments(SM), CommentsLoaded(false),
|
2012-09-11 04:32:42 +08:00
|
|
|
CommentCommandTraits(BumpAlloc),
|
2011-09-02 08:18:52 +08:00
|
|
|
LastSDM(0, 0),
|
2013-01-05 02:45:40 +08:00
|
|
|
UniqueBlockByRefTypeID(0)
|
2011-09-02 08:18:52 +08:00
|
|
|
{
|
2009-09-09 23:08:12 +08:00
|
|
|
if (size_reserve > 0) Types.reserve(size_reserve);
|
2008-08-11 12:54:23 +08:00
|
|
|
TUDecl = TranslationUnitDecl::Create(*this);
|
2011-09-02 08:18:52 +08:00
|
|
|
|
|
|
|
if (!DelayInitialization) {
|
|
|
|
assert(t && "No target supplied for ASTContext initialization");
|
|
|
|
InitBuiltinTypes(*t);
|
|
|
|
}
|
2008-08-11 12:54:23 +08:00
|
|
|
}
|
|
|
|
|
2006-11-12 08:53:46 +08:00
|
|
|
ASTContext::~ASTContext() {
|
2010-02-11 15:12:28 +08:00
|
|
|
// Release the DenseMaps associated with DeclContext objects.
|
|
|
|
// FIXME: Is this the ideal solution?
|
|
|
|
ReleaseDeclContextMaps();
|
2010-03-03 07:58:15 +08:00
|
|
|
|
2010-07-26 01:53:33 +08:00
|
|
|
// Call all of the deallocation functions.
|
|
|
|
for (unsigned I = 0, N = Deallocations.size(); I != N; ++I)
|
|
|
|
Deallocations[I].first(Deallocations[I].second);
|
2010-05-24 02:26:36 +08:00
|
|
|
|
2010-06-09 07:00:58 +08:00
|
|
|
// ASTRecordLayout objects in ASTRecordLayouts must always be destroyed
|
2010-07-26 01:53:33 +08:00
|
|
|
// because they can contain DenseMaps.
|
|
|
|
for (llvm::DenseMap<const ObjCContainerDecl*,
|
|
|
|
const ASTRecordLayout*>::iterator
|
|
|
|
I = ObjCLayouts.begin(), E = ObjCLayouts.end(); I != E; )
|
|
|
|
// Increment in loop to prevent using deallocated memory.
|
|
|
|
if (ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second))
|
|
|
|
R->Destroy(*this);
|
|
|
|
|
2010-06-09 07:00:58 +08:00
|
|
|
for (llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>::iterator
|
|
|
|
I = ASTRecordLayouts.begin(), E = ASTRecordLayouts.end(); I != E; ) {
|
|
|
|
// Increment in loop to prevent using deallocated memory.
|
|
|
|
if (ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second))
|
|
|
|
R->Destroy(*this);
|
|
|
|
}
|
2010-08-31 00:49:28 +08:00
|
|
|
|
|
|
|
for (llvm::DenseMap<const Decl*, AttrVec*>::iterator A = DeclAttrs.begin(),
|
|
|
|
AEnd = DeclAttrs.end();
|
|
|
|
A != AEnd; ++A)
|
|
|
|
A->second->~AttrVec();
|
|
|
|
}
|
2009-03-27 07:50:42 +08:00
|
|
|
|
2010-05-24 02:26:36 +08:00
|
|
|
void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) {
|
|
|
|
Deallocations.push_back(std::make_pair(Callback, Data));
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
void
|
2012-02-05 10:12:40 +08:00
|
|
|
ASTContext::setExternalSource(OwningPtr<ExternalASTSource> &Source) {
|
2009-04-10 06:27:44 +08:00
|
|
|
ExternalSource.reset(Source.take());
|
|
|
|
}
|
|
|
|
|
2007-01-26 09:27:23 +08:00
|
|
|
void ASTContext::PrintStats() const {
|
2011-07-04 13:32:14 +08:00
|
|
|
llvm::errs() << "\n*** AST Context Stats:\n";
|
|
|
|
llvm::errs() << " " << Types.size() << " types total.\n";
|
2009-03-17 07:22:08 +08:00
|
|
|
|
2009-05-26 22:40:08 +08:00
|
|
|
unsigned counts[] = {
|
2009-09-09 23:08:12 +08:00
|
|
|
#define TYPE(Name, Parent) 0,
|
2009-05-26 22:40:08 +08:00
|
|
|
#define ABSTRACT_TYPE(Name, Parent)
|
|
|
|
#include "clang/AST/TypeNodes.def"
|
|
|
|
0 // Extra
|
|
|
|
};
|
2009-04-08 01:20:56 +08:00
|
|
|
|
2007-01-26 09:27:23 +08:00
|
|
|
for (unsigned i = 0, e = Types.size(); i != e; ++i) {
|
|
|
|
Type *T = Types[i];
|
2009-05-26 22:40:08 +08:00
|
|
|
counts[(unsigned)T->getTypeClass()]++;
|
2007-01-26 09:27:23 +08:00
|
|
|
}
|
|
|
|
|
2009-05-26 22:40:08 +08:00
|
|
|
unsigned Idx = 0;
|
|
|
|
unsigned TotalBytes = 0;
|
|
|
|
#define TYPE(Name, Parent) \
|
|
|
|
if (counts[Idx]) \
|
2011-07-04 13:32:14 +08:00
|
|
|
llvm::errs() << " " << counts[Idx] << " " << #Name \
|
|
|
|
<< " types\n"; \
|
2009-05-26 22:40:08 +08:00
|
|
|
TotalBytes += counts[Idx] * sizeof(Name##Type); \
|
|
|
|
++Idx;
|
|
|
|
#define ABSTRACT_TYPE(Name, Parent)
|
|
|
|
#include "clang/AST/TypeNodes.def"
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-07-04 13:32:14 +08:00
|
|
|
llvm::errs() << "Total bytes = " << TotalBytes << "\n";
|
|
|
|
|
2010-07-03 04:37:36 +08:00
|
|
|
// Implicit special member functions.
|
2011-07-04 13:32:14 +08:00
|
|
|
llvm::errs() << NumImplicitDefaultConstructorsDeclared << "/"
|
|
|
|
<< NumImplicitDefaultConstructors
|
|
|
|
<< " implicit default constructors created\n";
|
|
|
|
llvm::errs() << NumImplicitCopyConstructorsDeclared << "/"
|
|
|
|
<< NumImplicitCopyConstructors
|
|
|
|
<< " implicit copy constructors created\n";
|
2012-03-11 15:00:24 +08:00
|
|
|
if (getLangOpts().CPlusPlus)
|
2011-07-04 13:32:14 +08:00
|
|
|
llvm::errs() << NumImplicitMoveConstructorsDeclared << "/"
|
|
|
|
<< NumImplicitMoveConstructors
|
|
|
|
<< " implicit move constructors created\n";
|
|
|
|
llvm::errs() << NumImplicitCopyAssignmentOperatorsDeclared << "/"
|
|
|
|
<< NumImplicitCopyAssignmentOperators
|
|
|
|
<< " implicit copy assignment operators created\n";
|
2012-03-11 15:00:24 +08:00
|
|
|
if (getLangOpts().CPlusPlus)
|
2011-07-04 13:32:14 +08:00
|
|
|
llvm::errs() << NumImplicitMoveAssignmentOperatorsDeclared << "/"
|
|
|
|
<< NumImplicitMoveAssignmentOperators
|
|
|
|
<< " implicit move assignment operators created\n";
|
|
|
|
llvm::errs() << NumImplicitDestructorsDeclared << "/"
|
|
|
|
<< NumImplicitDestructors
|
|
|
|
<< " implicit destructors created\n";
|
|
|
|
|
2009-04-10 06:27:44 +08:00
|
|
|
if (ExternalSource.get()) {
|
2011-07-04 13:32:14 +08:00
|
|
|
llvm::errs() << "\n";
|
2009-04-10 06:27:44 +08:00
|
|
|
ExternalSource->PrintStats();
|
|
|
|
}
|
2011-07-04 13:32:14 +08:00
|
|
|
|
2010-07-26 01:53:33 +08:00
|
|
|
BumpAlloc.PrintStats();
|
2007-01-26 09:27:23 +08:00
|
|
|
}
|
|
|
|
|
2011-08-12 14:49:56 +08:00
|
|
|
TypedefDecl *ASTContext::getInt128Decl() const {
|
|
|
|
if (!Int128Decl) {
|
|
|
|
TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(Int128Ty);
|
|
|
|
Int128Decl = TypedefDecl::Create(const_cast<ASTContext &>(*this),
|
|
|
|
getTranslationUnitDecl(),
|
|
|
|
SourceLocation(),
|
|
|
|
SourceLocation(),
|
|
|
|
&Idents.get("__int128_t"),
|
|
|
|
TInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Int128Decl;
|
|
|
|
}
|
|
|
|
|
|
|
|
TypedefDecl *ASTContext::getUInt128Decl() const {
|
|
|
|
if (!UInt128Decl) {
|
|
|
|
TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(UnsignedInt128Ty);
|
|
|
|
UInt128Decl = TypedefDecl::Create(const_cast<ASTContext &>(*this),
|
|
|
|
getTranslationUnitDecl(),
|
|
|
|
SourceLocation(),
|
|
|
|
SourceLocation(),
|
|
|
|
&Idents.get("__uint128_t"),
|
|
|
|
TInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
return UInt128Decl;
|
|
|
|
}
|
2007-01-26 09:27:23 +08:00
|
|
|
|
2009-10-24 07:03:21 +08:00
|
|
|
void ASTContext::InitBuiltinType(CanQualType &R, BuiltinType::Kind K) {
|
2009-09-25 07:30:46 +08:00
|
|
|
BuiltinType *Ty = new (*this, TypeAlignment) BuiltinType(K);
|
2009-10-24 07:03:21 +08:00
|
|
|
R = CanQualType::CreateUnsafe(QualType(Ty, 0));
|
2009-09-25 07:30:46 +08:00
|
|
|
Types.push_back(Ty);
|
2006-11-12 08:53:46 +08:00
|
|
|
}
|
|
|
|
|
2011-09-02 08:18:52 +08:00
|
|
|
void ASTContext::InitBuiltinTypes(const TargetInfo &Target) {
|
|
|
|
assert((!this->Target || this->Target == &Target) &&
|
|
|
|
"Incorrect target reinitialization");
|
2006-11-12 08:37:36 +08:00
|
|
|
assert(VoidTy.isNull() && "Context reinitialized?");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-09-02 08:18:52 +08:00
|
|
|
this->Target = &Target;
|
|
|
|
|
|
|
|
ABI.reset(createCXXABI(Target));
|
|
|
|
AddrSpaceMap = getAddressSpaceMap(Target, LangOpts);
|
|
|
|
|
2006-11-12 08:37:36 +08:00
|
|
|
// C99 6.2.5p19.
|
2006-12-03 10:57:32 +08:00
|
|
|
InitBuiltinType(VoidTy, BuiltinType::Void);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2006-11-12 08:37:36 +08:00
|
|
|
// C99 6.2.5p2.
|
2006-12-03 10:57:32 +08:00
|
|
|
InitBuiltinType(BoolTy, BuiltinType::Bool);
|
2006-11-12 08:37:36 +08:00
|
|
|
// C99 6.2.5p3.
|
2009-06-05 15:05:05 +08:00
|
|
|
if (LangOpts.CharIsSigned)
|
2007-06-03 15:25:34 +08:00
|
|
|
InitBuiltinType(CharTy, BuiltinType::Char_S);
|
|
|
|
else
|
|
|
|
InitBuiltinType(CharTy, BuiltinType::Char_U);
|
2006-11-12 08:37:36 +08:00
|
|
|
// C99 6.2.5p4.
|
2006-12-03 10:57:32 +08:00
|
|
|
InitBuiltinType(SignedCharTy, BuiltinType::SChar);
|
|
|
|
InitBuiltinType(ShortTy, BuiltinType::Short);
|
|
|
|
InitBuiltinType(IntTy, BuiltinType::Int);
|
|
|
|
InitBuiltinType(LongTy, BuiltinType::Long);
|
|
|
|
InitBuiltinType(LongLongTy, BuiltinType::LongLong);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2006-11-12 08:37:36 +08:00
|
|
|
// C99 6.2.5p6.
|
2006-12-03 10:57:32 +08:00
|
|
|
InitBuiltinType(UnsignedCharTy, BuiltinType::UChar);
|
|
|
|
InitBuiltinType(UnsignedShortTy, BuiltinType::UShort);
|
|
|
|
InitBuiltinType(UnsignedIntTy, BuiltinType::UInt);
|
|
|
|
InitBuiltinType(UnsignedLongTy, BuiltinType::ULong);
|
|
|
|
InitBuiltinType(UnsignedLongLongTy, BuiltinType::ULongLong);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2006-11-12 08:37:36 +08:00
|
|
|
// C99 6.2.5p10.
|
2006-12-03 10:57:32 +08:00
|
|
|
InitBuiltinType(FloatTy, BuiltinType::Float);
|
|
|
|
InitBuiltinType(DoubleTy, BuiltinType::Double);
|
|
|
|
InitBuiltinType(LongDoubleTy, BuiltinType::LongDouble);
|
2008-08-10 00:51:54 +08:00
|
|
|
|
2009-04-30 10:43:43 +08:00
|
|
|
// GNU extension, 128-bit integers.
|
|
|
|
InitBuiltinType(Int128Ty, BuiltinType::Int128);
|
|
|
|
InitBuiltinType(UnsignedInt128Ty, BuiltinType::UInt128);
|
|
|
|
|
2012-09-09 18:13:32 +08:00
|
|
|
if (LangOpts.CPlusPlus && LangOpts.WChar) { // C++ 3.9.1p5
|
2011-05-01 03:24:24 +08:00
|
|
|
if (TargetInfo::isTypeSigned(Target.getWCharType()))
|
2010-12-26 07:25:43 +08:00
|
|
|
InitBuiltinType(WCharTy, BuiltinType::WChar_S);
|
|
|
|
else // -fshort-wchar makes wchar_t be unsigned.
|
|
|
|
InitBuiltinType(WCharTy, BuiltinType::WChar_U);
|
2012-09-09 18:13:32 +08:00
|
|
|
} else // C99 (or C++ using -fno-wchar)
|
2009-02-27 07:43:47 +08:00
|
|
|
WCharTy = getFromTargetType(Target.getWCharType());
|
2008-08-10 00:51:54 +08:00
|
|
|
|
2012-05-04 18:55:22 +08:00
|
|
|
WIntTy = getFromTargetType(Target.getWIntType());
|
|
|
|
|
2009-07-14 14:30:34 +08:00
|
|
|
if (LangOpts.CPlusPlus) // C++0x 3.9.1p5, extension for C++
|
|
|
|
InitBuiltinType(Char16Ty, BuiltinType::Char16);
|
|
|
|
else // C99
|
|
|
|
Char16Ty = getFromTargetType(Target.getChar16Type());
|
|
|
|
|
|
|
|
if (LangOpts.CPlusPlus) // C++0x 3.9.1p5, extension for C++
|
|
|
|
InitBuiltinType(Char32Ty, BuiltinType::Char32);
|
|
|
|
else // C99
|
|
|
|
Char32Ty = getFromTargetType(Target.getChar32Type());
|
|
|
|
|
2008-12-06 07:32:09 +08:00
|
|
|
// Placeholder type for type-dependent expressions whose type is
|
|
|
|
// completely unknown. No code should ever check a type against
|
|
|
|
// DependentTy and users should never see it; however, it is here to
|
|
|
|
// help diagnose failures to properly check for type-dependent
|
|
|
|
// expressions.
|
|
|
|
InitBuiltinType(DependentTy, BuiltinType::Dependent);
|
2008-10-22 00:13:35 +08:00
|
|
|
|
2010-10-12 08:20:44 +08:00
|
|
|
// Placeholder type for functions.
|
|
|
|
InitBuiltinType(OverloadTy, BuiltinType::Overload);
|
|
|
|
|
2011-04-27 04:42:42 +08:00
|
|
|
// Placeholder type for bound members.
|
|
|
|
InitBuiltinType(BoundMemberTy, BuiltinType::BoundMember);
|
|
|
|
|
2011-10-26 01:37:35 +08:00
|
|
|
// Placeholder type for pseudo-objects.
|
|
|
|
InitBuiltinType(PseudoObjectTy, BuiltinType::PseudoObject);
|
|
|
|
|
2011-04-07 16:22:57 +08:00
|
|
|
// "any" type; useful for debugger-like clients.
|
|
|
|
InitBuiltinType(UnknownAnyTy, BuiltinType::UnknownAny);
|
|
|
|
|
2011-10-18 02:09:15 +08:00
|
|
|
// Placeholder type for unbridged ARC casts.
|
|
|
|
InitBuiltinType(ARCUnbridgedCastTy, BuiltinType::ARCUnbridgedCast);
|
|
|
|
|
2012-08-31 08:14:07 +08:00
|
|
|
// Placeholder type for builtin functions.
|
|
|
|
InitBuiltinType(BuiltinFnTy, BuiltinType::BuiltinFn);
|
|
|
|
|
2006-11-12 08:37:36 +08:00
|
|
|
// C99 6.2.5p11.
|
2007-06-23 04:56:16 +08:00
|
|
|
FloatComplexTy = getComplexType(FloatTy);
|
|
|
|
DoubleComplexTy = getComplexType(DoubleTy);
|
|
|
|
LongDoubleComplexTy = getComplexType(LongDoubleTy);
|
2008-10-22 00:13:35 +08:00
|
|
|
|
2009-11-22 03:53:08 +08:00
|
|
|
// Builtin types for 'id', 'Class', and 'SEL'.
|
2009-07-16 02:40:39 +08:00
|
|
|
InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId);
|
|
|
|
InitBuiltinType(ObjCBuiltinClassTy, BuiltinType::ObjCClass);
|
2009-11-22 03:53:08 +08:00
|
|
|
InitBuiltinType(ObjCBuiltinSelTy, BuiltinType::ObjCSel);
|
2012-12-18 22:38:23 +08:00
|
|
|
|
|
|
|
if (LangOpts.OpenCL) {
|
|
|
|
InitBuiltinType(OCLImage1dTy, BuiltinType::OCLImage1d);
|
|
|
|
InitBuiltinType(OCLImage1dArrayTy, BuiltinType::OCLImage1dArray);
|
|
|
|
InitBuiltinType(OCLImage1dBufferTy, BuiltinType::OCLImage1dBuffer);
|
|
|
|
InitBuiltinType(OCLImage2dTy, BuiltinType::OCLImage2d);
|
|
|
|
InitBuiltinType(OCLImage2dArrayTy, BuiltinType::OCLImage2dArray);
|
|
|
|
InitBuiltinType(OCLImage3dTy, BuiltinType::OCLImage3d);
|
2013-01-20 20:31:11 +08:00
|
|
|
|
2013-02-07 18:55:47 +08:00
|
|
|
InitBuiltinType(OCLSamplerTy, BuiltinType::OCLSampler);
|
2013-01-20 20:31:11 +08:00
|
|
|
InitBuiltinType(OCLEventTy, BuiltinType::OCLEvent);
|
2012-12-18 22:38:23 +08:00
|
|
|
}
|
2012-03-07 04:05:56 +08:00
|
|
|
|
|
|
|
// Builtin type for __objc_yes and __objc_no
|
2012-04-17 05:03:30 +08:00
|
|
|
ObjCBuiltinBoolTy = (Target.useSignedCharForObjCBool() ?
|
|
|
|
SignedCharTy : BoolTy);
|
2012-03-07 04:05:56 +08:00
|
|
|
|
2008-01-08 03:49:32 +08:00
|
|
|
ObjCConstantStringType = QualType();
|
2013-01-05 02:45:40 +08:00
|
|
|
|
|
|
|
ObjCSuperType = QualType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-10-30 06:57:28 +08:00
|
|
|
// void * type
|
|
|
|
VoidPtrTy = getPointerType(VoidTy);
|
2009-05-11 02:38:11 +08:00
|
|
|
|
|
|
|
// nullptr type (C++0x 2.14.7)
|
|
|
|
InitBuiltinType(NullPtrTy, BuiltinType::NullPtr);
|
2011-10-15 07:23:15 +08:00
|
|
|
|
|
|
|
// half type (OpenCL 6.1.1.1) / ARM NEON __fp16
|
|
|
|
InitBuiltinType(HalfTy, BuiltinType::Half);
|
2012-07-01 23:57:25 +08:00
|
|
|
|
|
|
|
// Builtin type used to help define __builtin_va_list.
|
|
|
|
VaListTagTy = QualType();
|
2006-11-12 08:37:36 +08:00
|
|
|
}
|
|
|
|
|
2011-09-26 07:23:43 +08:00
|
|
|
DiagnosticsEngine &ASTContext::getDiagnostics() const {
|
2010-09-22 22:32:24 +08:00
|
|
|
return SourceMgr.getDiagnostics();
|
|
|
|
}
|
|
|
|
|
2010-08-31 00:49:28 +08:00
|
|
|
AttrVec& ASTContext::getDeclAttrs(const Decl *D) {
|
|
|
|
AttrVec *&Result = DeclAttrs[D];
|
|
|
|
if (!Result) {
|
|
|
|
void *Mem = Allocate(sizeof(AttrVec));
|
|
|
|
Result = new (Mem) AttrVec;
|
|
|
|
}
|
|
|
|
|
|
|
|
return *Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Erase the attributes corresponding to the given declaration.
|
|
|
|
void ASTContext::eraseDeclAttrs(const Decl *D) {
|
|
|
|
llvm::DenseMap<const Decl*, AttrVec*>::iterator Pos = DeclAttrs.find(D);
|
|
|
|
if (Pos != DeclAttrs.end()) {
|
|
|
|
Pos->second->~AttrVec();
|
|
|
|
DeclAttrs.erase(Pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-08 15:24:58 +08:00
|
|
|
MemberSpecializationInfo *
|
2009-10-15 04:14:33 +08:00
|
|
|
ASTContext::getInstantiatedFromStaticDataMember(const VarDecl *Var) {
|
2009-07-25 04:34:43 +08:00
|
|
|
assert(Var->isStaticDataMember() && "Not a static data member");
|
2009-10-15 04:14:33 +08:00
|
|
|
llvm::DenseMap<const VarDecl *, MemberSpecializationInfo *>::iterator Pos
|
2009-07-25 04:34:43 +08:00
|
|
|
= InstantiatedFromStaticDataMember.find(Var);
|
|
|
|
if (Pos == InstantiatedFromStaticDataMember.end())
|
|
|
|
return 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-25 04:34:43 +08:00
|
|
|
return Pos->second;
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
void
|
2009-10-08 15:24:58 +08:00
|
|
|
ASTContext::setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl,
|
2010-07-05 05:44:00 +08:00
|
|
|
TemplateSpecializationKind TSK,
|
|
|
|
SourceLocation PointOfInstantiation) {
|
2009-07-25 04:34:43 +08:00
|
|
|
assert(Inst->isStaticDataMember() && "Not a static data member");
|
|
|
|
assert(Tmpl->isStaticDataMember() && "Not a static data member");
|
|
|
|
assert(!InstantiatedFromStaticDataMember[Inst] &&
|
|
|
|
"Already noted what static data member was instantiated from");
|
2009-10-08 15:24:58 +08:00
|
|
|
InstantiatedFromStaticDataMember[Inst]
|
2010-07-05 05:44:00 +08:00
|
|
|
= new (*this) MemberSpecializationInfo(Tmpl, TSK, PointOfInstantiation);
|
2009-07-25 04:34:43 +08:00
|
|
|
}
|
|
|
|
|
2011-08-14 11:52:19 +08:00
|
|
|
FunctionDecl *ASTContext::getClassScopeSpecializationPattern(
|
|
|
|
const FunctionDecl *FD){
|
|
|
|
assert(FD && "Specialization is 0");
|
|
|
|
llvm::DenseMap<const FunctionDecl*, FunctionDecl *>::const_iterator Pos
|
2011-08-14 22:28:49 +08:00
|
|
|
= ClassScopeSpecializationPattern.find(FD);
|
|
|
|
if (Pos == ClassScopeSpecializationPattern.end())
|
2011-08-14 11:52:19 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
return Pos->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTContext::setClassScopeSpecializationPattern(FunctionDecl *FD,
|
|
|
|
FunctionDecl *Pattern) {
|
|
|
|
assert(FD && "Specialization is 0");
|
|
|
|
assert(Pattern && "Class scope specialization pattern is 0");
|
2011-08-14 22:28:49 +08:00
|
|
|
ClassScopeSpecializationPattern[FD] = Pattern;
|
2011-08-14 11:52:19 +08:00
|
|
|
}
|
|
|
|
|
2009-11-18 10:36:19 +08:00
|
|
|
NamedDecl *
|
2009-12-05 06:46:56 +08:00
|
|
|
ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) {
|
2009-11-18 10:36:19 +08:00
|
|
|
llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos
|
2009-12-05 06:46:56 +08:00
|
|
|
= InstantiatedFromUsingDecl.find(UUD);
|
|
|
|
if (Pos == InstantiatedFromUsingDecl.end())
|
2009-08-30 03:37:28 +08:00
|
|
|
return 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-30 03:37:28 +08:00
|
|
|
return Pos->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-12-05 06:46:56 +08:00
|
|
|
ASTContext::setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern) {
|
|
|
|
assert((isa<UsingDecl>(Pattern) ||
|
|
|
|
isa<UnresolvedUsingValueDecl>(Pattern) ||
|
|
|
|
isa<UnresolvedUsingTypenameDecl>(Pattern)) &&
|
|
|
|
"pattern decl is not a using decl");
|
|
|
|
assert(!InstantiatedFromUsingDecl[Inst] && "pattern already exists");
|
|
|
|
InstantiatedFromUsingDecl[Inst] = Pattern;
|
|
|
|
}
|
|
|
|
|
|
|
|
UsingShadowDecl *
|
|
|
|
ASTContext::getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst) {
|
|
|
|
llvm::DenseMap<UsingShadowDecl*, UsingShadowDecl*>::const_iterator Pos
|
|
|
|
= InstantiatedFromUsingShadowDecl.find(Inst);
|
|
|
|
if (Pos == InstantiatedFromUsingShadowDecl.end())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return Pos->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ASTContext::setInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst,
|
|
|
|
UsingShadowDecl *Pattern) {
|
|
|
|
assert(!InstantiatedFromUsingShadowDecl[Inst] && "pattern already exists");
|
|
|
|
InstantiatedFromUsingShadowDecl[Inst] = Pattern;
|
2009-08-30 03:37:28 +08:00
|
|
|
}
|
|
|
|
|
2009-09-01 12:26:58 +08:00
|
|
|
FieldDecl *ASTContext::getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field) {
|
|
|
|
llvm::DenseMap<FieldDecl *, FieldDecl *>::iterator Pos
|
|
|
|
= InstantiatedFromUnnamedFieldDecl.find(Field);
|
|
|
|
if (Pos == InstantiatedFromUnnamedFieldDecl.end())
|
|
|
|
return 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-01 12:26:58 +08:00
|
|
|
return Pos->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTContext::setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst,
|
|
|
|
FieldDecl *Tmpl) {
|
|
|
|
assert(!Inst->getDeclName() && "Instantiated field decl is not unnamed");
|
|
|
|
assert(!Tmpl->getDeclName() && "Template field decl is not unnamed");
|
|
|
|
assert(!InstantiatedFromUnnamedFieldDecl[Inst] &&
|
|
|
|
"Already noted what unnamed field was instantiated from");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-01 12:26:58 +08:00
|
|
|
InstantiatedFromUnnamedFieldDecl[Inst] = Tmpl;
|
|
|
|
}
|
|
|
|
|
2011-04-28 01:14:21 +08:00
|
|
|
bool ASTContext::ZeroBitfieldFollowsNonBitfield(const FieldDecl *FD,
|
|
|
|
const FieldDecl *LastFD) const {
|
|
|
|
return (FD->isBitField() && LastFD && !LastFD->isBitField() &&
|
2011-10-11 02:28:20 +08:00
|
|
|
FD->getBitWidthValue(*this) == 0);
|
2011-04-28 01:14:21 +08:00
|
|
|
}
|
|
|
|
|
2011-05-03 01:20:56 +08:00
|
|
|
bool ASTContext::ZeroBitfieldFollowsBitfield(const FieldDecl *FD,
|
|
|
|
const FieldDecl *LastFD) const {
|
|
|
|
return (FD->isBitField() && LastFD && LastFD->isBitField() &&
|
2011-10-11 02:28:20 +08:00
|
|
|
FD->getBitWidthValue(*this) == 0 &&
|
|
|
|
LastFD->getBitWidthValue(*this) != 0);
|
2011-05-03 01:20:56 +08:00
|
|
|
}
|
|
|
|
|
2011-05-05 02:51:37 +08:00
|
|
|
bool ASTContext::BitfieldFollowsBitfield(const FieldDecl *FD,
|
|
|
|
const FieldDecl *LastFD) const {
|
|
|
|
return (FD->isBitField() && LastFD && LastFD->isBitField() &&
|
2011-10-11 02:28:20 +08:00
|
|
|
FD->getBitWidthValue(*this) &&
|
|
|
|
LastFD->getBitWidthValue(*this));
|
2011-05-05 02:51:37 +08:00
|
|
|
}
|
|
|
|
|
2011-08-05 07:34:15 +08:00
|
|
|
bool ASTContext::NonBitfieldFollowsBitfield(const FieldDecl *FD,
|
2011-05-07 05:56:12 +08:00
|
|
|
const FieldDecl *LastFD) const {
|
|
|
|
return (!FD->isBitField() && LastFD && LastFD->isBitField() &&
|
2011-10-11 02:28:20 +08:00
|
|
|
LastFD->getBitWidthValue(*this));
|
2011-05-07 05:56:12 +08:00
|
|
|
}
|
|
|
|
|
2011-08-05 07:34:15 +08:00
|
|
|
bool ASTContext::BitfieldFollowsNonBitfield(const FieldDecl *FD,
|
2011-05-07 05:56:12 +08:00
|
|
|
const FieldDecl *LastFD) const {
|
|
|
|
return (FD->isBitField() && LastFD && !LastFD->isBitField() &&
|
2011-10-11 02:28:20 +08:00
|
|
|
FD->getBitWidthValue(*this));
|
2011-05-07 05:56:12 +08:00
|
|
|
}
|
|
|
|
|
2010-03-03 07:58:15 +08:00
|
|
|
ASTContext::overridden_cxx_method_iterator
|
|
|
|
ASTContext::overridden_methods_begin(const CXXMethodDecl *Method) const {
|
|
|
|
llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos
|
2012-10-09 09:23:45 +08:00
|
|
|
= OverriddenMethods.find(Method->getCanonicalDecl());
|
2010-03-03 07:58:15 +08:00
|
|
|
if (Pos == OverriddenMethods.end())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return Pos->second.begin();
|
|
|
|
}
|
|
|
|
|
|
|
|
ASTContext::overridden_cxx_method_iterator
|
|
|
|
ASTContext::overridden_methods_end(const CXXMethodDecl *Method) const {
|
|
|
|
llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos
|
2012-10-09 09:23:45 +08:00
|
|
|
= OverriddenMethods.find(Method->getCanonicalDecl());
|
2010-03-03 07:58:15 +08:00
|
|
|
if (Pos == OverriddenMethods.end())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return Pos->second.end();
|
|
|
|
}
|
|
|
|
|
2010-07-05 05:44:35 +08:00
|
|
|
unsigned
|
|
|
|
ASTContext::overridden_methods_size(const CXXMethodDecl *Method) const {
|
|
|
|
llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos
|
2012-10-09 09:23:45 +08:00
|
|
|
= OverriddenMethods.find(Method->getCanonicalDecl());
|
2010-07-05 05:44:35 +08:00
|
|
|
if (Pos == OverriddenMethods.end())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return Pos->second.size();
|
|
|
|
}
|
|
|
|
|
2010-03-03 07:58:15 +08:00
|
|
|
void ASTContext::addOverriddenMethod(const CXXMethodDecl *Method,
|
|
|
|
const CXXMethodDecl *Overridden) {
|
2012-10-09 09:23:45 +08:00
|
|
|
assert(Method->isCanonicalDecl() && Overridden->isCanonicalDecl());
|
2010-03-03 07:58:15 +08:00
|
|
|
OverriddenMethods[Method].push_back(Overridden);
|
|
|
|
}
|
|
|
|
|
2012-11-03 22:24:57 +08:00
|
|
|
void ASTContext::getOverriddenMethods(
|
|
|
|
const NamedDecl *D,
|
|
|
|
SmallVectorImpl<const NamedDecl *> &Overridden) const {
|
2012-10-09 09:23:50 +08:00
|
|
|
assert(D);
|
|
|
|
|
|
|
|
if (const CXXMethodDecl *CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
|
2012-10-10 04:08:43 +08:00
|
|
|
Overridden.append(CXXMethod->begin_overridden_methods(),
|
|
|
|
CXXMethod->end_overridden_methods());
|
2012-10-09 09:23:50 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D);
|
|
|
|
if (!Method)
|
|
|
|
return;
|
|
|
|
|
2012-10-10 02:19:01 +08:00
|
|
|
SmallVector<const ObjCMethodDecl *, 8> OverDecls;
|
|
|
|
Method->getOverriddenMethods(OverDecls);
|
2012-10-10 04:08:43 +08:00
|
|
|
Overridden.append(OverDecls.begin(), OverDecls.end());
|
2012-10-09 09:23:50 +08:00
|
|
|
}
|
|
|
|
|
2011-12-03 08:30:27 +08:00
|
|
|
void ASTContext::addedLocalImportDecl(ImportDecl *Import) {
|
|
|
|
assert(!Import->NextLocalImport && "Import declaration already in the chain");
|
|
|
|
assert(!Import->isFromASTFile() && "Non-local import declaration");
|
|
|
|
if (!FirstLocalImport) {
|
|
|
|
FirstLocalImport = Import;
|
|
|
|
LastLocalImport = Import;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
LastLocalImport->NextLocalImport = Import;
|
|
|
|
LastLocalImport = Import;
|
|
|
|
}
|
|
|
|
|
2007-07-19 01:52:12 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Type Sizing and Analysis
|
|
|
|
//===----------------------------------------------------------------------===//
|
2007-07-14 06:13:22 +08:00
|
|
|
|
2008-07-01 02:32:54 +08:00
|
|
|
/// getFloatTypeSemantics - Return the APFloat 'semantics' for the specified
|
|
|
|
/// scalar floating point type.
|
|
|
|
const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
|
2009-09-22 07:43:11 +08:00
|
|
|
const BuiltinType *BT = T->getAs<BuiltinType>();
|
2008-07-01 02:32:54 +08:00
|
|
|
assert(BT && "Not a floating point type!");
|
|
|
|
switch (BT->getKind()) {
|
2011-09-23 13:06:16 +08:00
|
|
|
default: llvm_unreachable("Not a floating point type!");
|
2011-10-15 07:23:15 +08:00
|
|
|
case BuiltinType::Half: return Target->getHalfFormat();
|
2011-09-02 08:18:52 +08:00
|
|
|
case BuiltinType::Float: return Target->getFloatFormat();
|
|
|
|
case BuiltinType::Double: return Target->getDoubleFormat();
|
|
|
|
case BuiltinType::LongDouble: return Target->getLongDoubleFormat();
|
2008-07-01 02:32:54 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-28 01:10:57 +08:00
|
|
|
/// getDeclAlign - Return a conservative estimate of the alignment of the
|
2009-01-25 05:53:27 +08:00
|
|
|
/// specified decl. Note that bitfields do not have a valid alignment, so
|
|
|
|
/// this method will assert on them.
|
2009-11-24 01:18:46 +08:00
|
|
|
/// If @p RefAsPointee, references are treated like their underlying type
|
|
|
|
/// (for alignof), else they're treated like pointers (for CodeGen).
|
2011-01-12 17:06:06 +08:00
|
|
|
CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const {
|
2011-09-02 08:18:52 +08:00
|
|
|
unsigned Align = Target->getCharWidth();
|
2009-02-22 10:56:25 +08:00
|
|
|
|
2010-10-09 02:24:19 +08:00
|
|
|
bool UseAlignAttrOnly = false;
|
|
|
|
if (unsigned AlignFromAttr = D->getMaxAlignment()) {
|
|
|
|
Align = AlignFromAttr;
|
|
|
|
|
|
|
|
// __attribute__((aligned)) can increase or decrease alignment
|
|
|
|
// *except* on a struct or struct member, where it only increases
|
|
|
|
// alignment unless 'packed' is also specified.
|
|
|
|
//
|
2011-09-30 02:04:28 +08:00
|
|
|
// It is an error for alignas to decrease alignment, so we can
|
2010-10-09 02:24:19 +08:00
|
|
|
// ignore that possibility; Sema should diagnose it.
|
|
|
|
if (isa<FieldDecl>(D)) {
|
|
|
|
UseAlignAttrOnly = D->hasAttr<PackedAttr>() ||
|
|
|
|
cast<FieldDecl>(D)->getParent()->hasAttr<PackedAttr>();
|
|
|
|
} else {
|
|
|
|
UseAlignAttrOnly = true;
|
|
|
|
}
|
|
|
|
}
|
2011-05-06 05:19:14 +08:00
|
|
|
else if (isa<FieldDecl>(D))
|
|
|
|
UseAlignAttrOnly =
|
|
|
|
D->hasAttr<PackedAttr>() ||
|
|
|
|
cast<FieldDecl>(D)->getParent()->hasAttr<PackedAttr>();
|
2009-02-22 10:56:25 +08:00
|
|
|
|
2011-01-20 15:57:12 +08:00
|
|
|
// If we're using the align attribute only, just ignore everything
|
|
|
|
// else about the declaration and its type.
|
2010-10-09 02:24:19 +08:00
|
|
|
if (UseAlignAttrOnly) {
|
2011-01-20 15:57:12 +08:00
|
|
|
// do nothing
|
|
|
|
|
2010-10-09 02:24:19 +08:00
|
|
|
} else if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
|
2009-01-25 05:53:27 +08:00
|
|
|
QualType T = VD->getType();
|
2009-07-30 05:53:49 +08:00
|
|
|
if (const ReferenceType* RT = T->getAs<ReferenceType>()) {
|
2009-11-24 01:18:46 +08:00
|
|
|
if (RefAsPointee)
|
|
|
|
T = RT->getPointeeType();
|
|
|
|
else
|
|
|
|
T = getPointerType(RT->getPointeeType());
|
|
|
|
}
|
|
|
|
if (!T->isIncompleteType() && !T->isFunctionType()) {
|
2011-01-19 18:06:00 +08:00
|
|
|
// Adjust alignments of declarations with array type by the
|
|
|
|
// large-array alignment on the target.
|
2011-09-02 08:18:52 +08:00
|
|
|
unsigned MinWidth = Target->getLargeArrayMinWidth();
|
2011-01-19 18:06:00 +08:00
|
|
|
const ArrayType *arrayType;
|
|
|
|
if (MinWidth && (arrayType = getAsArrayType(T))) {
|
|
|
|
if (isa<VariableArrayType>(arrayType))
|
2011-09-02 08:18:52 +08:00
|
|
|
Align = std::max(Align, Target->getLargeArrayAlign());
|
2011-01-19 18:06:00 +08:00
|
|
|
else if (isa<ConstantArrayType>(arrayType) &&
|
|
|
|
MinWidth <= getTypeSize(cast<ConstantArrayType>(arrayType)))
|
2011-09-02 08:18:52 +08:00
|
|
|
Align = std::max(Align, Target->getLargeArrayAlign());
|
2011-01-19 18:06:00 +08:00
|
|
|
|
|
|
|
// Walk through any array types while we're at it.
|
|
|
|
T = getBaseElementType(arrayType);
|
2010-06-05 07:15:27 +08:00
|
|
|
}
|
2011-07-26 15:03:04 +08:00
|
|
|
Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr()));
|
2009-02-22 10:56:25 +08:00
|
|
|
}
|
2011-01-20 15:57:12 +08:00
|
|
|
|
|
|
|
// Fields can be subject to extra alignment constraints, like if
|
|
|
|
// the field is packed, the struct is packed, or the struct has a
|
|
|
|
// a max-field-alignment constraint (#pragma pack). So calculate
|
|
|
|
// the actual alignment of the field within the struct, and then
|
|
|
|
// (as we're expected to) constrain that by the alignment of the type.
|
|
|
|
if (const FieldDecl *field = dyn_cast<FieldDecl>(VD)) {
|
|
|
|
// So calculate the alignment of the field.
|
|
|
|
const ASTRecordLayout &layout = getASTRecordLayout(field->getParent());
|
|
|
|
|
|
|
|
// Start with the record's overall alignment.
|
2011-02-15 10:32:40 +08:00
|
|
|
unsigned fieldAlign = toBits(layout.getAlignment());
|
2011-01-20 15:57:12 +08:00
|
|
|
|
|
|
|
// Use the GCD of that and the offset within the record.
|
|
|
|
uint64_t offset = layout.getFieldOffset(field->getFieldIndex());
|
|
|
|
if (offset > 0) {
|
|
|
|
// Alignment is always a power of 2, so the GCD will be a power of 2,
|
|
|
|
// which means we get to do this crazy thing instead of Euclid's.
|
|
|
|
uint64_t lowBitOfOffset = offset & (~offset + 1);
|
|
|
|
if (lowBitOfOffset < fieldAlign)
|
|
|
|
fieldAlign = static_cast<unsigned>(lowBitOfOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
Align = std::min(Align, fieldAlign);
|
2010-02-23 12:52:00 +08:00
|
|
|
}
|
2009-01-25 05:53:27 +08:00
|
|
|
}
|
2009-02-22 10:56:25 +08:00
|
|
|
|
2011-01-16 02:38:59 +08:00
|
|
|
return toCharUnitsFromBits(Align);
|
2009-01-25 05:53:27 +08:00
|
|
|
}
|
2008-07-01 02:32:54 +08:00
|
|
|
|
2012-08-21 12:10:00 +08:00
|
|
|
// getTypeInfoDataSizeInChars - Return the size of a type, in
|
|
|
|
// chars. If the type is a record, its data size is returned. This is
|
|
|
|
// the size of the memcpy that's performed when assigning this type
|
|
|
|
// using a trivial copy/move assignment operator.
|
|
|
|
std::pair<CharUnits, CharUnits>
|
|
|
|
ASTContext::getTypeInfoDataSizeInChars(QualType T) const {
|
|
|
|
std::pair<CharUnits, CharUnits> sizeAndAlign = getTypeInfoInChars(T);
|
|
|
|
|
|
|
|
// In C++, objects can sometimes be allocated into the tail padding
|
|
|
|
// of a base-class subobject. We decide whether that's possible
|
|
|
|
// during class layout, so here we can just trust the layout results.
|
|
|
|
if (getLangOpts().CPlusPlus) {
|
|
|
|
if (const RecordType *RT = T->getAs<RecordType>()) {
|
|
|
|
const ASTRecordLayout &layout = getASTRecordLayout(RT->getDecl());
|
|
|
|
sizeAndAlign.first = layout.getDataSize();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return sizeAndAlign;
|
|
|
|
}
|
|
|
|
|
2010-05-20 09:18:31 +08:00
|
|
|
std::pair<CharUnits, CharUnits>
|
2011-02-20 09:55:18 +08:00
|
|
|
ASTContext::getTypeInfoInChars(const Type *T) const {
|
2010-05-20 09:18:31 +08:00
|
|
|
std::pair<uint64_t, unsigned> Info = getTypeInfo(T);
|
2011-01-16 02:38:59 +08:00
|
|
|
return std::make_pair(toCharUnitsFromBits(Info.first),
|
|
|
|
toCharUnitsFromBits(Info.second));
|
2010-05-20 09:18:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<CharUnits, CharUnits>
|
2011-02-20 09:55:18 +08:00
|
|
|
ASTContext::getTypeInfoInChars(QualType T) const {
|
2010-05-20 09:18:31 +08:00
|
|
|
return getTypeInfoInChars(T.getTypePtr());
|
|
|
|
}
|
|
|
|
|
2012-03-09 12:12:54 +08:00
|
|
|
std::pair<uint64_t, unsigned> ASTContext::getTypeInfo(const Type *T) const {
|
|
|
|
TypeInfoMap::iterator it = MemoizedTypeInfo.find(T);
|
|
|
|
if (it != MemoizedTypeInfo.end())
|
|
|
|
return it->second;
|
|
|
|
|
|
|
|
std::pair<uint64_t, unsigned> Info = getTypeInfoImpl(T);
|
|
|
|
MemoizedTypeInfo.insert(std::make_pair(T, Info));
|
|
|
|
return Info;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getTypeInfoImpl - Return the size of the specified type, in bits. This
|
|
|
|
/// method does not work on incomplete types.
|
2009-09-25 03:53:00 +08:00
|
|
|
///
|
|
|
|
/// FIXME: Pointers into different addr spaces could have different sizes and
|
|
|
|
/// alignment requirements: getPointerInfo should take an AddrSpace, this
|
|
|
|
/// should take a QualType, &c.
|
2007-07-14 09:29:45 +08:00
|
|
|
std::pair<uint64_t, unsigned>
|
2012-03-09 12:12:54 +08:00
|
|
|
ASTContext::getTypeInfoImpl(const Type *T) const {
|
2009-02-28 02:32:39 +08:00
|
|
|
uint64_t Width=0;
|
|
|
|
unsigned Align=8;
|
2007-07-14 06:13:22 +08:00
|
|
|
switch (T->getTypeClass()) {
|
2009-02-27 07:50:07 +08:00
|
|
|
#define TYPE(Class, Base)
|
|
|
|
#define ABSTRACT_TYPE(Class, Base)
|
2009-05-01 01:32:17 +08:00
|
|
|
#define NON_CANONICAL_TYPE(Class, Base)
|
2009-02-27 07:50:07 +08:00
|
|
|
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
|
|
|
|
#include "clang/AST/TypeNodes.def"
|
2011-06-29 00:49:23 +08:00
|
|
|
llvm_unreachable("Should not see dependent types");
|
2009-02-27 07:50:07 +08:00
|
|
|
|
2007-07-19 02:26:58 +08:00
|
|
|
case Type::FunctionNoProto:
|
|
|
|
case Type::FunctionProto:
|
2009-05-01 01:32:17 +08:00
|
|
|
// GCC extension: alignof(function) = 32 bits
|
|
|
|
Width = 0;
|
|
|
|
Align = 32;
|
|
|
|
break;
|
|
|
|
|
2009-02-27 07:50:07 +08:00
|
|
|
case Type::IncompleteArray:
|
2007-08-30 09:06:46 +08:00
|
|
|
case Type::VariableArray:
|
2009-05-01 01:32:17 +08:00
|
|
|
Width = 0;
|
|
|
|
Align = getTypeAlign(cast<ArrayType>(T)->getElementType());
|
|
|
|
break;
|
|
|
|
|
2007-08-30 09:06:46 +08:00
|
|
|
case Type::ConstantArray: {
|
2008-11-08 13:48:37 +08:00
|
|
|
const ConstantArrayType *CAT = cast<ConstantArrayType>(T);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-03-06 02:54:05 +08:00
|
|
|
std::pair<uint64_t, unsigned> EltInfo = getTypeInfo(CAT->getElementType());
|
2011-12-13 19:23:52 +08:00
|
|
|
uint64_t Size = CAT->getSize().getZExtValue();
|
2012-03-09 12:12:54 +08:00
|
|
|
assert((Size == 0 || EltInfo.first <= (uint64_t)(-1)/Size) &&
|
|
|
|
"Overflow in array type bit size evaluation");
|
2011-12-13 19:23:52 +08:00
|
|
|
Width = EltInfo.first*Size;
|
2007-07-20 06:06:24 +08:00
|
|
|
Align = EltInfo.second;
|
2011-04-27 05:05:39 +08:00
|
|
|
Width = llvm::RoundUpToAlignment(Width, Align);
|
2007-07-20 06:06:24 +08:00
|
|
|
break;
|
2007-12-29 13:10:55 +08:00
|
|
|
}
|
2008-04-19 07:10:10 +08:00
|
|
|
case Type::ExtVector:
|
2007-07-20 06:06:24 +08:00
|
|
|
case Type::Vector: {
|
2009-10-22 13:17:15 +08:00
|
|
|
const VectorType *VT = cast<VectorType>(T);
|
|
|
|
std::pair<uint64_t, unsigned> EltInfo = getTypeInfo(VT->getElementType());
|
|
|
|
Width = EltInfo.first*VT->getNumElements();
|
2008-05-30 17:31:38 +08:00
|
|
|
Align = Width;
|
2009-01-18 14:42:49 +08:00
|
|
|
// If the alignment is not a power of 2, round up to the next power of 2.
|
|
|
|
// This happens for non-power-of-2 length vectors.
|
2010-04-22 07:32:43 +08:00
|
|
|
if (Align & (Align-1)) {
|
2009-10-22 13:17:15 +08:00
|
|
|
Align = llvm::NextPowerOf2(Align);
|
|
|
|
Width = llvm::RoundUpToAlignment(Width, Align);
|
|
|
|
}
|
2012-07-14 07:57:43 +08:00
|
|
|
// Adjust the alignment based on the target max.
|
|
|
|
uint64_t TargetVectorAlign = Target->getMaxVectorAlign();
|
|
|
|
if (TargetVectorAlign && TargetVectorAlign < Align)
|
|
|
|
Align = TargetVectorAlign;
|
2007-07-20 06:06:24 +08:00
|
|
|
break;
|
|
|
|
}
|
2007-07-19 02:26:58 +08:00
|
|
|
|
2008-03-08 16:52:55 +08:00
|
|
|
case Type::Builtin:
|
2007-07-14 06:13:22 +08:00
|
|
|
switch (cast<BuiltinType>(T)->getKind()) {
|
2011-09-23 13:06:16 +08:00
|
|
|
default: llvm_unreachable("Unknown builtin type!");
|
2007-07-14 09:29:45 +08:00
|
|
|
case BuiltinType::Void:
|
2009-05-01 01:32:17 +08:00
|
|
|
// GCC extension: alignof(void) = 8 bits.
|
|
|
|
Width = 0;
|
|
|
|
Align = 8;
|
|
|
|
break;
|
|
|
|
|
2007-12-20 03:23:28 +08:00
|
|
|
case BuiltinType::Bool:
|
2011-09-02 08:18:52 +08:00
|
|
|
Width = Target->getBoolWidth();
|
|
|
|
Align = Target->getBoolAlign();
|
2007-12-20 03:23:28 +08:00
|
|
|
break;
|
2007-07-14 06:27:08 +08:00
|
|
|
case BuiltinType::Char_S:
|
|
|
|
case BuiltinType::Char_U:
|
|
|
|
case BuiltinType::UChar:
|
2007-12-20 03:23:28 +08:00
|
|
|
case BuiltinType::SChar:
|
2011-09-02 08:18:52 +08:00
|
|
|
Width = Target->getCharWidth();
|
|
|
|
Align = Target->getCharAlign();
|
2007-12-20 03:23:28 +08:00
|
|
|
break;
|
2010-12-26 07:25:43 +08:00
|
|
|
case BuiltinType::WChar_S:
|
|
|
|
case BuiltinType::WChar_U:
|
2011-09-02 08:18:52 +08:00
|
|
|
Width = Target->getWCharWidth();
|
|
|
|
Align = Target->getWCharAlign();
|
2008-08-10 00:51:54 +08:00
|
|
|
break;
|
2009-07-14 14:30:34 +08:00
|
|
|
case BuiltinType::Char16:
|
2011-09-02 08:18:52 +08:00
|
|
|
Width = Target->getChar16Width();
|
|
|
|
Align = Target->getChar16Align();
|
2009-07-14 14:30:34 +08:00
|
|
|
break;
|
|
|
|
case BuiltinType::Char32:
|
2011-09-02 08:18:52 +08:00
|
|
|
Width = Target->getChar32Width();
|
|
|
|
Align = Target->getChar32Align();
|
2009-07-14 14:30:34 +08:00
|
|
|
break;
|
2007-07-14 06:27:08 +08:00
|
|
|
case BuiltinType::UShort:
|
2007-12-20 03:23:28 +08:00
|
|
|
case BuiltinType::Short:
|
2011-09-02 08:18:52 +08:00
|
|
|
Width = Target->getShortWidth();
|
|
|
|
Align = Target->getShortAlign();
|
2007-12-20 03:23:28 +08:00
|
|
|
break;
|
2007-07-14 06:27:08 +08:00
|
|
|
case BuiltinType::UInt:
|
2007-12-20 03:23:28 +08:00
|
|
|
case BuiltinType::Int:
|
2011-09-02 08:18:52 +08:00
|
|
|
Width = Target->getIntWidth();
|
|
|
|
Align = Target->getIntAlign();
|
2007-12-20 03:23:28 +08:00
|
|
|
break;
|
2007-07-14 06:27:08 +08:00
|
|
|
case BuiltinType::ULong:
|
2007-12-20 03:23:28 +08:00
|
|
|
case BuiltinType::Long:
|
2011-09-02 08:18:52 +08:00
|
|
|
Width = Target->getLongWidth();
|
|
|
|
Align = Target->getLongAlign();
|
2007-12-20 03:23:28 +08:00
|
|
|
break;
|
2007-07-14 06:27:08 +08:00
|
|
|
case BuiltinType::ULongLong:
|
2007-12-20 03:23:28 +08:00
|
|
|
case BuiltinType::LongLong:
|
2011-09-02 08:18:52 +08:00
|
|
|
Width = Target->getLongLongWidth();
|
|
|
|
Align = Target->getLongLongAlign();
|
2007-12-20 03:23:28 +08:00
|
|
|
break;
|
2009-04-30 10:55:13 +08:00
|
|
|
case BuiltinType::Int128:
|
|
|
|
case BuiltinType::UInt128:
|
|
|
|
Width = 128;
|
|
|
|
Align = 128; // int128_t is 128-bit aligned on all targets.
|
|
|
|
break;
|
2011-10-15 07:23:15 +08:00
|
|
|
case BuiltinType::Half:
|
|
|
|
Width = Target->getHalfWidth();
|
|
|
|
Align = Target->getHalfAlign();
|
|
|
|
break;
|
2007-12-20 03:23:28 +08:00
|
|
|
case BuiltinType::Float:
|
2011-09-02 08:18:52 +08:00
|
|
|
Width = Target->getFloatWidth();
|
|
|
|
Align = Target->getFloatAlign();
|
2007-12-20 03:23:28 +08:00
|
|
|
break;
|
|
|
|
case BuiltinType::Double:
|
2011-09-02 08:18:52 +08:00
|
|
|
Width = Target->getDoubleWidth();
|
|
|
|
Align = Target->getDoubleAlign();
|
2007-12-20 03:23:28 +08:00
|
|
|
break;
|
|
|
|
case BuiltinType::LongDouble:
|
2011-09-02 08:18:52 +08:00
|
|
|
Width = Target->getLongDoubleWidth();
|
|
|
|
Align = Target->getLongDoubleAlign();
|
2007-12-20 03:23:28 +08:00
|
|
|
break;
|
2009-05-11 02:38:11 +08:00
|
|
|
case BuiltinType::NullPtr:
|
2011-09-02 08:18:52 +08:00
|
|
|
Width = Target->getPointerWidth(0); // C++ 3.9.1p11: sizeof(nullptr_t)
|
|
|
|
Align = Target->getPointerAlign(0); // == sizeof(void*)
|
2009-05-28 03:34:06 +08:00
|
|
|
break;
|
2010-08-03 02:03:20 +08:00
|
|
|
case BuiltinType::ObjCId:
|
|
|
|
case BuiltinType::ObjCClass:
|
|
|
|
case BuiltinType::ObjCSel:
|
2011-09-02 08:18:52 +08:00
|
|
|
Width = Target->getPointerWidth(0);
|
|
|
|
Align = Target->getPointerAlign(0);
|
2010-08-03 02:03:20 +08:00
|
|
|
break;
|
2013-02-07 18:55:47 +08:00
|
|
|
case BuiltinType::OCLSampler:
|
|
|
|
// Samplers are modeled as integers.
|
|
|
|
Width = Target->getIntWidth();
|
|
|
|
Align = Target->getIntAlign();
|
|
|
|
break;
|
2013-01-20 20:31:11 +08:00
|
|
|
case BuiltinType::OCLEvent:
|
2012-12-18 22:38:23 +08:00
|
|
|
case BuiltinType::OCLImage1d:
|
|
|
|
case BuiltinType::OCLImage1dArray:
|
|
|
|
case BuiltinType::OCLImage1dBuffer:
|
|
|
|
case BuiltinType::OCLImage2d:
|
|
|
|
case BuiltinType::OCLImage2dArray:
|
|
|
|
case BuiltinType::OCLImage3d:
|
|
|
|
// Currently these types are pointers to opaque types.
|
|
|
|
Width = Target->getPointerWidth(0);
|
|
|
|
Align = Target->getPointerAlign(0);
|
|
|
|
break;
|
2007-07-14 06:13:22 +08:00
|
|
|
}
|
2007-07-16 07:46:53 +08:00
|
|
|
break;
|
2009-06-18 06:40:22 +08:00
|
|
|
case Type::ObjCObjectPointer:
|
2011-09-02 08:18:52 +08:00
|
|
|
Width = Target->getPointerWidth(0);
|
|
|
|
Align = Target->getPointerAlign(0);
|
2007-12-20 03:23:28 +08:00
|
|
|
break;
|
2008-09-24 23:05:44 +08:00
|
|
|
case Type::BlockPointer: {
|
2011-03-19 06:38:29 +08:00
|
|
|
unsigned AS = getTargetAddressSpace(
|
|
|
|
cast<BlockPointerType>(T)->getPointeeType());
|
2011-09-02 08:18:52 +08:00
|
|
|
Width = Target->getPointerWidth(AS);
|
|
|
|
Align = Target->getPointerAlign(AS);
|
2008-09-24 23:05:44 +08:00
|
|
|
break;
|
|
|
|
}
|
2009-11-24 01:18:46 +08:00
|
|
|
case Type::LValueReference:
|
|
|
|
case Type::RValueReference: {
|
|
|
|
// alignof and sizeof should never enter this code path here, so we go
|
|
|
|
// the pointer route.
|
2011-03-19 06:38:29 +08:00
|
|
|
unsigned AS = getTargetAddressSpace(
|
|
|
|
cast<ReferenceType>(T)->getPointeeType());
|
2011-09-02 08:18:52 +08:00
|
|
|
Width = Target->getPointerWidth(AS);
|
|
|
|
Align = Target->getPointerAlign(AS);
|
2009-11-24 01:18:46 +08:00
|
|
|
break;
|
|
|
|
}
|
2008-03-08 16:34:58 +08:00
|
|
|
case Type::Pointer: {
|
2011-03-19 06:38:29 +08:00
|
|
|
unsigned AS = getTargetAddressSpace(cast<PointerType>(T)->getPointeeType());
|
2011-09-02 08:18:52 +08:00
|
|
|
Width = Target->getPointerWidth(AS);
|
|
|
|
Align = Target->getPointerAlign(AS);
|
2008-03-08 16:34:58 +08:00
|
|
|
break;
|
|
|
|
}
|
2009-01-25 05:16:55 +08:00
|
|
|
case Type::MemberPointer: {
|
2010-08-16 11:33:14 +08:00
|
|
|
const MemberPointerType *MPT = cast<MemberPointerType>(T);
|
2009-09-09 23:08:12 +08:00
|
|
|
std::pair<uint64_t, unsigned> PtrDiffInfo =
|
2009-05-17 10:06:04 +08:00
|
|
|
getTypeInfo(getPointerDiffType());
|
2010-08-16 11:33:14 +08:00
|
|
|
Width = PtrDiffInfo.first * ABI->getMemberPointerSize(MPT);
|
2009-05-17 10:06:04 +08:00
|
|
|
Align = PtrDiffInfo.second;
|
|
|
|
break;
|
2009-01-25 05:16:55 +08:00
|
|
|
}
|
2007-07-19 02:26:58 +08:00
|
|
|
case Type::Complex: {
|
|
|
|
// Complex types have the same alignment as their elements, but twice the
|
|
|
|
// size.
|
2009-09-09 23:08:12 +08:00
|
|
|
std::pair<uint64_t, unsigned> EltInfo =
|
2008-03-06 02:54:05 +08:00
|
|
|
getTypeInfo(cast<ComplexType>(T)->getElementType());
|
2008-03-08 16:52:55 +08:00
|
|
|
Width = EltInfo.first*2;
|
2007-07-19 02:26:58 +08:00
|
|
|
Align = EltInfo.second;
|
|
|
|
break;
|
|
|
|
}
|
2010-05-15 19:32:37 +08:00
|
|
|
case Type::ObjCObject:
|
|
|
|
return getTypeInfo(cast<ObjCObjectType>(T)->getBaseType().getTypePtr());
|
2008-06-05 05:54:36 +08:00
|
|
|
case Type::ObjCInterface: {
|
2008-11-08 13:48:37 +08:00
|
|
|
const ObjCInterfaceType *ObjCI = cast<ObjCInterfaceType>(T);
|
2008-06-05 05:54:36 +08:00
|
|
|
const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl());
|
2011-02-11 09:54:29 +08:00
|
|
|
Width = toBits(Layout.getSize());
|
2011-02-15 10:32:40 +08:00
|
|
|
Align = toBits(Layout.getAlignment());
|
2008-06-05 05:54:36 +08:00
|
|
|
break;
|
|
|
|
}
|
2009-02-27 07:50:07 +08:00
|
|
|
case Type::Record:
|
|
|
|
case Type::Enum: {
|
2008-11-08 13:48:37 +08:00
|
|
|
const TagType *TT = cast<TagType>(T);
|
|
|
|
|
|
|
|
if (TT->getDecl()->isInvalidDecl()) {
|
2011-04-21 01:29:44 +08:00
|
|
|
Width = 8;
|
|
|
|
Align = 8;
|
2008-08-10 05:35:13 +08:00
|
|
|
break;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-08 13:48:37 +08:00
|
|
|
if (const EnumType *ET = dyn_cast<EnumType>(TT))
|
2008-04-07 06:05:18 +08:00
|
|
|
return getTypeInfo(ET->getDecl()->getIntegerType());
|
|
|
|
|
2008-11-08 13:48:37 +08:00
|
|
|
const RecordType *RT = cast<RecordType>(TT);
|
2008-04-07 06:05:18 +08:00
|
|
|
const ASTRecordLayout &Layout = getASTRecordLayout(RT->getDecl());
|
2011-02-11 09:54:29 +08:00
|
|
|
Width = toBits(Layout.getSize());
|
2011-02-15 10:32:40 +08:00
|
|
|
Align = toBits(Layout.getAlignment());
|
2007-07-24 06:46:22 +08:00
|
|
|
break;
|
2007-07-14 06:13:22 +08:00
|
|
|
}
|
2009-03-31 06:58:21 +08:00
|
|
|
|
2009-10-22 13:17:15 +08:00
|
|
|
case Type::SubstTemplateTypeParm:
|
2009-10-18 17:09:24 +08:00
|
|
|
return getTypeInfo(cast<SubstTemplateTypeParmType>(T)->
|
|
|
|
getReplacementType().getTypePtr());
|
|
|
|
|
2011-02-20 11:19:35 +08:00
|
|
|
case Type::Auto: {
|
|
|
|
const AutoType *A = cast<AutoType>(T);
|
|
|
|
assert(A->isDeduced() && "Cannot request the size of a dependent type");
|
2011-02-23 04:00:16 +08:00
|
|
|
return getTypeInfo(A->getDeducedType().getTypePtr());
|
2011-02-20 11:19:35 +08:00
|
|
|
}
|
|
|
|
|
2010-12-11 00:29:40 +08:00
|
|
|
case Type::Paren:
|
|
|
|
return getTypeInfo(cast<ParenType>(T)->getInnerType().getTypePtr());
|
|
|
|
|
2009-05-01 01:32:17 +08:00
|
|
|
case Type::Typedef: {
|
2011-04-15 22:24:37 +08:00
|
|
|
const TypedefNameDecl *Typedef = cast<TypedefType>(T)->getDecl();
|
2010-08-27 08:11:28 +08:00
|
|
|
std::pair<uint64_t, unsigned> Info
|
|
|
|
= getTypeInfo(Typedef->getUnderlyingType().getTypePtr());
|
2011-02-20 06:55:41 +08:00
|
|
|
// If the typedef has an aligned attribute on it, it overrides any computed
|
|
|
|
// alignment we have. This violates the GCC documentation (which says that
|
|
|
|
// attribute(aligned) can only round up) but matches its implementation.
|
|
|
|
if (unsigned AttrAlign = Typedef->getMaxAlignment())
|
|
|
|
Align = AttrAlign;
|
|
|
|
else
|
|
|
|
Align = Info.second;
|
2010-08-27 08:11:28 +08:00
|
|
|
Width = Info.first;
|
2009-03-31 06:58:21 +08:00
|
|
|
break;
|
2008-04-07 06:05:18 +08:00
|
|
|
}
|
2009-05-01 01:32:17 +08:00
|
|
|
|
|
|
|
case Type::TypeOfExpr:
|
|
|
|
return getTypeInfo(cast<TypeOfExprType>(T)->getUnderlyingExpr()->getType()
|
|
|
|
.getTypePtr());
|
|
|
|
|
|
|
|
case Type::TypeOf:
|
|
|
|
return getTypeInfo(cast<TypeOfType>(T)->getUnderlyingType().getTypePtr());
|
|
|
|
|
2009-06-25 03:06:50 +08:00
|
|
|
case Type::Decltype:
|
|
|
|
return getTypeInfo(cast<DecltypeType>(T)->getUnderlyingExpr()->getType()
|
|
|
|
.getTypePtr());
|
|
|
|
|
2011-05-25 06:41:36 +08:00
|
|
|
case Type::UnaryTransform:
|
|
|
|
return getTypeInfo(cast<UnaryTransformType>(T)->getUnderlyingType());
|
|
|
|
|
2010-05-12 05:36:43 +08:00
|
|
|
case Type::Elaborated:
|
|
|
|
return getTypeInfo(cast<ElaboratedType>(T)->getNamedType().getTypePtr());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-01-06 09:58:22 +08:00
|
|
|
case Type::Attributed:
|
|
|
|
return getTypeInfo(
|
|
|
|
cast<AttributedType>(T)->getEquivalentType().getTypePtr());
|
|
|
|
|
2011-05-06 05:57:07 +08:00
|
|
|
case Type::TemplateSpecialization: {
|
2009-09-09 23:08:12 +08:00
|
|
|
assert(getCanonicalType(T) != T &&
|
2009-05-01 01:32:17 +08:00
|
|
|
"Cannot request the size of a dependent type");
|
2011-05-06 05:57:07 +08:00
|
|
|
const TemplateSpecializationType *TST = cast<TemplateSpecializationType>(T);
|
|
|
|
// A type alias template specialization may refer to a typedef with the
|
|
|
|
// aligned attribute on it.
|
|
|
|
if (TST->isTypeAlias())
|
|
|
|
return getTypeInfo(TST->getAliasedType().getTypePtr());
|
|
|
|
else
|
|
|
|
return getTypeInfo(getCanonicalType(T));
|
|
|
|
}
|
|
|
|
|
2011-10-07 07:00:33 +08:00
|
|
|
case Type::Atomic: {
|
2011-10-15 04:59:01 +08:00
|
|
|
std::pair<uint64_t, unsigned> Info
|
|
|
|
= getTypeInfo(cast<AtomicType>(T)->getValueType());
|
|
|
|
Width = Info.first;
|
|
|
|
Align = Info.second;
|
|
|
|
if (Width != 0 && Width <= Target->getMaxAtomicPromoteWidth() &&
|
|
|
|
llvm::isPowerOf2_64(Width)) {
|
|
|
|
// We can potentially perform lock-free atomic operations for this
|
|
|
|
// type; promote the alignment appropriately.
|
|
|
|
// FIXME: We could potentially promote the width here as well...
|
|
|
|
// is that worthwhile? (Non-struct atomic types generally have
|
|
|
|
// power-of-two size anyway, but structs might not. Requires a bit
|
|
|
|
// of implementation work to make sure we zero out the extra bits.)
|
|
|
|
Align = static_cast<unsigned>(Width);
|
|
|
|
}
|
2011-10-07 07:00:33 +08:00
|
|
|
}
|
|
|
|
|
2009-05-01 01:32:17 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-10-15 04:59:01 +08:00
|
|
|
assert(llvm::isPowerOf2_32(Align) && "Alignment must be power of 2");
|
2008-03-08 16:52:55 +08:00
|
|
|
return std::make_pair(Width, Align);
|
2007-07-14 06:13:22 +08:00
|
|
|
}
|
|
|
|
|
2011-01-16 02:38:59 +08:00
|
|
|
/// toCharUnitsFromBits - Convert a size in bits to a size in characters.
|
|
|
|
CharUnits ASTContext::toCharUnitsFromBits(int64_t BitSize) const {
|
|
|
|
return CharUnits::fromQuantity(BitSize / getCharWidth());
|
|
|
|
}
|
|
|
|
|
2011-02-11 09:54:29 +08:00
|
|
|
/// toBits - Convert a size in characters to a size in characters.
|
|
|
|
int64_t ASTContext::toBits(CharUnits CharSize) const {
|
|
|
|
return CharSize.getQuantity() * getCharWidth();
|
|
|
|
}
|
|
|
|
|
2009-12-22 22:23:30 +08:00
|
|
|
/// getTypeSizeInChars - Return the size of the specified type, in characters.
|
|
|
|
/// This method does not work on incomplete types.
|
2011-01-12 17:06:06 +08:00
|
|
|
CharUnits ASTContext::getTypeSizeInChars(QualType T) const {
|
2011-01-16 02:38:59 +08:00
|
|
|
return toCharUnitsFromBits(getTypeSize(T));
|
2009-12-22 22:23:30 +08:00
|
|
|
}
|
2011-01-12 17:06:06 +08:00
|
|
|
CharUnits ASTContext::getTypeSizeInChars(const Type *T) const {
|
2011-01-16 02:38:59 +08:00
|
|
|
return toCharUnitsFromBits(getTypeSize(T));
|
2009-12-22 22:23:30 +08:00
|
|
|
}
|
|
|
|
|
2010-01-27 01:25:18 +08:00
|
|
|
/// getTypeAlignInChars - Return the ABI-specified alignment of a type, in
|
2010-01-27 01:22:55 +08:00
|
|
|
/// characters. This method does not work on incomplete types.
|
2011-01-12 17:06:06 +08:00
|
|
|
CharUnits ASTContext::getTypeAlignInChars(QualType T) const {
|
2011-01-16 02:38:59 +08:00
|
|
|
return toCharUnitsFromBits(getTypeAlign(T));
|
2010-01-27 01:22:55 +08:00
|
|
|
}
|
2011-01-12 17:06:06 +08:00
|
|
|
CharUnits ASTContext::getTypeAlignInChars(const Type *T) const {
|
2011-01-16 02:38:59 +08:00
|
|
|
return toCharUnitsFromBits(getTypeAlign(T));
|
2010-01-27 01:22:55 +08:00
|
|
|
}
|
|
|
|
|
2009-01-28 02:08:34 +08:00
|
|
|
/// getPreferredTypeAlign - Return the "preferred" alignment of the specified
|
|
|
|
/// type for the current target in bits. This can be different than the ABI
|
|
|
|
/// alignment in cases where it is beneficial for performance to overalign
|
|
|
|
/// a data type.
|
2011-01-12 17:06:06 +08:00
|
|
|
unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
|
2009-01-28 02:08:34 +08:00
|
|
|
unsigned ABIAlign = getTypeAlign(T);
|
2009-05-26 05:27:19 +08:00
|
|
|
|
|
|
|
// Double and long long should be naturally aligned if possible.
|
2009-09-22 07:43:11 +08:00
|
|
|
if (const ComplexType* CT = T->getAs<ComplexType>())
|
2009-05-26 05:27:19 +08:00
|
|
|
T = CT->getElementType().getTypePtr();
|
|
|
|
if (T->isSpecificBuiltinType(BuiltinType::Double) ||
|
2012-03-22 04:20:47 +08:00
|
|
|
T->isSpecificBuiltinType(BuiltinType::LongLong) ||
|
|
|
|
T->isSpecificBuiltinType(BuiltinType::ULongLong))
|
2009-05-26 05:27:19 +08:00
|
|
|
return std::max(ABIAlign, (unsigned)getTypeSize(T));
|
|
|
|
|
2009-01-28 02:08:34 +08:00
|
|
|
return ABIAlign;
|
|
|
|
}
|
|
|
|
|
2010-08-21 05:21:08 +08:00
|
|
|
/// DeepCollectObjCIvars -
|
|
|
|
/// This routine first collects all declared, but not synthesized, ivars in
|
|
|
|
/// super class and then collects all ivars, including those synthesized for
|
|
|
|
/// current class. This routine is used for implementation of current class
|
|
|
|
/// when all ivars, declared and synthesized are known.
|
2009-05-13 02:14:29 +08:00
|
|
|
///
|
2010-08-21 05:21:08 +08:00
|
|
|
void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI,
|
|
|
|
bool leafClass,
|
2011-07-22 10:08:32 +08:00
|
|
|
SmallVectorImpl<const ObjCIvarDecl*> &Ivars) const {
|
2010-08-21 05:21:08 +08:00
|
|
|
if (const ObjCInterfaceDecl *SuperClass = OI->getSuperClass())
|
|
|
|
DeepCollectObjCIvars(SuperClass, false, Ivars);
|
|
|
|
if (!leafClass) {
|
|
|
|
for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
|
|
|
|
E = OI->ivar_end(); I != E; ++I)
|
2012-06-07 04:45:41 +08:00
|
|
|
Ivars.push_back(*I);
|
2011-08-18 07:08:45 +08:00
|
|
|
} else {
|
2011-06-29 02:05:25 +08:00
|
|
|
ObjCInterfaceDecl *IDecl = const_cast<ObjCInterfaceDecl *>(OI);
|
2011-07-22 10:08:32 +08:00
|
|
|
for (const ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv;
|
2011-06-29 02:05:25 +08:00
|
|
|
Iv= Iv->getNextIvar())
|
|
|
|
Ivars.push_back(Iv);
|
|
|
|
}
|
2009-05-13 02:14:29 +08:00
|
|
|
}
|
|
|
|
|
2009-10-30 09:13:23 +08:00
|
|
|
/// CollectInheritedProtocols - Collect all protocols in current class and
|
|
|
|
/// those inherited by it.
|
|
|
|
void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
|
2010-02-13 03:27:33 +08:00
|
|
|
llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols) {
|
2009-10-30 09:13:23 +08:00
|
|
|
if (const ObjCInterfaceDecl *OI = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
|
2010-09-01 09:21:15 +08:00
|
|
|
// We can use protocol_iterator here instead of
|
|
|
|
// all_referenced_protocol_iterator since we are walking all categories.
|
|
|
|
for (ObjCInterfaceDecl::all_protocol_iterator P = OI->all_referenced_protocol_begin(),
|
|
|
|
PE = OI->all_referenced_protocol_end(); P != PE; ++P) {
|
2009-10-30 09:13:23 +08:00
|
|
|
ObjCProtocolDecl *Proto = (*P);
|
2012-01-02 02:09:12 +08:00
|
|
|
Protocols.insert(Proto->getCanonicalDecl());
|
2009-10-30 09:13:23 +08:00
|
|
|
for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
|
2010-02-26 02:24:33 +08:00
|
|
|
PE = Proto->protocol_end(); P != PE; ++P) {
|
2012-01-02 02:09:12 +08:00
|
|
|
Protocols.insert((*P)->getCanonicalDecl());
|
2009-10-30 09:13:23 +08:00
|
|
|
CollectInheritedProtocols(*P, Protocols);
|
|
|
|
}
|
2010-02-26 02:24:33 +08:00
|
|
|
}
|
2009-10-30 09:13:23 +08:00
|
|
|
|
|
|
|
// Categories of this Interface.
|
2013-01-17 07:00:23 +08:00
|
|
|
for (ObjCInterfaceDecl::visible_categories_iterator
|
|
|
|
Cat = OI->visible_categories_begin(),
|
|
|
|
CatEnd = OI->visible_categories_end();
|
|
|
|
Cat != CatEnd; ++Cat) {
|
|
|
|
CollectInheritedProtocols(*Cat, Protocols);
|
|
|
|
}
|
|
|
|
|
2009-10-30 09:13:23 +08:00
|
|
|
if (ObjCInterfaceDecl *SD = OI->getSuperClass())
|
|
|
|
while (SD) {
|
|
|
|
CollectInheritedProtocols(SD, Protocols);
|
|
|
|
SD = SD->getSuperClass();
|
|
|
|
}
|
2010-04-28 01:47:25 +08:00
|
|
|
} else if (const ObjCCategoryDecl *OC = dyn_cast<ObjCCategoryDecl>(CDecl)) {
|
2010-09-01 09:21:15 +08:00
|
|
|
for (ObjCCategoryDecl::protocol_iterator P = OC->protocol_begin(),
|
2009-10-30 09:13:23 +08:00
|
|
|
PE = OC->protocol_end(); P != PE; ++P) {
|
|
|
|
ObjCProtocolDecl *Proto = (*P);
|
2012-01-02 02:09:12 +08:00
|
|
|
Protocols.insert(Proto->getCanonicalDecl());
|
2009-10-30 09:13:23 +08:00
|
|
|
for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
|
|
|
|
PE = Proto->protocol_end(); P != PE; ++P)
|
|
|
|
CollectInheritedProtocols(*P, Protocols);
|
|
|
|
}
|
2010-04-28 01:47:25 +08:00
|
|
|
} else if (const ObjCProtocolDecl *OP = dyn_cast<ObjCProtocolDecl>(CDecl)) {
|
2009-10-30 09:13:23 +08:00
|
|
|
for (ObjCProtocolDecl::protocol_iterator P = OP->protocol_begin(),
|
|
|
|
PE = OP->protocol_end(); P != PE; ++P) {
|
|
|
|
ObjCProtocolDecl *Proto = (*P);
|
2012-01-02 02:09:12 +08:00
|
|
|
Protocols.insert(Proto->getCanonicalDecl());
|
2009-10-30 09:13:23 +08:00
|
|
|
for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
|
|
|
|
PE = Proto->protocol_end(); P != PE; ++P)
|
|
|
|
CollectInheritedProtocols(*P, Protocols);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-12 17:06:06 +08:00
|
|
|
unsigned ASTContext::CountNonClassIvars(const ObjCInterfaceDecl *OI) const {
|
2010-03-23 02:25:57 +08:00
|
|
|
unsigned count = 0;
|
|
|
|
// Count ivars declared in class extension.
|
2013-01-17 07:00:23 +08:00
|
|
|
for (ObjCInterfaceDecl::known_extensions_iterator
|
|
|
|
Ext = OI->known_extensions_begin(),
|
|
|
|
ExtEnd = OI->known_extensions_end();
|
|
|
|
Ext != ExtEnd; ++Ext) {
|
|
|
|
count += Ext->ivar_size();
|
|
|
|
}
|
|
|
|
|
2010-03-23 02:25:57 +08:00
|
|
|
// Count ivar defined in this class's implementation. This
|
|
|
|
// includes synthesized ivars.
|
|
|
|
if (ObjCImplementationDecl *ImplDecl = OI->getImplementation())
|
2010-04-28 01:47:25 +08:00
|
|
|
count += ImplDecl->ivar_size();
|
|
|
|
|
2009-06-04 09:19:09 +08:00
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2012-02-03 13:58:16 +08:00
|
|
|
bool ASTContext::isSentinelNullExpr(const Expr *E) {
|
|
|
|
if (!E)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// nullptr_t is always treated as null.
|
|
|
|
if (E->getType()->isNullPtrType()) return true;
|
|
|
|
|
|
|
|
if (E->getType()->isAnyPointerType() &&
|
|
|
|
E->IgnoreParenCasts()->isNullPointerConstant(*this,
|
|
|
|
Expr::NPC_ValueDependentIsNull))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Unfortunately, __null has type 'int'.
|
|
|
|
if (isa<GNUNullExpr>(E)) return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-07-21 08:05:53 +08:00
|
|
|
/// \brief Get the implementation of ObjCInterfaceDecl,or NULL if none exists.
|
|
|
|
ObjCImplementationDecl *ASTContext::getObjCImplementation(ObjCInterfaceDecl *D) {
|
|
|
|
llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*>::iterator
|
|
|
|
I = ObjCImpls.find(D);
|
|
|
|
if (I != ObjCImpls.end())
|
|
|
|
return cast<ObjCImplementationDecl>(I->second);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists.
|
|
|
|
ObjCCategoryImplDecl *ASTContext::getObjCImplementation(ObjCCategoryDecl *D) {
|
|
|
|
llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*>::iterator
|
|
|
|
I = ObjCImpls.find(D);
|
|
|
|
if (I != ObjCImpls.end())
|
|
|
|
return cast<ObjCCategoryImplDecl>(I->second);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Set the implementation of ObjCInterfaceDecl.
|
|
|
|
void ASTContext::setObjCImplementation(ObjCInterfaceDecl *IFaceD,
|
|
|
|
ObjCImplementationDecl *ImplD) {
|
|
|
|
assert(IFaceD && ImplD && "Passed null params");
|
|
|
|
ObjCImpls[IFaceD] = ImplD;
|
|
|
|
}
|
|
|
|
/// \brief Set the implementation of ObjCCategoryDecl.
|
|
|
|
void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD,
|
|
|
|
ObjCCategoryImplDecl *ImplD) {
|
|
|
|
assert(CatD && ImplD && "Passed null params");
|
|
|
|
ObjCImpls[CatD] = ImplD;
|
|
|
|
}
|
|
|
|
|
2013-02-03 21:23:21 +08:00
|
|
|
const ObjCInterfaceDecl *ASTContext::getObjContainingInterface(
|
|
|
|
const NamedDecl *ND) const {
|
|
|
|
if (const ObjCInterfaceDecl *ID =
|
|
|
|
dyn_cast<ObjCInterfaceDecl>(ND->getDeclContext()))
|
2011-11-02 01:14:12 +08:00
|
|
|
return ID;
|
2013-02-03 21:23:21 +08:00
|
|
|
if (const ObjCCategoryDecl *CD =
|
|
|
|
dyn_cast<ObjCCategoryDecl>(ND->getDeclContext()))
|
2011-11-02 01:14:12 +08:00
|
|
|
return CD->getClassInterface();
|
2013-02-03 21:23:21 +08:00
|
|
|
if (const ObjCImplDecl *IMD =
|
|
|
|
dyn_cast<ObjCImplDecl>(ND->getDeclContext()))
|
2011-11-02 01:14:12 +08:00
|
|
|
return IMD->getClassInterface();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-12-02 06:29:46 +08:00
|
|
|
/// \brief Get the copy initialization expression of VarDecl,or NULL if
|
|
|
|
/// none exists.
|
2010-12-03 01:02:11 +08:00
|
|
|
Expr *ASTContext::getBlockVarCopyInits(const VarDecl*VD) {
|
2010-12-07 01:28:17 +08:00
|
|
|
assert(VD && "Passed null params");
|
|
|
|
assert(VD->hasAttr<BlocksAttr>() &&
|
|
|
|
"getBlockVarCopyInits - not __block var");
|
2010-12-03 01:02:11 +08:00
|
|
|
llvm::DenseMap<const VarDecl*, Expr*>::iterator
|
2010-12-07 01:28:17 +08:00
|
|
|
I = BlockVarCopyInits.find(VD);
|
2010-12-02 06:29:46 +08:00
|
|
|
return (I != BlockVarCopyInits.end()) ? cast<Expr>(I->second) : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Set the copy inialization expression of a block var decl.
|
|
|
|
void ASTContext::setBlockVarCopyInits(VarDecl*VD, Expr* Init) {
|
|
|
|
assert(VD && Init && "Passed null params");
|
2010-12-07 01:28:17 +08:00
|
|
|
assert(VD->hasAttr<BlocksAttr>() &&
|
|
|
|
"setBlockVarCopyInits - not __block var");
|
2010-12-02 06:29:46 +08:00
|
|
|
BlockVarCopyInits[VD] = Init;
|
|
|
|
}
|
|
|
|
|
2009-12-07 10:54:59 +08:00
|
|
|
TypeSourceInfo *ASTContext::CreateTypeSourceInfo(QualType T,
|
2011-01-12 17:06:06 +08:00
|
|
|
unsigned DataSize) const {
|
2009-10-21 08:23:54 +08:00
|
|
|
if (!DataSize)
|
|
|
|
DataSize = TypeLoc::getFullDataSizeForType(T);
|
|
|
|
else
|
|
|
|
assert(DataSize == TypeLoc::getFullDataSizeForType(T) &&
|
2009-12-07 10:54:59 +08:00
|
|
|
"incorrect data size provided to CreateTypeSourceInfo!");
|
2009-10-21 08:23:54 +08:00
|
|
|
|
2009-12-07 10:54:59 +08:00
|
|
|
TypeSourceInfo *TInfo =
|
|
|
|
(TypeSourceInfo*)BumpAlloc.Allocate(sizeof(TypeSourceInfo) + DataSize, 8);
|
|
|
|
new (TInfo) TypeSourceInfo(T);
|
|
|
|
return TInfo;
|
2009-08-19 09:27:32 +08:00
|
|
|
}
|
|
|
|
|
2009-12-07 10:54:59 +08:00
|
|
|
TypeSourceInfo *ASTContext::getTrivialTypeSourceInfo(QualType T,
|
2011-01-20 04:10:05 +08:00
|
|
|
SourceLocation L) const {
|
2009-12-07 10:54:59 +08:00
|
|
|
TypeSourceInfo *DI = CreateTypeSourceInfo(T);
|
2011-01-26 03:13:18 +08:00
|
|
|
DI->getTypeLoc().initialize(const_cast<ASTContext &>(*this), L);
|
2009-10-24 05:14:09 +08:00
|
|
|
return DI;
|
|
|
|
}
|
|
|
|
|
2009-05-03 18:38:35 +08:00
|
|
|
const ASTRecordLayout &
|
2011-01-12 17:06:06 +08:00
|
|
|
ASTContext::getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const {
|
2009-05-03 18:38:35 +08:00
|
|
|
return getObjCLayout(D, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
const ASTRecordLayout &
|
2011-01-12 17:06:06 +08:00
|
|
|
ASTContext::getASTObjCImplementationLayout(
|
|
|
|
const ObjCImplementationDecl *D) const {
|
2009-05-03 18:38:35 +08:00
|
|
|
return getObjCLayout(D->getClassInterface(), D);
|
|
|
|
}
|
|
|
|
|
2007-07-14 06:13:22 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Type creation/memoization methods
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType
|
2011-01-19 18:06:00 +08:00
|
|
|
ASTContext::getExtQualType(const Type *baseType, Qualifiers quals) const {
|
|
|
|
unsigned fastQuals = quals.getFastQualifiers();
|
|
|
|
quals.removeFastQualifiers();
|
2009-09-25 03:53:00 +08:00
|
|
|
|
|
|
|
// Check if we've already instantiated this type.
|
|
|
|
llvm::FoldingSetNodeID ID;
|
2011-01-19 18:06:00 +08:00
|
|
|
ExtQuals::Profile(ID, baseType, quals);
|
|
|
|
void *insertPos = 0;
|
|
|
|
if (ExtQuals *eq = ExtQualNodes.FindNodeOrInsertPos(ID, insertPos)) {
|
|
|
|
assert(eq->getQualifiers() == quals);
|
|
|
|
return QualType(eq, fastQuals);
|
2009-09-25 03:53:00 +08:00
|
|
|
}
|
|
|
|
|
2011-01-19 18:06:00 +08:00
|
|
|
// If the base type is not canonical, make the appropriate canonical type.
|
|
|
|
QualType canon;
|
|
|
|
if (!baseType->isCanonicalUnqualified()) {
|
|
|
|
SplitQualType canonSplit = baseType->getCanonicalTypeInternal().split();
|
2012-02-08 08:46:36 +08:00
|
|
|
canonSplit.Quals.addConsistentQualifiers(quals);
|
|
|
|
canon = getExtQualType(canonSplit.Ty, canonSplit.Quals);
|
2011-01-19 18:06:00 +08:00
|
|
|
|
|
|
|
// Re-find the insert position.
|
|
|
|
(void) ExtQualNodes.FindNodeOrInsertPos(ID, insertPos);
|
|
|
|
}
|
|
|
|
|
|
|
|
ExtQuals *eq = new (*this, TypeAlignment) ExtQuals(baseType, canon, quals);
|
|
|
|
ExtQualNodes.InsertNode(eq, insertPos);
|
|
|
|
return QualType(eq, fastQuals);
|
2009-09-25 03:53:00 +08:00
|
|
|
}
|
|
|
|
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType
|
|
|
|
ASTContext::getAddrSpaceQualType(QualType T, unsigned AddressSpace) const {
|
2008-04-07 06:59:24 +08:00
|
|
|
QualType CanT = getCanonicalType(T);
|
|
|
|
if (CanT.getAddressSpace() == AddressSpace)
|
2008-02-21 04:55:12 +08:00
|
|
|
return T;
|
2009-02-19 06:53:11 +08:00
|
|
|
|
2009-09-25 03:53:00 +08:00
|
|
|
// If we are composing extended qualifiers together, merge together
|
|
|
|
// into one ExtQuals node.
|
|
|
|
QualifierCollector Quals;
|
|
|
|
const Type *TypeNode = Quals.strip(T);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-25 03:53:00 +08:00
|
|
|
// If this type already has an address space specified, it cannot get
|
|
|
|
// another one.
|
|
|
|
assert(!Quals.hasAddressSpace() &&
|
|
|
|
"Type cannot be in multiple addr spaces!");
|
|
|
|
Quals.addAddressSpace(AddressSpace);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-25 03:53:00 +08:00
|
|
|
return getExtQualType(TypeNode, Quals);
|
2008-02-04 10:31:56 +08:00
|
|
|
}
|
|
|
|
|
2009-02-19 06:53:11 +08:00
|
|
|
QualType ASTContext::getObjCGCQualType(QualType T,
|
2011-01-12 17:06:06 +08:00
|
|
|
Qualifiers::GC GCAttr) const {
|
2009-02-18 13:09:49 +08:00
|
|
|
QualType CanT = getCanonicalType(T);
|
2009-02-19 06:53:11 +08:00
|
|
|
if (CanT.getObjCGCAttr() == GCAttr)
|
2009-02-18 13:09:49 +08:00
|
|
|
return T;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-12-24 10:08:15 +08:00
|
|
|
if (const PointerType *ptr = T->getAs<PointerType>()) {
|
|
|
|
QualType Pointee = ptr->getPointeeType();
|
2009-07-15 02:25:06 +08:00
|
|
|
if (Pointee->isAnyPointerType()) {
|
2009-06-04 01:15:17 +08:00
|
|
|
QualType ResultType = getObjCGCQualType(Pointee, GCAttr);
|
|
|
|
return getPointerType(ResultType);
|
|
|
|
}
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-25 03:53:00 +08:00
|
|
|
// If we are composing extended qualifiers together, merge together
|
|
|
|
// into one ExtQuals node.
|
|
|
|
QualifierCollector Quals;
|
|
|
|
const Type *TypeNode = Quals.strip(T);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-25 03:53:00 +08:00
|
|
|
// If this type already has an ObjCGC specified, it cannot get
|
|
|
|
// another one.
|
|
|
|
assert(!Quals.hasObjCGCAttr() &&
|
|
|
|
"Type cannot have multiple ObjCGCs!");
|
|
|
|
Quals.addObjCGCAttr(GCAttr);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-25 03:53:00 +08:00
|
|
|
return getExtQualType(TypeNode, Quals);
|
2009-02-18 13:09:49 +08:00
|
|
|
}
|
2007-07-14 06:13:22 +08:00
|
|
|
|
2010-12-19 10:44:49 +08:00
|
|
|
const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T,
|
|
|
|
FunctionType::ExtInfo Info) {
|
|
|
|
if (T->getExtInfo() == Info)
|
|
|
|
return T;
|
|
|
|
|
|
|
|
QualType Result;
|
|
|
|
if (const FunctionNoProtoType *FNPT = dyn_cast<FunctionNoProtoType>(T)) {
|
|
|
|
Result = getFunctionNoProtoType(FNPT->getResultType(), Info);
|
|
|
|
} else {
|
|
|
|
const FunctionProtoType *FPT = cast<FunctionProtoType>(T);
|
|
|
|
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
|
|
|
|
EPI.ExtInfo = Info;
|
|
|
|
Result = getFunctionType(FPT->getResultType(), FPT->arg_type_begin(),
|
|
|
|
FPT->getNumArgs(), EPI);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cast<FunctionType>(Result.getTypePtr());
|
|
|
|
}
|
|
|
|
|
2007-06-23 04:56:16 +08:00
|
|
|
/// getComplexType - Return the uniqued reference to the type for a complex
|
|
|
|
/// number with the specified element type.
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType ASTContext::getComplexType(QualType T) const {
|
2007-06-23 04:56:16 +08:00
|
|
|
// Unique pointers, to guarantee there is only one pointer of a particular
|
|
|
|
// structure.
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
ComplexType::Profile(ID, T);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-06-23 04:56:16 +08:00
|
|
|
void *InsertPos = 0;
|
|
|
|
if (ComplexType *CT = ComplexTypes.FindNodeOrInsertPos(ID, InsertPos))
|
|
|
|
return QualType(CT, 0);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-06-23 04:56:16 +08:00
|
|
|
// If the pointee type isn't canonical, this won't be a canonical type either,
|
|
|
|
// so fill in the canonical type field.
|
|
|
|
QualType Canonical;
|
2009-10-23 04:10:53 +08:00
|
|
|
if (!T.isCanonical()) {
|
2008-04-07 06:59:24 +08:00
|
|
|
Canonical = getComplexType(getCanonicalType(T));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-06-23 04:56:16 +08:00
|
|
|
// Get the new insert position for the node we care about.
|
|
|
|
ComplexType *NewIP = ComplexTypes.FindNodeOrInsertPos(ID, InsertPos);
|
2010-12-23 09:01:28 +08:00
|
|
|
assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
|
2007-06-23 04:56:16 +08:00
|
|
|
}
|
2009-09-25 07:30:46 +08:00
|
|
|
ComplexType *New = new (*this, TypeAlignment) ComplexType(T, Canonical);
|
2007-06-23 04:56:16 +08:00
|
|
|
Types.push_back(New);
|
|
|
|
ComplexTypes.InsertNode(New, InsertPos);
|
|
|
|
return QualType(New, 0);
|
|
|
|
}
|
|
|
|
|
2006-11-12 08:37:36 +08:00
|
|
|
/// getPointerType - Return the uniqued reference to the type for a pointer to
|
|
|
|
/// the specified type.
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType ASTContext::getPointerType(QualType T) const {
|
2006-11-12 08:53:46 +08:00
|
|
|
// Unique pointers, to guarantee there is only one pointer of a particular
|
|
|
|
// structure.
|
2007-06-16 07:05:46 +08:00
|
|
|
llvm::FoldingSetNodeID ID;
|
2007-01-27 09:29:36 +08:00
|
|
|
PointerType::Profile(ID, T);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-01-27 09:29:36 +08:00
|
|
|
void *InsertPos = 0;
|
|
|
|
if (PointerType *PT = PointerTypes.FindNodeOrInsertPos(ID, InsertPos))
|
2007-04-06 06:36:20 +08:00
|
|
|
return QualType(PT, 0);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2006-11-12 16:50:50 +08:00
|
|
|
// If the pointee type isn't canonical, this won't be a canonical type either,
|
|
|
|
// so fill in the canonical type field.
|
2007-04-06 06:36:20 +08:00
|
|
|
QualType Canonical;
|
2009-10-23 04:10:53 +08:00
|
|
|
if (!T.isCanonical()) {
|
2008-04-07 06:59:24 +08:00
|
|
|
Canonical = getPointerType(getCanonicalType(T));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-01-27 09:29:36 +08:00
|
|
|
// Get the new insert position for the node we care about.
|
|
|
|
PointerType *NewIP = PointerTypes.FindNodeOrInsertPos(ID, InsertPos);
|
2010-12-23 09:01:28 +08:00
|
|
|
assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
|
2007-01-27 09:29:36 +08:00
|
|
|
}
|
2009-09-25 07:30:46 +08:00
|
|
|
PointerType *New = new (*this, TypeAlignment) PointerType(T, Canonical);
|
2007-01-27 09:29:36 +08:00
|
|
|
Types.push_back(New);
|
|
|
|
PointerTypes.InsertNode(New, InsertPos);
|
2007-04-06 06:36:20 +08:00
|
|
|
return QualType(New, 0);
|
2006-11-10 14:34:16 +08:00
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
/// getBlockPointerType - Return the uniqued reference to the type for
|
2008-08-28 00:04:49 +08:00
|
|
|
/// a pointer to the specified block.
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType ASTContext::getBlockPointerType(QualType T) const {
|
2008-08-29 03:20:44 +08:00
|
|
|
assert(T->isFunctionType() && "block of function types only");
|
|
|
|
// Unique pointers, to guarantee there is only one block of a particular
|
2008-08-28 00:04:49 +08:00
|
|
|
// structure.
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
BlockPointerType::Profile(ID, T);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-08-28 00:04:49 +08:00
|
|
|
void *InsertPos = 0;
|
|
|
|
if (BlockPointerType *PT =
|
|
|
|
BlockPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
|
|
|
|
return QualType(PT, 0);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
// If the block pointee type isn't canonical, this won't be a canonical
|
2008-08-28 00:04:49 +08:00
|
|
|
// type either so fill in the canonical type field.
|
|
|
|
QualType Canonical;
|
2009-10-23 04:10:53 +08:00
|
|
|
if (!T.isCanonical()) {
|
2008-08-28 00:04:49 +08:00
|
|
|
Canonical = getBlockPointerType(getCanonicalType(T));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-08-28 00:04:49 +08:00
|
|
|
// Get the new insert position for the node we care about.
|
|
|
|
BlockPointerType *NewIP =
|
|
|
|
BlockPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
|
2010-12-23 09:01:28 +08:00
|
|
|
assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
|
2008-08-28 00:04:49 +08:00
|
|
|
}
|
2009-09-25 07:30:46 +08:00
|
|
|
BlockPointerType *New
|
|
|
|
= new (*this, TypeAlignment) BlockPointerType(T, Canonical);
|
2008-08-28 00:04:49 +08:00
|
|
|
Types.push_back(New);
|
|
|
|
BlockPointerTypes.InsertNode(New, InsertPos);
|
|
|
|
return QualType(New, 0);
|
|
|
|
}
|
|
|
|
|
2009-03-17 07:22:08 +08:00
|
|
|
/// getLValueReferenceType - Return the uniqued reference to the type for an
|
|
|
|
/// lvalue reference to the specified type.
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType
|
|
|
|
ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) const {
|
2011-05-22 06:16:50 +08:00
|
|
|
assert(getCanonicalType(T) != OverloadTy &&
|
|
|
|
"Unresolved overloaded function type");
|
|
|
|
|
2007-05-27 18:15:43 +08:00
|
|
|
// Unique pointers, to guarantee there is only one pointer of a particular
|
|
|
|
// structure.
|
2007-06-16 07:05:46 +08:00
|
|
|
llvm::FoldingSetNodeID ID;
|
2009-10-23 06:37:11 +08:00
|
|
|
ReferenceType::Profile(ID, T, SpelledAsLValue);
|
2007-05-27 18:15:43 +08:00
|
|
|
|
|
|
|
void *InsertPos = 0;
|
2009-03-17 07:22:08 +08:00
|
|
|
if (LValueReferenceType *RT =
|
|
|
|
LValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos))
|
2007-05-27 18:15:43 +08:00
|
|
|
return QualType(RT, 0);
|
2009-03-17 07:22:08 +08:00
|
|
|
|
2009-10-23 06:37:11 +08:00
|
|
|
const ReferenceType *InnerRef = T->getAs<ReferenceType>();
|
|
|
|
|
2007-05-27 18:15:43 +08:00
|
|
|
// If the referencee type isn't canonical, this won't be a canonical type
|
|
|
|
// either, so fill in the canonical type field.
|
|
|
|
QualType Canonical;
|
2009-10-23 06:37:11 +08:00
|
|
|
if (!SpelledAsLValue || InnerRef || !T.isCanonical()) {
|
|
|
|
QualType PointeeType = (InnerRef ? InnerRef->getPointeeType() : T);
|
|
|
|
Canonical = getLValueReferenceType(getCanonicalType(PointeeType));
|
2009-03-17 07:22:08 +08:00
|
|
|
|
|
|
|
// Get the new insert position for the node we care about.
|
|
|
|
LValueReferenceType *NewIP =
|
|
|
|
LValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos);
|
2010-12-23 09:01:28 +08:00
|
|
|
assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
|
2009-03-17 07:22:08 +08:00
|
|
|
}
|
|
|
|
|
2009-09-25 07:30:46 +08:00
|
|
|
LValueReferenceType *New
|
2009-10-23 06:37:11 +08:00
|
|
|
= new (*this, TypeAlignment) LValueReferenceType(T, Canonical,
|
|
|
|
SpelledAsLValue);
|
2009-03-17 07:22:08 +08:00
|
|
|
Types.push_back(New);
|
|
|
|
LValueReferenceTypes.InsertNode(New, InsertPos);
|
2009-10-23 06:37:11 +08:00
|
|
|
|
2009-03-17 07:22:08 +08:00
|
|
|
return QualType(New, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getRValueReferenceType - Return the uniqued reference to the type for an
|
|
|
|
/// rvalue reference to the specified type.
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType ASTContext::getRValueReferenceType(QualType T) const {
|
2009-03-17 07:22:08 +08:00
|
|
|
// Unique pointers, to guarantee there is only one pointer of a particular
|
|
|
|
// structure.
|
|
|
|
llvm::FoldingSetNodeID ID;
|
2009-10-23 06:37:11 +08:00
|
|
|
ReferenceType::Profile(ID, T, false);
|
2009-03-17 07:22:08 +08:00
|
|
|
|
|
|
|
void *InsertPos = 0;
|
|
|
|
if (RValueReferenceType *RT =
|
|
|
|
RValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos))
|
|
|
|
return QualType(RT, 0);
|
|
|
|
|
2009-10-23 06:37:11 +08:00
|
|
|
const ReferenceType *InnerRef = T->getAs<ReferenceType>();
|
|
|
|
|
2009-03-17 07:22:08 +08:00
|
|
|
// If the referencee type isn't canonical, this won't be a canonical type
|
|
|
|
// either, so fill in the canonical type field.
|
|
|
|
QualType Canonical;
|
2009-10-23 06:37:11 +08:00
|
|
|
if (InnerRef || !T.isCanonical()) {
|
|
|
|
QualType PointeeType = (InnerRef ? InnerRef->getPointeeType() : T);
|
|
|
|
Canonical = getRValueReferenceType(getCanonicalType(PointeeType));
|
2009-03-17 07:22:08 +08:00
|
|
|
|
2007-05-27 18:15:43 +08:00
|
|
|
// Get the new insert position for the node we care about.
|
2009-03-17 07:22:08 +08:00
|
|
|
RValueReferenceType *NewIP =
|
|
|
|
RValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos);
|
2010-12-23 09:01:28 +08:00
|
|
|
assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
|
2007-05-27 18:15:43 +08:00
|
|
|
}
|
|
|
|
|
2009-09-25 07:30:46 +08:00
|
|
|
RValueReferenceType *New
|
|
|
|
= new (*this, TypeAlignment) RValueReferenceType(T, Canonical);
|
2007-05-27 18:15:43 +08:00
|
|
|
Types.push_back(New);
|
2009-03-17 07:22:08 +08:00
|
|
|
RValueReferenceTypes.InsertNode(New, InsertPos);
|
2007-05-27 18:15:43 +08:00
|
|
|
return QualType(New, 0);
|
|
|
|
}
|
|
|
|
|
2009-01-25 05:16:55 +08:00
|
|
|
/// getMemberPointerType - Return the uniqued reference to the type for a
|
|
|
|
/// member pointer to the specified type, in the specified class.
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) const {
|
2009-01-25 05:16:55 +08:00
|
|
|
// Unique pointers, to guarantee there is only one pointer of a particular
|
|
|
|
// structure.
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
MemberPointerType::Profile(ID, T, Cls);
|
|
|
|
|
|
|
|
void *InsertPos = 0;
|
|
|
|
if (MemberPointerType *PT =
|
|
|
|
MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
|
|
|
|
return QualType(PT, 0);
|
|
|
|
|
|
|
|
// If the pointee or class type isn't canonical, this won't be a canonical
|
|
|
|
// type either, so fill in the canonical type field.
|
|
|
|
QualType Canonical;
|
2009-11-05 00:49:01 +08:00
|
|
|
if (!T.isCanonical() || !Cls->isCanonicalUnqualified()) {
|
2009-01-25 05:16:55 +08:00
|
|
|
Canonical = getMemberPointerType(getCanonicalType(T),getCanonicalType(Cls));
|
|
|
|
|
|
|
|
// Get the new insert position for the node we care about.
|
|
|
|
MemberPointerType *NewIP =
|
|
|
|
MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
|
2010-12-23 09:01:28 +08:00
|
|
|
assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
|
2009-01-25 05:16:55 +08:00
|
|
|
}
|
2009-09-25 07:30:46 +08:00
|
|
|
MemberPointerType *New
|
|
|
|
= new (*this, TypeAlignment) MemberPointerType(T, Cls, Canonical);
|
2009-01-25 05:16:55 +08:00
|
|
|
Types.push_back(New);
|
|
|
|
MemberPointerTypes.InsertNode(New, InsertPos);
|
|
|
|
return QualType(New, 0);
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
/// getConstantArrayType - Return the unique reference to the type for an
|
2007-08-30 09:06:46 +08:00
|
|
|
/// array of the specified element type.
|
2009-09-09 23:08:12 +08:00
|
|
|
QualType ASTContext::getConstantArrayType(QualType EltTy,
|
2009-05-13 12:12:56 +08:00
|
|
|
const llvm::APInt &ArySizeIn,
|
2007-08-31 02:10:14 +08:00
|
|
|
ArrayType::ArraySizeModifier ASM,
|
2011-01-28 03:55:10 +08:00
|
|
|
unsigned IndexTypeQuals) const {
|
2009-11-05 23:52:31 +08:00
|
|
|
assert((EltTy->isDependentType() ||
|
|
|
|
EltTy->isIncompleteType() || EltTy->isConstantSizeType()) &&
|
2009-05-30 04:17:55 +08:00
|
|
|
"Constant array of VLAs is illegal!");
|
|
|
|
|
2009-05-13 12:12:56 +08:00
|
|
|
// Convert the array size into a canonical width matching the pointer size for
|
|
|
|
// the target.
|
|
|
|
llvm::APInt ArySize(ArySizeIn);
|
2010-12-07 16:25:34 +08:00
|
|
|
ArySize =
|
2011-09-02 08:18:52 +08:00
|
|
|
ArySize.zextOrTrunc(Target->getPointerWidth(getTargetAddressSpace(EltTy)));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-06-16 07:05:46 +08:00
|
|
|
llvm::FoldingSetNodeID ID;
|
2011-01-28 03:55:10 +08:00
|
|
|
ConstantArrayType::Profile(ID, EltTy, ArySize, ASM, IndexTypeQuals);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-01-27 16:31:04 +08:00
|
|
|
void *InsertPos = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
if (ConstantArrayType *ATP =
|
2007-11-01 01:10:13 +08:00
|
|
|
ConstantArrayTypes.FindNodeOrInsertPos(ID, InsertPos))
|
2007-04-06 06:36:20 +08:00
|
|
|
return QualType(ATP, 0);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-01-19 18:06:00 +08:00
|
|
|
// If the element type isn't canonical or has qualifiers, this won't
|
|
|
|
// be a canonical type either, so fill in the canonical type field.
|
|
|
|
QualType Canon;
|
|
|
|
if (!EltTy.isCanonical() || EltTy.hasLocalQualifiers()) {
|
|
|
|
SplitQualType canonSplit = getCanonicalType(EltTy).split();
|
2012-02-08 08:46:36 +08:00
|
|
|
Canon = getConstantArrayType(QualType(canonSplit.Ty, 0), ArySize,
|
2011-01-28 03:55:10 +08:00
|
|
|
ASM, IndexTypeQuals);
|
2012-02-08 08:46:36 +08:00
|
|
|
Canon = getQualifiedType(Canon, canonSplit.Quals);
|
2011-01-19 18:06:00 +08:00
|
|
|
|
2007-01-27 16:31:04 +08:00
|
|
|
// Get the new insert position for the node we care about.
|
2009-09-09 23:08:12 +08:00
|
|
|
ConstantArrayType *NewIP =
|
2007-11-01 01:10:13 +08:00
|
|
|
ConstantArrayTypes.FindNodeOrInsertPos(ID, InsertPos);
|
2010-12-23 09:01:28 +08:00
|
|
|
assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
|
2007-01-27 16:31:04 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-25 07:30:46 +08:00
|
|
|
ConstantArrayType *New = new(*this,TypeAlignment)
|
2011-01-28 03:55:10 +08:00
|
|
|
ConstantArrayType(EltTy, Canon, ArySize, ASM, IndexTypeQuals);
|
2007-11-01 01:10:13 +08:00
|
|
|
ConstantArrayTypes.InsertNode(New, InsertPos);
|
2007-01-27 16:31:04 +08:00
|
|
|
Types.push_back(New);
|
2007-04-06 06:36:20 +08:00
|
|
|
return QualType(New, 0);
|
2006-11-12 16:50:50 +08:00
|
|
|
}
|
|
|
|
|
2011-01-18 16:40:38 +08:00
|
|
|
/// getVariableArrayDecayedType - Turns the given type, which may be
|
|
|
|
/// variably-modified, into the corresponding type with all the known
|
|
|
|
/// sizes replaced with [*].
|
|
|
|
QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
|
|
|
|
// Vastly most common case.
|
|
|
|
if (!type->isVariablyModifiedType()) return type;
|
|
|
|
|
|
|
|
QualType result;
|
|
|
|
|
|
|
|
SplitQualType split = type.getSplitDesugaredType();
|
2012-02-08 08:46:36 +08:00
|
|
|
const Type *ty = split.Ty;
|
2011-01-18 16:40:38 +08:00
|
|
|
switch (ty->getTypeClass()) {
|
|
|
|
#define TYPE(Class, Base)
|
|
|
|
#define ABSTRACT_TYPE(Class, Base)
|
|
|
|
#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
|
|
|
|
#include "clang/AST/TypeNodes.def"
|
|
|
|
llvm_unreachable("didn't desugar past all non-canonical types?");
|
|
|
|
|
|
|
|
// These types should never be variably-modified.
|
|
|
|
case Type::Builtin:
|
|
|
|
case Type::Complex:
|
|
|
|
case Type::Vector:
|
|
|
|
case Type::ExtVector:
|
|
|
|
case Type::DependentSizedExtVector:
|
|
|
|
case Type::ObjCObject:
|
|
|
|
case Type::ObjCInterface:
|
|
|
|
case Type::ObjCObjectPointer:
|
|
|
|
case Type::Record:
|
|
|
|
case Type::Enum:
|
|
|
|
case Type::UnresolvedUsing:
|
|
|
|
case Type::TypeOfExpr:
|
|
|
|
case Type::TypeOf:
|
|
|
|
case Type::Decltype:
|
2011-05-25 06:41:36 +08:00
|
|
|
case Type::UnaryTransform:
|
2011-01-18 16:40:38 +08:00
|
|
|
case Type::DependentName:
|
|
|
|
case Type::InjectedClassName:
|
|
|
|
case Type::TemplateSpecialization:
|
|
|
|
case Type::DependentTemplateSpecialization:
|
|
|
|
case Type::TemplateTypeParm:
|
|
|
|
case Type::SubstTemplateTypeParmPack:
|
2011-02-20 11:19:35 +08:00
|
|
|
case Type::Auto:
|
2011-01-18 16:40:38 +08:00
|
|
|
case Type::PackExpansion:
|
|
|
|
llvm_unreachable("type should never be variably-modified");
|
|
|
|
|
|
|
|
// These types can be variably-modified but should never need to
|
|
|
|
// further decay.
|
|
|
|
case Type::FunctionNoProto:
|
|
|
|
case Type::FunctionProto:
|
|
|
|
case Type::BlockPointer:
|
|
|
|
case Type::MemberPointer:
|
|
|
|
return type;
|
|
|
|
|
|
|
|
// These types can be variably-modified. All these modifications
|
|
|
|
// preserve structure except as noted by comments.
|
|
|
|
// TODO: if we ever care about optimizing VLAs, there are no-op
|
|
|
|
// optimizations available here.
|
|
|
|
case Type::Pointer:
|
|
|
|
result = getPointerType(getVariableArrayDecayedType(
|
|
|
|
cast<PointerType>(ty)->getPointeeType()));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Type::LValueReference: {
|
|
|
|
const LValueReferenceType *lv = cast<LValueReferenceType>(ty);
|
|
|
|
result = getLValueReferenceType(
|
|
|
|
getVariableArrayDecayedType(lv->getPointeeType()),
|
|
|
|
lv->isSpelledAsLValue());
|
|
|
|
break;
|
2010-09-25 01:30:16 +08:00
|
|
|
}
|
2011-01-18 16:40:38 +08:00
|
|
|
|
|
|
|
case Type::RValueReference: {
|
|
|
|
const RValueReferenceType *lv = cast<RValueReferenceType>(ty);
|
|
|
|
result = getRValueReferenceType(
|
|
|
|
getVariableArrayDecayedType(lv->getPointeeType()));
|
|
|
|
break;
|
2010-09-25 01:30:16 +08:00
|
|
|
}
|
|
|
|
|
2011-10-07 07:00:33 +08:00
|
|
|
case Type::Atomic: {
|
|
|
|
const AtomicType *at = cast<AtomicType>(ty);
|
|
|
|
result = getAtomicType(getVariableArrayDecayedType(at->getValueType()));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-01-18 16:40:38 +08:00
|
|
|
case Type::ConstantArray: {
|
|
|
|
const ConstantArrayType *cat = cast<ConstantArrayType>(ty);
|
|
|
|
result = getConstantArrayType(
|
|
|
|
getVariableArrayDecayedType(cat->getElementType()),
|
|
|
|
cat->getSize(),
|
|
|
|
cat->getSizeModifier(),
|
|
|
|
cat->getIndexTypeCVRQualifiers());
|
|
|
|
break;
|
2010-09-25 01:30:16 +08:00
|
|
|
}
|
|
|
|
|
2011-01-18 16:40:38 +08:00
|
|
|
case Type::DependentSizedArray: {
|
|
|
|
const DependentSizedArrayType *dat = cast<DependentSizedArrayType>(ty);
|
|
|
|
result = getDependentSizedArrayType(
|
|
|
|
getVariableArrayDecayedType(dat->getElementType()),
|
|
|
|
dat->getSizeExpr(),
|
|
|
|
dat->getSizeModifier(),
|
|
|
|
dat->getIndexTypeCVRQualifiers(),
|
|
|
|
dat->getBracketsRange());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Turn incomplete types into [*] types.
|
|
|
|
case Type::IncompleteArray: {
|
|
|
|
const IncompleteArrayType *iat = cast<IncompleteArrayType>(ty);
|
|
|
|
result = getVariableArrayType(
|
|
|
|
getVariableArrayDecayedType(iat->getElementType()),
|
|
|
|
/*size*/ 0,
|
|
|
|
ArrayType::Normal,
|
|
|
|
iat->getIndexTypeCVRQualifiers(),
|
|
|
|
SourceRange());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Turn VLA types into [*] types.
|
|
|
|
case Type::VariableArray: {
|
|
|
|
const VariableArrayType *vat = cast<VariableArrayType>(ty);
|
|
|
|
result = getVariableArrayType(
|
|
|
|
getVariableArrayDecayedType(vat->getElementType()),
|
|
|
|
/*size*/ 0,
|
|
|
|
ArrayType::Star,
|
|
|
|
vat->getIndexTypeCVRQualifiers(),
|
|
|
|
vat->getBracketsRange());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Apply the top-level qualifiers from the original.
|
2012-02-08 08:46:36 +08:00
|
|
|
return getQualifiedType(result, split.Quals);
|
2011-01-18 16:40:38 +08:00
|
|
|
}
|
2010-09-25 01:30:16 +08:00
|
|
|
|
2007-08-31 02:14:25 +08:00
|
|
|
/// getVariableArrayType - Returns a non-unique reference to the type for a
|
|
|
|
/// variable array of the specified element type.
|
2009-07-06 23:59:29 +08:00
|
|
|
QualType ASTContext::getVariableArrayType(QualType EltTy,
|
|
|
|
Expr *NumElts,
|
2007-08-31 02:10:14 +08:00
|
|
|
ArrayType::ArraySizeModifier ASM,
|
2011-01-28 03:55:10 +08:00
|
|
|
unsigned IndexTypeQuals,
|
2011-01-12 17:06:06 +08:00
|
|
|
SourceRange Brackets) const {
|
2008-02-16 02:16:39 +08:00
|
|
|
// Since we don't unique expressions, it isn't possible to unique VLA's
|
|
|
|
// that have an expression provided for their size.
|
2011-01-19 18:06:00 +08:00
|
|
|
QualType Canon;
|
2010-05-24 00:10:32 +08:00
|
|
|
|
2011-01-19 18:06:00 +08:00
|
|
|
// Be sure to pull qualifiers off the element type.
|
|
|
|
if (!EltTy.isCanonical() || EltTy.hasLocalQualifiers()) {
|
|
|
|
SplitQualType canonSplit = getCanonicalType(EltTy).split();
|
2012-02-08 08:46:36 +08:00
|
|
|
Canon = getVariableArrayType(QualType(canonSplit.Ty, 0), NumElts, ASM,
|
2011-01-28 03:55:10 +08:00
|
|
|
IndexTypeQuals, Brackets);
|
2012-02-08 08:46:36 +08:00
|
|
|
Canon = getQualifiedType(Canon, canonSplit.Quals);
|
2010-05-24 00:10:32 +08:00
|
|
|
}
|
|
|
|
|
2009-09-25 07:30:46 +08:00
|
|
|
VariableArrayType *New = new(*this, TypeAlignment)
|
2011-01-28 03:55:10 +08:00
|
|
|
VariableArrayType(EltTy, Canon, NumElts, ASM, IndexTypeQuals, Brackets);
|
2008-02-16 02:16:39 +08:00
|
|
|
|
|
|
|
VariableArrayTypes.push_back(New);
|
|
|
|
Types.push_back(New);
|
|
|
|
return QualType(New, 0);
|
|
|
|
}
|
|
|
|
|
2008-12-06 07:32:09 +08:00
|
|
|
/// getDependentSizedArrayType - Returns a non-unique reference to
|
|
|
|
/// the type for a dependently-sized array of the specified element
|
2009-07-31 08:23:35 +08:00
|
|
|
/// type.
|
2011-01-19 18:06:00 +08:00
|
|
|
QualType ASTContext::getDependentSizedArrayType(QualType elementType,
|
|
|
|
Expr *numElements,
|
2008-12-06 07:32:09 +08:00
|
|
|
ArrayType::ArraySizeModifier ASM,
|
2011-01-19 18:06:00 +08:00
|
|
|
unsigned elementTypeQuals,
|
|
|
|
SourceRange brackets) const {
|
|
|
|
assert((!numElements || numElements->isTypeDependent() ||
|
|
|
|
numElements->isValueDependent()) &&
|
2008-12-06 07:32:09 +08:00
|
|
|
"Size must be type- or value-dependent!");
|
|
|
|
|
2011-01-19 18:06:00 +08:00
|
|
|
// Dependently-sized array types that do not have a specified number
|
|
|
|
// of elements will have their sizes deduced from a dependent
|
|
|
|
// initializer. We do no canonicalization here at all, which is okay
|
|
|
|
// because they can't be used in most locations.
|
|
|
|
if (!numElements) {
|
|
|
|
DependentSizedArrayType *newType
|
|
|
|
= new (*this, TypeAlignment)
|
|
|
|
DependentSizedArrayType(*this, elementType, QualType(),
|
|
|
|
numElements, ASM, elementTypeQuals,
|
|
|
|
brackets);
|
|
|
|
Types.push_back(newType);
|
|
|
|
return QualType(newType, 0);
|
2009-11-20 02:03:26 +08:00
|
|
|
}
|
|
|
|
|
2011-01-19 18:06:00 +08:00
|
|
|
// Otherwise, we actually build a new type every time, but we
|
|
|
|
// also build a canonical type.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-01-19 18:06:00 +08:00
|
|
|
SplitQualType canonElementType = getCanonicalType(elementType).split();
|
2008-12-06 07:32:09 +08:00
|
|
|
|
2011-01-19 18:06:00 +08:00
|
|
|
void *insertPos = 0;
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
DependentSizedArrayType::Profile(ID, *this,
|
2012-02-08 08:46:36 +08:00
|
|
|
QualType(canonElementType.Ty, 0),
|
2011-01-19 18:06:00 +08:00
|
|
|
ASM, elementTypeQuals, numElements);
|
|
|
|
|
|
|
|
// Look for an existing type with these properties.
|
|
|
|
DependentSizedArrayType *canonTy =
|
|
|
|
DependentSizedArrayTypes.FindNodeOrInsertPos(ID, insertPos);
|
|
|
|
|
|
|
|
// If we don't have one, build one.
|
|
|
|
if (!canonTy) {
|
|
|
|
canonTy = new (*this, TypeAlignment)
|
2012-02-08 08:46:36 +08:00
|
|
|
DependentSizedArrayType(*this, QualType(canonElementType.Ty, 0),
|
2011-01-19 18:06:00 +08:00
|
|
|
QualType(), numElements, ASM, elementTypeQuals,
|
|
|
|
brackets);
|
|
|
|
DependentSizedArrayTypes.InsertNode(canonTy, insertPos);
|
|
|
|
Types.push_back(canonTy);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Apply qualifiers from the element type to the array.
|
|
|
|
QualType canon = getQualifiedType(QualType(canonTy,0),
|
2012-02-08 08:46:36 +08:00
|
|
|
canonElementType.Quals);
|
2011-01-19 18:06:00 +08:00
|
|
|
|
|
|
|
// If we didn't need extra canonicalization for the element type,
|
|
|
|
// then just use that as our result.
|
2012-02-08 08:46:36 +08:00
|
|
|
if (QualType(canonElementType.Ty, 0) == elementType)
|
2011-01-19 18:06:00 +08:00
|
|
|
return canon;
|
|
|
|
|
|
|
|
// Otherwise, we need to build a type which follows the spelling
|
|
|
|
// of the element type.
|
|
|
|
DependentSizedArrayType *sugaredType
|
|
|
|
= new (*this, TypeAlignment)
|
|
|
|
DependentSizedArrayType(*this, elementType, canon, numElements,
|
|
|
|
ASM, elementTypeQuals, brackets);
|
|
|
|
Types.push_back(sugaredType);
|
|
|
|
return QualType(sugaredType, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType ASTContext::getIncompleteArrayType(QualType elementType,
|
2008-02-16 02:16:39 +08:00
|
|
|
ArrayType::ArraySizeModifier ASM,
|
2011-01-19 18:06:00 +08:00
|
|
|
unsigned elementTypeQuals) const {
|
2008-02-16 02:16:39 +08:00
|
|
|
llvm::FoldingSetNodeID ID;
|
2011-01-19 18:06:00 +08:00
|
|
|
IncompleteArrayType::Profile(ID, elementType, ASM, elementTypeQuals);
|
2008-02-16 02:16:39 +08:00
|
|
|
|
2011-01-19 18:06:00 +08:00
|
|
|
void *insertPos = 0;
|
|
|
|
if (IncompleteArrayType *iat =
|
|
|
|
IncompleteArrayTypes.FindNodeOrInsertPos(ID, insertPos))
|
|
|
|
return QualType(iat, 0);
|
2008-02-16 02:16:39 +08:00
|
|
|
|
|
|
|
// If the element type isn't canonical, this won't be a canonical type
|
2011-01-19 18:06:00 +08:00
|
|
|
// either, so fill in the canonical type field. We also have to pull
|
|
|
|
// qualifiers off the element type.
|
|
|
|
QualType canon;
|
2008-02-16 02:16:39 +08:00
|
|
|
|
2011-01-19 18:06:00 +08:00
|
|
|
if (!elementType.isCanonical() || elementType.hasLocalQualifiers()) {
|
|
|
|
SplitQualType canonSplit = getCanonicalType(elementType).split();
|
2012-02-08 08:46:36 +08:00
|
|
|
canon = getIncompleteArrayType(QualType(canonSplit.Ty, 0),
|
2011-01-19 18:06:00 +08:00
|
|
|
ASM, elementTypeQuals);
|
2012-02-08 08:46:36 +08:00
|
|
|
canon = getQualifiedType(canon, canonSplit.Quals);
|
2008-02-16 02:16:39 +08:00
|
|
|
|
|
|
|
// Get the new insert position for the node we care about.
|
2011-01-19 18:06:00 +08:00
|
|
|
IncompleteArrayType *existing =
|
|
|
|
IncompleteArrayTypes.FindNodeOrInsertPos(ID, insertPos);
|
|
|
|
assert(!existing && "Shouldn't be in the map!"); (void) existing;
|
2007-10-30 07:37:31 +08:00
|
|
|
}
|
2008-02-16 02:16:39 +08:00
|
|
|
|
2011-01-19 18:06:00 +08:00
|
|
|
IncompleteArrayType *newType = new (*this, TypeAlignment)
|
|
|
|
IncompleteArrayType(elementType, canon, ASM, elementTypeQuals);
|
2008-02-16 02:16:39 +08:00
|
|
|
|
2011-01-19 18:06:00 +08:00
|
|
|
IncompleteArrayTypes.InsertNode(newType, insertPos);
|
|
|
|
Types.push_back(newType);
|
|
|
|
return QualType(newType, 0);
|
2007-08-30 09:06:46 +08:00
|
|
|
}
|
|
|
|
|
2007-07-19 02:00:27 +08:00
|
|
|
/// getVectorType - Return the unique reference to a vector type of
|
|
|
|
/// the specified element type and size. VectorType must be a built-in type.
|
2010-02-05 08:12:22 +08:00
|
|
|
QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts,
|
2011-01-12 17:06:06 +08:00
|
|
|
VectorType::VectorKind VecKind) const {
|
2011-01-19 18:06:00 +08:00
|
|
|
assert(vecType->isBuiltinType());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-07-07 07:09:18 +08:00
|
|
|
// Check if we've already instantiated a vector of this type.
|
|
|
|
llvm::FoldingSetNodeID ID;
|
2010-11-11 05:56:12 +08:00
|
|
|
VectorType::Profile(ID, vecType, NumElts, Type::Vector, VecKind);
|
2010-06-23 14:00:24 +08:00
|
|
|
|
2007-07-07 07:09:18 +08:00
|
|
|
void *InsertPos = 0;
|
|
|
|
if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos))
|
|
|
|
return QualType(VTP, 0);
|
|
|
|
|
|
|
|
// If the element type isn't canonical, this won't be a canonical type either,
|
|
|
|
// so fill in the canonical type field.
|
|
|
|
QualType Canonical;
|
2010-08-06 18:14:59 +08:00
|
|
|
if (!vecType.isCanonical()) {
|
2010-11-16 08:32:20 +08:00
|
|
|
Canonical = getVectorType(getCanonicalType(vecType), NumElts, VecKind);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-07-07 07:09:18 +08:00
|
|
|
// Get the new insert position for the node we care about.
|
|
|
|
VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos);
|
2010-12-23 09:01:28 +08:00
|
|
|
assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
|
2007-07-07 07:09:18 +08:00
|
|
|
}
|
2009-09-25 07:30:46 +08:00
|
|
|
VectorType *New = new (*this, TypeAlignment)
|
2010-11-11 05:56:12 +08:00
|
|
|
VectorType(vecType, NumElts, Canonical, VecKind);
|
2007-07-07 07:09:18 +08:00
|
|
|
VectorTypes.InsertNode(New, InsertPos);
|
|
|
|
Types.push_back(New);
|
|
|
|
return QualType(New, 0);
|
|
|
|
}
|
|
|
|
|
2008-04-19 07:10:10 +08:00
|
|
|
/// getExtVectorType - Return the unique reference to an extended vector type of
|
2007-07-19 02:00:27 +08:00
|
|
|
/// the specified element type and size. VectorType must be a built-in type.
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType
|
|
|
|
ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) const {
|
2011-06-16 00:02:29 +08:00
|
|
|
assert(vecType->isBuiltinType() || vecType->isDependentType());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-07-19 02:00:27 +08:00
|
|
|
// Check if we've already instantiated a vector of this type.
|
|
|
|
llvm::FoldingSetNodeID ID;
|
2010-06-23 14:00:24 +08:00
|
|
|
VectorType::Profile(ID, vecType, NumElts, Type::ExtVector,
|
2010-11-11 05:56:12 +08:00
|
|
|
VectorType::GenericVector);
|
2007-07-19 02:00:27 +08:00
|
|
|
void *InsertPos = 0;
|
|
|
|
if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos))
|
|
|
|
return QualType(VTP, 0);
|
|
|
|
|
|
|
|
// If the element type isn't canonical, this won't be a canonical type either,
|
|
|
|
// so fill in the canonical type field.
|
|
|
|
QualType Canonical;
|
2009-10-23 04:10:53 +08:00
|
|
|
if (!vecType.isCanonical()) {
|
2008-04-19 07:10:10 +08:00
|
|
|
Canonical = getExtVectorType(getCanonicalType(vecType), NumElts);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-07-19 02:00:27 +08:00
|
|
|
// Get the new insert position for the node we care about.
|
|
|
|
VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos);
|
2010-12-23 09:01:28 +08:00
|
|
|
assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
|
2007-07-19 02:00:27 +08:00
|
|
|
}
|
2009-09-25 07:30:46 +08:00
|
|
|
ExtVectorType *New = new (*this, TypeAlignment)
|
|
|
|
ExtVectorType(vecType, NumElts, Canonical);
|
2007-07-19 02:00:27 +08:00
|
|
|
VectorTypes.InsertNode(New, InsertPos);
|
|
|
|
Types.push_back(New);
|
|
|
|
return QualType(New, 0);
|
|
|
|
}
|
|
|
|
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType
|
|
|
|
ASTContext::getDependentSizedExtVectorType(QualType vecType,
|
|
|
|
Expr *SizeExpr,
|
|
|
|
SourceLocation AttrLoc) const {
|
2009-07-31 11:54:25 +08:00
|
|
|
llvm::FoldingSetNodeID ID;
|
2009-09-09 23:08:12 +08:00
|
|
|
DependentSizedExtVectorType::Profile(ID, *this, getCanonicalType(vecType),
|
2009-07-31 11:54:25 +08:00
|
|
|
SizeExpr);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-31 11:54:25 +08:00
|
|
|
void *InsertPos = 0;
|
|
|
|
DependentSizedExtVectorType *Canon
|
|
|
|
= DependentSizedExtVectorTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
DependentSizedExtVectorType *New;
|
|
|
|
if (Canon) {
|
|
|
|
// We already have a canonical version of this array type; use it as
|
|
|
|
// the canonical type for a newly-built type.
|
2009-09-25 07:30:46 +08:00
|
|
|
New = new (*this, TypeAlignment)
|
|
|
|
DependentSizedExtVectorType(*this, vecType, QualType(Canon, 0),
|
|
|
|
SizeExpr, AttrLoc);
|
2009-07-31 11:54:25 +08:00
|
|
|
} else {
|
|
|
|
QualType CanonVecTy = getCanonicalType(vecType);
|
|
|
|
if (CanonVecTy == vecType) {
|
2009-09-25 07:30:46 +08:00
|
|
|
New = new (*this, TypeAlignment)
|
|
|
|
DependentSizedExtVectorType(*this, vecType, QualType(), SizeExpr,
|
|
|
|
AttrLoc);
|
Fix an obscure crash found in the Boost.MPL test suite, along with a
ton of potential crashes of the same kind. The fundamental problem is
that type creation was following a dangerous pattern when using its
FoldingSets:
1) Use FindNodeOrInsertPos to see if the type is available
2) If not, and we aren't looking at a canonical type, build the
canonical type
3) Build and insert the new node into the FoldingSet
The problem here is that building the canonical type can, in very rare
circumstances, force the hash table inside the FoldingSet to
reallocate. That invalidates the insertion position we computed in
step 1, and in step 3 we end up inserting the new node into the wrong
place. BOOM!
I've audited all of ASTContext, fixing this problem everywhere I found
it. The vast majority of wrong code was C++-specific (and *ahem*
written by me), so I also audited other major folding sets in the C++
code (e.g., template specializations), but found no other instances of
this problem.
llvm-svn: 95315
2010-02-05 02:10:26 +08:00
|
|
|
|
|
|
|
DependentSizedExtVectorType *CanonCheck
|
|
|
|
= DependentSizedExtVectorTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
assert(!CanonCheck && "Dependent-sized ext_vector canonical type broken");
|
|
|
|
(void)CanonCheck;
|
2009-07-31 11:54:25 +08:00
|
|
|
DependentSizedExtVectorTypes.InsertNode(New, InsertPos);
|
|
|
|
} else {
|
|
|
|
QualType Canon = getDependentSizedExtVectorType(CanonVecTy, SizeExpr,
|
|
|
|
SourceLocation());
|
2009-09-25 07:30:46 +08:00
|
|
|
New = new (*this, TypeAlignment)
|
|
|
|
DependentSizedExtVectorType(*this, vecType, Canon, SizeExpr, AttrLoc);
|
2009-07-31 11:54:25 +08:00
|
|
|
}
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-18 05:51:59 +08:00
|
|
|
Types.push_back(New);
|
|
|
|
return QualType(New, 0);
|
|
|
|
}
|
|
|
|
|
2009-02-27 07:50:07 +08:00
|
|
|
/// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.
|
2006-12-02 15:52:18 +08:00
|
|
|
///
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType
|
|
|
|
ASTContext::getFunctionNoProtoType(QualType ResultTy,
|
|
|
|
const FunctionType::ExtInfo &Info) const {
|
2011-03-02 01:40:53 +08:00
|
|
|
const CallingConv DefaultCC = Info.getCC();
|
|
|
|
const CallingConv CallConv = (LangOpts.MRTD && DefaultCC == CC_Default) ?
|
|
|
|
CC_X86StdCall : DefaultCC;
|
2006-12-02 15:52:18 +08:00
|
|
|
// Unique functions, to guarantee there is only one function of a particular
|
|
|
|
// structure.
|
2007-06-16 07:05:46 +08:00
|
|
|
llvm::FoldingSetNodeID ID;
|
2010-03-31 04:24:48 +08:00
|
|
|
FunctionNoProtoType::Profile(ID, ResultTy, Info);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-01-27 16:37:20 +08:00
|
|
|
void *InsertPos = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
if (FunctionNoProtoType *FT =
|
2009-02-27 07:50:07 +08:00
|
|
|
FunctionNoProtoTypes.FindNodeOrInsertPos(ID, InsertPos))
|
2007-04-06 06:36:20 +08:00
|
|
|
return QualType(FT, 0);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-04-06 06:36:20 +08:00
|
|
|
QualType Canonical;
|
2010-01-19 01:14:39 +08:00
|
|
|
if (!ResultTy.isCanonical() ||
|
2010-02-06 05:31:56 +08:00
|
|
|
getCanonicalCallConv(CallConv) != CallConv) {
|
2010-03-31 04:24:48 +08:00
|
|
|
Canonical =
|
|
|
|
getFunctionNoProtoType(getCanonicalType(ResultTy),
|
|
|
|
Info.withCallingConv(getCanonicalCallConv(CallConv)));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-01-27 16:37:20 +08:00
|
|
|
// Get the new insert position for the node we care about.
|
2009-02-27 07:50:07 +08:00
|
|
|
FunctionNoProtoType *NewIP =
|
|
|
|
FunctionNoProtoTypes.FindNodeOrInsertPos(ID, InsertPos);
|
2010-12-23 09:01:28 +08:00
|
|
|
assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
|
2007-01-27 16:37:20 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-03-02 01:40:53 +08:00
|
|
|
FunctionProtoType::ExtInfo newInfo = Info.withCallingConv(CallConv);
|
2009-09-25 07:30:46 +08:00
|
|
|
FunctionNoProtoType *New = new (*this, TypeAlignment)
|
2011-03-02 01:40:53 +08:00
|
|
|
FunctionNoProtoType(ResultTy, Canonical, newInfo);
|
2007-01-27 16:37:20 +08:00
|
|
|
Types.push_back(New);
|
2009-02-27 07:50:07 +08:00
|
|
|
FunctionNoProtoTypes.InsertNode(New, InsertPos);
|
2007-04-06 06:36:20 +08:00
|
|
|
return QualType(New, 0);
|
2006-12-02 15:52:18 +08:00
|
|
|
}
|
|
|
|
|
2013-01-18 07:36:45 +08:00
|
|
|
/// \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);
|
|
|
|
}
|
|
|
|
|
2006-12-02 15:52:18 +08:00
|
|
|
/// getFunctionType - Return a normal function type with a typed argument
|
|
|
|
/// list. isVariadic indicates whether the argument list includes '...'.
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType
|
|
|
|
ASTContext::getFunctionType(QualType ResultTy,
|
|
|
|
const QualType *ArgArray, unsigned NumArgs,
|
|
|
|
const FunctionProtoType::ExtProtoInfo &EPI) const {
|
2006-12-02 15:52:18 +08:00
|
|
|
// Unique functions, to guarantee there is only one function of a particular
|
|
|
|
// structure.
|
2007-06-16 07:05:46 +08:00
|
|
|
llvm::FoldingSetNodeID ID;
|
2011-03-14 01:09:40 +08:00
|
|
|
FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, EPI, *this);
|
2007-01-27 09:15:32 +08:00
|
|
|
|
|
|
|
void *InsertPos = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
if (FunctionProtoType *FTP =
|
2009-02-27 07:50:07 +08:00
|
|
|
FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos))
|
2007-04-06 06:36:20 +08:00
|
|
|
return QualType(FTP, 0);
|
2009-05-28 06:11:52 +08:00
|
|
|
|
|
|
|
// Determine whether the type being created is already canonical or not.
|
2012-02-10 17:58:53 +08:00
|
|
|
bool isCanonical =
|
2013-01-18 07:36:45 +08:00
|
|
|
EPI.ExceptionSpecType == EST_None && isCanonicalResultType(ResultTy) &&
|
2012-02-10 17:58:53 +08:00
|
|
|
!EPI.HasTrailingReturn;
|
2006-12-02 15:52:18 +08:00
|
|
|
for (unsigned i = 0; i != NumArgs && isCanonical; ++i)
|
2009-10-23 06:37:11 +08:00
|
|
|
if (!ArgArray[i].isCanonicalAsParam())
|
2006-12-02 15:52:18 +08:00
|
|
|
isCanonical = false;
|
|
|
|
|
2011-03-02 01:40:53 +08:00
|
|
|
const CallingConv DefaultCC = EPI.ExtInfo.getCC();
|
|
|
|
const CallingConv CallConv = (LangOpts.MRTD && DefaultCC == CC_Default) ?
|
|
|
|
CC_X86StdCall : DefaultCC;
|
2010-12-14 16:05:40 +08:00
|
|
|
|
2006-12-02 15:52:18 +08:00
|
|
|
// If this type isn't canonical, get the canonical version of it.
|
2009-05-28 06:11:52 +08:00
|
|
|
// The exception spec is not part of the canonical type.
|
2007-04-06 06:36:20 +08:00
|
|
|
QualType Canonical;
|
2010-02-06 05:31:56 +08:00
|
|
|
if (!isCanonical || getCanonicalCallConv(CallConv) != CallConv) {
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<QualType, 16> CanonicalArgs;
|
2006-12-02 15:52:18 +08:00
|
|
|
CanonicalArgs.reserve(NumArgs);
|
|
|
|
for (unsigned i = 0; i != NumArgs; ++i)
|
2009-10-23 06:37:11 +08:00
|
|
|
CanonicalArgs.push_back(getCanonicalParamType(ArgArray[i]));
|
2009-05-28 06:11:52 +08:00
|
|
|
|
2010-12-14 16:05:40 +08:00
|
|
|
FunctionProtoType::ExtProtoInfo CanonicalEPI = EPI;
|
2012-02-10 17:58:53 +08:00
|
|
|
CanonicalEPI.HasTrailingReturn = false;
|
2011-03-06 18:52:04 +08:00
|
|
|
CanonicalEPI.ExceptionSpecType = EST_None;
|
|
|
|
CanonicalEPI.NumExceptions = 0;
|
2010-12-14 16:05:40 +08:00
|
|
|
CanonicalEPI.ExtInfo
|
|
|
|
= CanonicalEPI.ExtInfo.withCallingConv(getCanonicalCallConv(CallConv));
|
|
|
|
|
2013-01-18 07:36:45 +08:00
|
|
|
// Result types do not have ARC lifetime qualifiers.
|
|
|
|
QualType CanResultTy = getCanonicalType(ResultTy);
|
|
|
|
if (ResultTy.getQualifiers().hasObjCLifetime()) {
|
|
|
|
Qualifiers Qs = CanResultTy.getQualifiers();
|
|
|
|
Qs.removeObjCLifetime();
|
|
|
|
CanResultTy = getQualifiedType(CanResultTy.getUnqualifiedType(), Qs);
|
|
|
|
}
|
|
|
|
|
|
|
|
Canonical = getFunctionType(CanResultTy,
|
2009-05-21 17:52:38 +08:00
|
|
|
CanonicalArgs.data(), NumArgs,
|
2010-12-14 16:05:40 +08:00
|
|
|
CanonicalEPI);
|
2009-05-28 06:11:52 +08:00
|
|
|
|
2007-01-27 09:15:32 +08:00
|
|
|
// Get the new insert position for the node we care about.
|
2009-02-27 07:50:07 +08:00
|
|
|
FunctionProtoType *NewIP =
|
|
|
|
FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos);
|
2010-12-23 09:01:28 +08:00
|
|
|
assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
|
2006-12-02 15:52:18 +08:00
|
|
|
}
|
2009-05-28 06:11:52 +08:00
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
// FunctionProtoType objects are allocated with extra bytes after
|
|
|
|
// them for three variable size arrays at the end:
|
|
|
|
// - parameter types
|
|
|
|
// - exception types
|
|
|
|
// - consumed-arguments flags
|
|
|
|
// Instead of the exception types, there could be a noexcept
|
Final piece of core issue 1330: delay computing the exception specification of
a defaulted special member function until the exception specification is needed
(using the same criteria used for the delayed instantiation of exception
specifications for function temploids).
EST_Delayed is now EST_Unevaluated (using 1330's terminology), and, like
EST_Uninstantiated, carries a pointer to the FunctionDecl which will be used to
resolve the exception specification.
This is enabled for all C++ modes: it's a little faster in the case where the
exception specification isn't used, allows our C++11-in-C++98 extensions to
work, and is still correct for C++98, since in that mode the computation of the
exception specification can't fail.
The diagnostics here aren't great (in particular, we should include implicit
evaluation of exception specifications for defaulted special members in the
template instantiation backtraces), but they're not much worse than before.
Our approach to the problem of cycles between in-class initializers and the
exception specification for a defaulted default constructor is modified a
little by this change -- we now reject any odr-use of a defaulted default
constructor if that constructor uses an in-class initializer and the use is in
an in-class initialzer which is declared lexically earlier. This is a closer
approximation to the current draft solution in core issue 1351, but isn't an
exact match (but the current draft wording isn't reasonable, so that's to be
expected).
llvm-svn: 160847
2012-07-27 12:22:15 +08:00
|
|
|
// expression, or information used to resolve the exception
|
|
|
|
// specification.
|
2010-12-14 16:05:40 +08:00
|
|
|
size_t Size = sizeof(FunctionProtoType) +
|
2011-03-12 19:50:43 +08:00
|
|
|
NumArgs * sizeof(QualType);
|
Final piece of core issue 1330: delay computing the exception specification of
a defaulted special member function until the exception specification is needed
(using the same criteria used for the delayed instantiation of exception
specifications for function temploids).
EST_Delayed is now EST_Unevaluated (using 1330's terminology), and, like
EST_Uninstantiated, carries a pointer to the FunctionDecl which will be used to
resolve the exception specification.
This is enabled for all C++ modes: it's a little faster in the case where the
exception specification isn't used, allows our C++11-in-C++98 extensions to
work, and is still correct for C++98, since in that mode the computation of the
exception specification can't fail.
The diagnostics here aren't great (in particular, we should include implicit
evaluation of exception specifications for defaulted special members in the
template instantiation backtraces), but they're not much worse than before.
Our approach to the problem of cycles between in-class initializers and the
exception specification for a defaulted default constructor is modified a
little by this change -- we now reject any odr-use of a defaulted default
constructor if that constructor uses an in-class initializer and the use is in
an in-class initialzer which is declared lexically earlier. This is a closer
approximation to the current draft solution in core issue 1351, but isn't an
exact match (but the current draft wording isn't reasonable, so that's to be
expected).
llvm-svn: 160847
2012-07-27 12:22:15 +08:00
|
|
|
if (EPI.ExceptionSpecType == EST_Dynamic) {
|
2011-03-12 19:50:43 +08:00
|
|
|
Size += EPI.NumExceptions * sizeof(QualType);
|
Final piece of core issue 1330: delay computing the exception specification of
a defaulted special member function until the exception specification is needed
(using the same criteria used for the delayed instantiation of exception
specifications for function temploids).
EST_Delayed is now EST_Unevaluated (using 1330's terminology), and, like
EST_Uninstantiated, carries a pointer to the FunctionDecl which will be used to
resolve the exception specification.
This is enabled for all C++ modes: it's a little faster in the case where the
exception specification isn't used, allows our C++11-in-C++98 extensions to
work, and is still correct for C++98, since in that mode the computation of the
exception specification can't fail.
The diagnostics here aren't great (in particular, we should include implicit
evaluation of exception specifications for defaulted special members in the
template instantiation backtraces), but they're not much worse than before.
Our approach to the problem of cycles between in-class initializers and the
exception specification for a defaulted default constructor is modified a
little by this change -- we now reject any odr-use of a defaulted default
constructor if that constructor uses an in-class initializer and the use is in
an in-class initialzer which is declared lexically earlier. This is a closer
approximation to the current draft solution in core issue 1351, but isn't an
exact match (but the current draft wording isn't reasonable, so that's to be
expected).
llvm-svn: 160847
2012-07-27 12:22:15 +08:00
|
|
|
} else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
|
2011-03-14 01:09:40 +08:00
|
|
|
Size += sizeof(Expr*);
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
} else if (EPI.ExceptionSpecType == EST_Uninstantiated) {
|
2012-04-19 08:08:28 +08:00
|
|
|
Size += 2 * sizeof(FunctionDecl*);
|
Final piece of core issue 1330: delay computing the exception specification of
a defaulted special member function until the exception specification is needed
(using the same criteria used for the delayed instantiation of exception
specifications for function temploids).
EST_Delayed is now EST_Unevaluated (using 1330's terminology), and, like
EST_Uninstantiated, carries a pointer to the FunctionDecl which will be used to
resolve the exception specification.
This is enabled for all C++ modes: it's a little faster in the case where the
exception specification isn't used, allows our C++11-in-C++98 extensions to
work, and is still correct for C++98, since in that mode the computation of the
exception specification can't fail.
The diagnostics here aren't great (in particular, we should include implicit
evaluation of exception specifications for defaulted special members in the
template instantiation backtraces), but they're not much worse than before.
Our approach to the problem of cycles between in-class initializers and the
exception specification for a defaulted default constructor is modified a
little by this change -- we now reject any odr-use of a defaulted default
constructor if that constructor uses an in-class initializer and the use is in
an in-class initialzer which is declared lexically earlier. This is a closer
approximation to the current draft solution in core issue 1351, but isn't an
exact match (but the current draft wording isn't reasonable, so that's to be
expected).
llvm-svn: 160847
2012-07-27 12:22:15 +08:00
|
|
|
} else if (EPI.ExceptionSpecType == EST_Unevaluated) {
|
|
|
|
Size += sizeof(FunctionDecl*);
|
2011-03-12 19:50:43 +08:00
|
|
|
}
|
2011-06-16 07:02:42 +08:00
|
|
|
if (EPI.ConsumedArguments)
|
|
|
|
Size += NumArgs * sizeof(bool);
|
|
|
|
|
2010-12-14 16:05:40 +08:00
|
|
|
FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment);
|
2011-03-02 01:40:53 +08:00
|
|
|
FunctionProtoType::ExtProtoInfo newEPI = EPI;
|
|
|
|
newEPI.ExtInfo = EPI.ExtInfo.withCallingConv(CallConv);
|
2011-03-14 01:09:40 +08:00
|
|
|
new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, Canonical, newEPI);
|
2006-12-02 15:52:18 +08:00
|
|
|
Types.push_back(FTP);
|
2009-02-27 07:50:07 +08:00
|
|
|
FunctionProtoTypes.InsertNode(FTP, InsertPos);
|
2007-04-06 06:36:20 +08:00
|
|
|
return QualType(FTP, 0);
|
2006-12-02 15:52:18 +08:00
|
|
|
}
|
2006-11-10 15:17:23 +08:00
|
|
|
|
2010-03-10 11:28:59 +08:00
|
|
|
#ifndef NDEBUG
|
|
|
|
static bool NeedsInjectedClassNameType(const RecordDecl *D) {
|
|
|
|
if (!isa<CXXRecordDecl>(D)) return false;
|
|
|
|
const CXXRecordDecl *RD = cast<CXXRecordDecl>(D);
|
|
|
|
if (isa<ClassTemplatePartialSpecializationDecl>(RD))
|
|
|
|
return true;
|
|
|
|
if (RD->getDescribedClassTemplate() &&
|
|
|
|
!isa<ClassTemplateSpecializationDecl>(RD))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/// getInjectedClassNameType - Return the unique reference to the
|
|
|
|
/// injected class name type for the specified templated declaration.
|
|
|
|
QualType ASTContext::getInjectedClassNameType(CXXRecordDecl *Decl,
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType TST) const {
|
2010-03-10 11:28:59 +08:00
|
|
|
assert(NeedsInjectedClassNameType(Decl));
|
|
|
|
if (Decl->TypeForDecl) {
|
|
|
|
assert(isa<InjectedClassNameType>(Decl->TypeForDecl));
|
2012-01-15 00:38:05 +08:00
|
|
|
} else if (CXXRecordDecl *PrevDecl = Decl->getPreviousDecl()) {
|
2010-03-10 11:28:59 +08:00
|
|
|
assert(PrevDecl->TypeForDecl && "previous declaration has no type");
|
|
|
|
Decl->TypeForDecl = PrevDecl->TypeForDecl;
|
|
|
|
assert(isa<InjectedClassNameType>(Decl->TypeForDecl));
|
|
|
|
} else {
|
2011-01-19 14:33:43 +08:00
|
|
|
Type *newType =
|
2010-04-27 08:57:59 +08:00
|
|
|
new (*this, TypeAlignment) InjectedClassNameType(Decl, TST);
|
2011-01-19 14:33:43 +08:00
|
|
|
Decl->TypeForDecl = newType;
|
|
|
|
Types.push_back(newType);
|
2010-03-10 11:28:59 +08:00
|
|
|
}
|
|
|
|
return QualType(Decl->TypeForDecl, 0);
|
|
|
|
}
|
|
|
|
|
2008-04-14 05:07:44 +08:00
|
|
|
/// getTypeDeclType - Return the unique reference to the type for the
|
|
|
|
/// specified type declaration.
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const {
|
2008-10-17 00:50:47 +08:00
|
|
|
assert(Decl && "Passed null for Decl param");
|
2010-03-10 14:48:02 +08:00
|
|
|
assert(!Decl->TypeForDecl && "TypeForDecl present in slow case");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-04-15 22:24:37 +08:00
|
|
|
if (const TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Decl))
|
2008-04-14 05:07:44 +08:00
|
|
|
return getTypedefType(Typedef);
|
2010-03-10 14:48:02 +08:00
|
|
|
|
|
|
|
assert(!isa<TemplateTypeParmDecl>(Decl) &&
|
|
|
|
"Template type parameter types are always available.");
|
|
|
|
|
2010-02-16 11:57:14 +08:00
|
|
|
if (const RecordDecl *Record = dyn_cast<RecordDecl>(Decl)) {
|
2012-01-15 00:38:05 +08:00
|
|
|
assert(!Record->getPreviousDecl() &&
|
2010-03-10 14:48:02 +08:00
|
|
|
"struct/union has previous declaration");
|
|
|
|
assert(!NeedsInjectedClassNameType(Record));
|
2010-07-05 05:44:47 +08:00
|
|
|
return getRecordType(Record);
|
2010-02-16 11:57:14 +08:00
|
|
|
} else if (const EnumDecl *Enum = dyn_cast<EnumDecl>(Decl)) {
|
2012-01-15 00:38:05 +08:00
|
|
|
assert(!Enum->getPreviousDecl() &&
|
2010-03-10 14:48:02 +08:00
|
|
|
"enum has previous declaration");
|
2010-07-05 05:44:47 +08:00
|
|
|
return getEnumType(Enum);
|
2010-02-16 11:57:14 +08:00
|
|
|
} else if (const UnresolvedUsingTypenameDecl *Using =
|
2009-12-05 06:46:56 +08:00
|
|
|
dyn_cast<UnresolvedUsingTypenameDecl>(Decl)) {
|
2011-01-19 14:33:43 +08:00
|
|
|
Type *newType = new (*this, TypeAlignment) UnresolvedUsingType(Using);
|
|
|
|
Decl->TypeForDecl = newType;
|
|
|
|
Types.push_back(newType);
|
2009-07-31 10:02:20 +08:00
|
|
|
} else
|
2010-03-10 14:48:02 +08:00
|
|
|
llvm_unreachable("TypeDecl without a type?");
|
2008-08-08 04:55:28 +08:00
|
|
|
|
|
|
|
return QualType(Decl->TypeForDecl, 0);
|
2008-04-14 05:07:44 +08:00
|
|
|
}
|
|
|
|
|
2007-01-26 10:01:53 +08:00
|
|
|
/// getTypedefType - Return the unique reference to the type for the
|
2011-04-15 22:24:37 +08:00
|
|
|
/// specified typedef name decl.
|
2010-07-02 19:55:11 +08:00
|
|
|
QualType
|
2011-04-15 22:24:37 +08:00
|
|
|
ASTContext::getTypedefType(const TypedefNameDecl *Decl,
|
|
|
|
QualType Canonical) const {
|
2007-04-06 06:36:20 +08:00
|
|
|
if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-07-02 19:55:11 +08:00
|
|
|
if (Canonical.isNull())
|
|
|
|
Canonical = getCanonicalType(Decl->getUnderlyingType());
|
2011-01-19 14:33:43 +08:00
|
|
|
TypedefType *newType = new(*this, TypeAlignment)
|
2009-09-25 07:30:46 +08:00
|
|
|
TypedefType(Type::Typedef, Decl, Canonical);
|
2011-01-19 14:33:43 +08:00
|
|
|
Decl->TypeForDecl = newType;
|
|
|
|
Types.push_back(newType);
|
|
|
|
return QualType(newType, 0);
|
2006-11-20 12:02:15 +08:00
|
|
|
}
|
|
|
|
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType ASTContext::getRecordType(const RecordDecl *Decl) const {
|
2010-07-05 05:44:47 +08:00
|
|
|
if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
|
|
|
|
|
2012-01-15 00:38:05 +08:00
|
|
|
if (const RecordDecl *PrevDecl = Decl->getPreviousDecl())
|
2010-07-05 05:44:47 +08:00
|
|
|
if (PrevDecl->TypeForDecl)
|
|
|
|
return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0);
|
|
|
|
|
2011-01-19 14:33:43 +08:00
|
|
|
RecordType *newType = new (*this, TypeAlignment) RecordType(Decl);
|
|
|
|
Decl->TypeForDecl = newType;
|
|
|
|
Types.push_back(newType);
|
|
|
|
return QualType(newType, 0);
|
2010-07-05 05:44:47 +08:00
|
|
|
}
|
|
|
|
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType ASTContext::getEnumType(const EnumDecl *Decl) const {
|
2010-07-05 05:44:47 +08:00
|
|
|
if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
|
|
|
|
|
2012-01-15 00:38:05 +08:00
|
|
|
if (const EnumDecl *PrevDecl = Decl->getPreviousDecl())
|
2010-07-05 05:44:47 +08:00
|
|
|
if (PrevDecl->TypeForDecl)
|
|
|
|
return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0);
|
|
|
|
|
2011-01-19 14:33:43 +08:00
|
|
|
EnumType *newType = new (*this, TypeAlignment) EnumType(Decl);
|
|
|
|
Decl->TypeForDecl = newType;
|
|
|
|
Types.push_back(newType);
|
|
|
|
return QualType(newType, 0);
|
2010-07-05 05:44:47 +08:00
|
|
|
}
|
|
|
|
|
2011-01-06 09:58:22 +08:00
|
|
|
QualType ASTContext::getAttributedType(AttributedType::Kind attrKind,
|
|
|
|
QualType modifiedType,
|
|
|
|
QualType equivalentType) {
|
|
|
|
llvm::FoldingSetNodeID id;
|
|
|
|
AttributedType::Profile(id, attrKind, modifiedType, equivalentType);
|
|
|
|
|
|
|
|
void *insertPos = 0;
|
|
|
|
AttributedType *type = AttributedTypes.FindNodeOrInsertPos(id, insertPos);
|
|
|
|
if (type) return QualType(type, 0);
|
|
|
|
|
|
|
|
QualType canon = getCanonicalType(equivalentType);
|
|
|
|
type = new (*this, TypeAlignment)
|
|
|
|
AttributedType(canon, attrKind, modifiedType, equivalentType);
|
|
|
|
|
|
|
|
Types.push_back(type);
|
|
|
|
AttributedTypes.InsertNode(type, insertPos);
|
|
|
|
|
|
|
|
return QualType(type, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-18 17:09:24 +08:00
|
|
|
/// \brief Retrieve a substitution-result type.
|
|
|
|
QualType
|
|
|
|
ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm,
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType Replacement) const {
|
2009-10-23 04:10:53 +08:00
|
|
|
assert(Replacement.isCanonical()
|
2009-10-18 17:09:24 +08:00
|
|
|
&& "replacement types must always be canonical");
|
|
|
|
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
SubstTemplateTypeParmType::Profile(ID, Parm, Replacement);
|
|
|
|
void *InsertPos = 0;
|
|
|
|
SubstTemplateTypeParmType *SubstParm
|
|
|
|
= SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
|
|
|
|
if (!SubstParm) {
|
|
|
|
SubstParm = new (*this, TypeAlignment)
|
|
|
|
SubstTemplateTypeParmType(Parm, Replacement);
|
|
|
|
Types.push_back(SubstParm);
|
|
|
|
SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos);
|
|
|
|
}
|
|
|
|
|
|
|
|
return QualType(SubstParm, 0);
|
|
|
|
}
|
|
|
|
|
2011-01-14 10:55:32 +08:00
|
|
|
/// \brief Retrieve a
|
|
|
|
QualType ASTContext::getSubstTemplateTypeParmPackType(
|
|
|
|
const TemplateTypeParmType *Parm,
|
|
|
|
const TemplateArgument &ArgPack) {
|
|
|
|
#ifndef NDEBUG
|
|
|
|
for (TemplateArgument::pack_iterator P = ArgPack.pack_begin(),
|
|
|
|
PEnd = ArgPack.pack_end();
|
|
|
|
P != PEnd; ++P) {
|
|
|
|
assert(P->getKind() == TemplateArgument::Type &&"Pack contains a non-type");
|
|
|
|
assert(P->getAsType().isCanonical() && "Pack contains non-canonical type");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
SubstTemplateTypeParmPackType::Profile(ID, Parm, ArgPack);
|
|
|
|
void *InsertPos = 0;
|
|
|
|
if (SubstTemplateTypeParmPackType *SubstParm
|
|
|
|
= SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos))
|
|
|
|
return QualType(SubstParm, 0);
|
|
|
|
|
|
|
|
QualType Canon;
|
|
|
|
if (!Parm->isCanonicalUnqualified()) {
|
|
|
|
Canon = getCanonicalType(QualType(Parm, 0));
|
|
|
|
Canon = getSubstTemplateTypeParmPackType(cast<TemplateTypeParmType>(Canon),
|
|
|
|
ArgPack);
|
|
|
|
SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
}
|
|
|
|
|
|
|
|
SubstTemplateTypeParmPackType *SubstParm
|
|
|
|
= new (*this, TypeAlignment) SubstTemplateTypeParmPackType(Parm, Canon,
|
|
|
|
ArgPack);
|
|
|
|
Types.push_back(SubstParm);
|
|
|
|
SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos);
|
|
|
|
return QualType(SubstParm, 0);
|
|
|
|
}
|
|
|
|
|
2009-02-06 07:33:38 +08:00
|
|
|
/// \brief Retrieve the template type parameter type for a template
|
2009-09-09 23:08:12 +08:00
|
|
|
/// parameter or parameter pack with the given depth, index, and (optionally)
|
2009-06-16 08:30:48 +08:00
|
|
|
/// name.
|
2009-09-09 23:08:12 +08:00
|
|
|
QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index,
|
2009-06-16 08:30:48 +08:00
|
|
|
bool ParameterPack,
|
Re-applies the patch first applied way back in r106099, with
accompanying fixes to make it work today.
The core of this patch is to provide a link from a TemplateTypeParmType
back to the TemplateTypeParmDecl node which declared it. This in turn
provides much more precise information about the type, where it came
from, and how it functions for AST consumers.
To make the patch work almost a year after its first attempt, it needed
serialization support, and it now retains the old getName() interface.
Finally, it requires us to not attempt to instantiate the type in an
unsupported friend decl -- specifically those coming from template
friend decls but which refer to a specific type through a dependent
name.
A cleaner representation of the last item would be to build
FriendTemplateDecl nodes for these, storing their template parameters
etc, and to perform proper instantation of them like any other template
declaration. They can still be flagged as unsupported for the purpose of
access checking, etc.
This passed an asserts-enabled bootstrap for me, and the reduced test
case mentioned in the original review thread no longer causes issues,
likely fixed at somewhere amidst the 24k revisions that have elapsed.
llvm-svn: 130628
2011-05-01 08:51:33 +08:00
|
|
|
TemplateTypeParmDecl *TTPDecl) const {
|
2009-02-06 07:33:38 +08:00
|
|
|
llvm::FoldingSetNodeID ID;
|
Re-applies the patch first applied way back in r106099, with
accompanying fixes to make it work today.
The core of this patch is to provide a link from a TemplateTypeParmType
back to the TemplateTypeParmDecl node which declared it. This in turn
provides much more precise information about the type, where it came
from, and how it functions for AST consumers.
To make the patch work almost a year after its first attempt, it needed
serialization support, and it now retains the old getName() interface.
Finally, it requires us to not attempt to instantiate the type in an
unsupported friend decl -- specifically those coming from template
friend decls but which refer to a specific type through a dependent
name.
A cleaner representation of the last item would be to build
FriendTemplateDecl nodes for these, storing their template parameters
etc, and to perform proper instantation of them like any other template
declaration. They can still be flagged as unsupported for the purpose of
access checking, etc.
This passed an asserts-enabled bootstrap for me, and the reduced test
case mentioned in the original review thread no longer causes issues,
likely fixed at somewhere amidst the 24k revisions that have elapsed.
llvm-svn: 130628
2011-05-01 08:51:33 +08:00
|
|
|
TemplateTypeParmType::Profile(ID, Depth, Index, ParameterPack, TTPDecl);
|
2009-02-06 07:33:38 +08:00
|
|
|
void *InsertPos = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
TemplateTypeParmType *TypeParm
|
2009-02-06 07:33:38 +08:00
|
|
|
= TemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
|
|
|
|
if (TypeParm)
|
|
|
|
return QualType(TypeParm, 0);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Re-applies the patch first applied way back in r106099, with
accompanying fixes to make it work today.
The core of this patch is to provide a link from a TemplateTypeParmType
back to the TemplateTypeParmDecl node which declared it. This in turn
provides much more precise information about the type, where it came
from, and how it functions for AST consumers.
To make the patch work almost a year after its first attempt, it needed
serialization support, and it now retains the old getName() interface.
Finally, it requires us to not attempt to instantiate the type in an
unsupported friend decl -- specifically those coming from template
friend decls but which refer to a specific type through a dependent
name.
A cleaner representation of the last item would be to build
FriendTemplateDecl nodes for these, storing their template parameters
etc, and to perform proper instantation of them like any other template
declaration. They can still be flagged as unsupported for the purpose of
access checking, etc.
This passed an asserts-enabled bootstrap for me, and the reduced test
case mentioned in the original review thread no longer causes issues,
likely fixed at somewhere amidst the 24k revisions that have elapsed.
llvm-svn: 130628
2011-05-01 08:51:33 +08:00
|
|
|
if (TTPDecl) {
|
2009-06-16 08:30:48 +08:00
|
|
|
QualType Canon = getTemplateTypeParmType(Depth, Index, ParameterPack);
|
Re-applies the patch first applied way back in r106099, with
accompanying fixes to make it work today.
The core of this patch is to provide a link from a TemplateTypeParmType
back to the TemplateTypeParmDecl node which declared it. This in turn
provides much more precise information about the type, where it came
from, and how it functions for AST consumers.
To make the patch work almost a year after its first attempt, it needed
serialization support, and it now retains the old getName() interface.
Finally, it requires us to not attempt to instantiate the type in an
unsupported friend decl -- specifically those coming from template
friend decls but which refer to a specific type through a dependent
name.
A cleaner representation of the last item would be to build
FriendTemplateDecl nodes for these, storing their template parameters
etc, and to perform proper instantation of them like any other template
declaration. They can still be flagged as unsupported for the purpose of
access checking, etc.
This passed an asserts-enabled bootstrap for me, and the reduced test
case mentioned in the original review thread no longer causes issues,
likely fixed at somewhere amidst the 24k revisions that have elapsed.
llvm-svn: 130628
2011-05-01 08:51:33 +08:00
|
|
|
TypeParm = new (*this, TypeAlignment) TemplateTypeParmType(TTPDecl, Canon);
|
Fix an obscure crash found in the Boost.MPL test suite, along with a
ton of potential crashes of the same kind. The fundamental problem is
that type creation was following a dangerous pattern when using its
FoldingSets:
1) Use FindNodeOrInsertPos to see if the type is available
2) If not, and we aren't looking at a canonical type, build the
canonical type
3) Build and insert the new node into the FoldingSet
The problem here is that building the canonical type can, in very rare
circumstances, force the hash table inside the FoldingSet to
reallocate. That invalidates the insertion position we computed in
step 1, and in step 3 we end up inserting the new node into the wrong
place. BOOM!
I've audited all of ASTContext, fixing this problem everywhere I found
it. The vast majority of wrong code was C++-specific (and *ahem*
written by me), so I also audited other major folding sets in the C++
code (e.g., template specializations), but found no other instances of
this problem.
llvm-svn: 95315
2010-02-05 02:10:26 +08:00
|
|
|
|
|
|
|
TemplateTypeParmType *TypeCheck
|
|
|
|
= TemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
assert(!TypeCheck && "Template type parameter canonical type broken");
|
|
|
|
(void)TypeCheck;
|
2009-06-16 08:30:48 +08:00
|
|
|
} else
|
2009-09-25 07:30:46 +08:00
|
|
|
TypeParm = new (*this, TypeAlignment)
|
|
|
|
TemplateTypeParmType(Depth, Index, ParameterPack);
|
2009-02-06 07:33:38 +08:00
|
|
|
|
|
|
|
Types.push_back(TypeParm);
|
|
|
|
TemplateTypeParmTypes.InsertNode(TypeParm, InsertPos);
|
|
|
|
|
|
|
|
return QualType(TypeParm, 0);
|
|
|
|
}
|
|
|
|
|
2010-03-10 11:28:59 +08:00
|
|
|
TypeSourceInfo *
|
|
|
|
ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name,
|
|
|
|
SourceLocation NameLoc,
|
|
|
|
const TemplateArgumentListInfo &Args,
|
2011-05-06 05:57:07 +08:00
|
|
|
QualType Underlying) const {
|
2011-03-01 02:50:33 +08:00
|
|
|
assert(!Name.getAsDependentTemplateName() &&
|
|
|
|
"No dependent template names here!");
|
2011-05-06 05:57:07 +08:00
|
|
|
QualType TST = getTemplateSpecializationType(Name, Args, Underlying);
|
2010-03-10 11:28:59 +08:00
|
|
|
|
|
|
|
TypeSourceInfo *DI = CreateTypeSourceInfo(TST);
|
|
|
|
TemplateSpecializationTypeLoc TL
|
|
|
|
= cast<TemplateSpecializationTypeLoc>(DI->getTypeLoc());
|
2012-02-06 22:41:24 +08:00
|
|
|
TL.setTemplateKeywordLoc(SourceLocation());
|
2010-03-10 11:28:59 +08:00
|
|
|
TL.setTemplateNameLoc(NameLoc);
|
|
|
|
TL.setLAngleLoc(Args.getLAngleLoc());
|
|
|
|
TL.setRAngleLoc(Args.getRAngleLoc());
|
|
|
|
for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
|
|
|
|
TL.setArgLocInfo(i, Args[i].getLocInfo());
|
|
|
|
return DI;
|
|
|
|
}
|
|
|
|
|
2009-10-29 16:12:44 +08:00
|
|
|
QualType
|
|
|
|
ASTContext::getTemplateSpecializationType(TemplateName Template,
|
2009-11-23 09:53:49 +08:00
|
|
|
const TemplateArgumentListInfo &Args,
|
2011-05-06 05:57:07 +08:00
|
|
|
QualType Underlying) const {
|
2011-03-01 02:50:33 +08:00
|
|
|
assert(!Template.getAsDependentTemplateName() &&
|
|
|
|
"No dependent template names here!");
|
|
|
|
|
2009-11-23 09:53:49 +08:00
|
|
|
unsigned NumArgs = Args.size();
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<TemplateArgument, 4> ArgVec;
|
2009-10-29 16:12:44 +08:00
|
|
|
ArgVec.reserve(NumArgs);
|
|
|
|
for (unsigned i = 0; i != NumArgs; ++i)
|
|
|
|
ArgVec.push_back(Args[i].getArgument());
|
|
|
|
|
2010-04-27 08:57:59 +08:00
|
|
|
return getTemplateSpecializationType(Template, ArgVec.data(), NumArgs,
|
2011-05-06 05:57:07 +08:00
|
|
|
Underlying);
|
2009-10-29 16:12:44 +08:00
|
|
|
}
|
|
|
|
|
2012-02-04 01:16:23 +08:00
|
|
|
#ifndef NDEBUG
|
|
|
|
static bool hasAnyPackExpansions(const TemplateArgument *Args,
|
|
|
|
unsigned NumArgs) {
|
|
|
|
for (unsigned I = 0; I != NumArgs; ++I)
|
|
|
|
if (Args[I].isPackExpansion())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
QualType
|
2009-03-31 06:58:21 +08:00
|
|
|
ASTContext::getTemplateSpecializationType(TemplateName Template,
|
|
|
|
const TemplateArgument *Args,
|
|
|
|
unsigned NumArgs,
|
2011-05-06 05:57:07 +08:00
|
|
|
QualType Underlying) const {
|
2011-03-01 02:50:33 +08:00
|
|
|
assert(!Template.getAsDependentTemplateName() &&
|
|
|
|
"No dependent template names here!");
|
2011-03-04 01:04:51 +08:00
|
|
|
// Look through qualified template names.
|
|
|
|
if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
|
|
|
|
Template = TemplateName(QTN->getTemplateDecl());
|
2011-03-01 02:50:33 +08:00
|
|
|
|
2012-02-04 01:16:23 +08:00
|
|
|
bool IsTypeAlias =
|
2011-05-06 05:57:07 +08:00
|
|
|
Template.getAsTemplateDecl() &&
|
|
|
|
isa<TypeAliasTemplateDecl>(Template.getAsTemplateDecl());
|
|
|
|
QualType CanonType;
|
|
|
|
if (!Underlying.isNull())
|
|
|
|
CanonType = getCanonicalType(Underlying);
|
|
|
|
else {
|
2012-02-04 01:16:23 +08:00
|
|
|
// We can get here with an alias template when the specialization contains
|
|
|
|
// a pack expansion that does not match up with a parameter pack.
|
|
|
|
assert((!IsTypeAlias || hasAnyPackExpansions(Args, NumArgs)) &&
|
|
|
|
"Caller must compute aliased type");
|
|
|
|
IsTypeAlias = false;
|
2011-05-06 05:57:07 +08:00
|
|
|
CanonType = getCanonicalTemplateSpecializationType(Template, Args,
|
|
|
|
NumArgs);
|
|
|
|
}
|
2009-02-27 06:19:44 +08:00
|
|
|
|
2009-07-29 07:00:59 +08:00
|
|
|
// Allocate the (non-canonical) template specialization type, but don't
|
|
|
|
// try to unique it: these types typically have location information that
|
|
|
|
// we don't unique and don't want to lose.
|
2011-05-06 05:57:07 +08:00
|
|
|
void *Mem = Allocate(sizeof(TemplateSpecializationType) +
|
|
|
|
sizeof(TemplateArgument) * NumArgs +
|
2012-02-04 01:16:23 +08:00
|
|
|
(IsTypeAlias? sizeof(QualType) : 0),
|
2009-09-25 07:30:46 +08:00
|
|
|
TypeAlignment);
|
2009-09-09 23:08:12 +08:00
|
|
|
TemplateSpecializationType *Spec
|
2012-02-04 01:16:23 +08:00
|
|
|
= new (Mem) TemplateSpecializationType(Template, Args, NumArgs, CanonType,
|
|
|
|
IsTypeAlias ? Underlying : QualType());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-10 02:46:07 +08:00
|
|
|
Types.push_back(Spec);
|
2009-09-09 23:08:12 +08:00
|
|
|
return QualType(Spec, 0);
|
2009-02-10 02:46:07 +08:00
|
|
|
}
|
|
|
|
|
2010-07-02 19:55:11 +08:00
|
|
|
QualType
|
|
|
|
ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template,
|
|
|
|
const TemplateArgument *Args,
|
2011-01-12 17:06:06 +08:00
|
|
|
unsigned NumArgs) const {
|
2011-03-01 02:50:33 +08:00
|
|
|
assert(!Template.getAsDependentTemplateName() &&
|
|
|
|
"No dependent template names here!");
|
2011-05-06 05:57:07 +08:00
|
|
|
|
2011-03-04 01:04:51 +08:00
|
|
|
// Look through qualified template names.
|
|
|
|
if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
|
|
|
|
Template = TemplateName(QTN->getTemplateDecl());
|
2011-03-01 02:50:33 +08:00
|
|
|
|
2010-07-02 19:55:11 +08:00
|
|
|
// Build the canonical template specialization type.
|
|
|
|
TemplateName CanonTemplate = getCanonicalTemplateName(Template);
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<TemplateArgument, 4> CanonArgs;
|
2010-07-02 19:55:11 +08:00
|
|
|
CanonArgs.reserve(NumArgs);
|
|
|
|
for (unsigned I = 0; I != NumArgs; ++I)
|
|
|
|
CanonArgs.push_back(getCanonicalTemplateArgument(Args[I]));
|
|
|
|
|
|
|
|
// Determine whether this canonical template specialization type already
|
|
|
|
// exists.
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
TemplateSpecializationType::Profile(ID, CanonTemplate,
|
|
|
|
CanonArgs.data(), NumArgs, *this);
|
|
|
|
|
|
|
|
void *InsertPos = 0;
|
|
|
|
TemplateSpecializationType *Spec
|
|
|
|
= TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
|
|
|
|
if (!Spec) {
|
|
|
|
// Allocate a new canonical template specialization type.
|
|
|
|
void *Mem = Allocate((sizeof(TemplateSpecializationType) +
|
|
|
|
sizeof(TemplateArgument) * NumArgs),
|
|
|
|
TypeAlignment);
|
|
|
|
Spec = new (Mem) TemplateSpecializationType(CanonTemplate,
|
|
|
|
CanonArgs.data(), NumArgs,
|
2011-05-06 05:57:07 +08:00
|
|
|
QualType(), QualType());
|
2010-07-02 19:55:11 +08:00
|
|
|
Types.push_back(Spec);
|
|
|
|
TemplateSpecializationTypes.InsertNode(Spec, InsertPos);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(Spec->isDependentType() &&
|
|
|
|
"Non-dependent template-id type must have a canonical type");
|
|
|
|
return QualType(Spec, 0);
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
QualType
|
2010-05-12 05:36:43 +08:00
|
|
|
ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword,
|
|
|
|
NestedNameSpecifier *NNS,
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType NamedType) const {
|
Introduce a representation for types that we referred to via a
qualified name, e.g.,
foo::x
so that we retain the nested-name-specifier as written in the source
code and can reproduce that qualified name when printing the types
back (e.g., in diagnostics). This is PR3493, which won't be complete
until finished the other tasks mentioned near the end of this commit.
The parser's representation of nested-name-specifiers, CXXScopeSpec,
is now a bit fatter, because it needs to contain the scopes that
precede each '::' and keep track of whether the global scoping
operator '::' was at the beginning. For example, we need to keep track
of the leading '::', 'foo', and 'bar' in
::foo::bar::x
The Action's CXXScopeTy * is no longer a DeclContext *. It's now the
opaque version of the new NestedNameSpecifier, which contains a single
component of a nested-name-specifier (either a DeclContext * or a Type
*, bitmangled).
The new sugar type QualifiedNameType composes a sequence of
NestedNameSpecifiers with a representation of the type we're actually
referring to. At present, we only build QualifiedNameType nodes within
Sema::getTypeName. This will be extended to other type-constructing
actions (e.g., ActOnClassTemplateId).
Also on the way: QualifiedDeclRefExprs will also store a sequence of
NestedNameSpecifiers, so that we can print out the property
nested-name-specifier. I expect to also use this for handling
dependent names like Fibonacci<I - 1>::value.
llvm-svn: 67265
2009-03-19 08:18:19 +08:00
|
|
|
llvm::FoldingSetNodeID ID;
|
2010-05-12 05:36:43 +08:00
|
|
|
ElaboratedType::Profile(ID, Keyword, NNS, NamedType);
|
Introduce a representation for types that we referred to via a
qualified name, e.g.,
foo::x
so that we retain the nested-name-specifier as written in the source
code and can reproduce that qualified name when printing the types
back (e.g., in diagnostics). This is PR3493, which won't be complete
until finished the other tasks mentioned near the end of this commit.
The parser's representation of nested-name-specifiers, CXXScopeSpec,
is now a bit fatter, because it needs to contain the scopes that
precede each '::' and keep track of whether the global scoping
operator '::' was at the beginning. For example, we need to keep track
of the leading '::', 'foo', and 'bar' in
::foo::bar::x
The Action's CXXScopeTy * is no longer a DeclContext *. It's now the
opaque version of the new NestedNameSpecifier, which contains a single
component of a nested-name-specifier (either a DeclContext * or a Type
*, bitmangled).
The new sugar type QualifiedNameType composes a sequence of
NestedNameSpecifiers with a representation of the type we're actually
referring to. At present, we only build QualifiedNameType nodes within
Sema::getTypeName. This will be extended to other type-constructing
actions (e.g., ActOnClassTemplateId).
Also on the way: QualifiedDeclRefExprs will also store a sequence of
NestedNameSpecifiers, so that we can print out the property
nested-name-specifier. I expect to also use this for handling
dependent names like Fibonacci<I - 1>::value.
llvm-svn: 67265
2009-03-19 08:18:19 +08:00
|
|
|
|
|
|
|
void *InsertPos = 0;
|
2010-05-12 05:36:43 +08:00
|
|
|
ElaboratedType *T = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos);
|
Introduce a representation for types that we referred to via a
qualified name, e.g.,
foo::x
so that we retain the nested-name-specifier as written in the source
code and can reproduce that qualified name when printing the types
back (e.g., in diagnostics). This is PR3493, which won't be complete
until finished the other tasks mentioned near the end of this commit.
The parser's representation of nested-name-specifiers, CXXScopeSpec,
is now a bit fatter, because it needs to contain the scopes that
precede each '::' and keep track of whether the global scoping
operator '::' was at the beginning. For example, we need to keep track
of the leading '::', 'foo', and 'bar' in
::foo::bar::x
The Action's CXXScopeTy * is no longer a DeclContext *. It's now the
opaque version of the new NestedNameSpecifier, which contains a single
component of a nested-name-specifier (either a DeclContext * or a Type
*, bitmangled).
The new sugar type QualifiedNameType composes a sequence of
NestedNameSpecifiers with a representation of the type we're actually
referring to. At present, we only build QualifiedNameType nodes within
Sema::getTypeName. This will be extended to other type-constructing
actions (e.g., ActOnClassTemplateId).
Also on the way: QualifiedDeclRefExprs will also store a sequence of
NestedNameSpecifiers, so that we can print out the property
nested-name-specifier. I expect to also use this for handling
dependent names like Fibonacci<I - 1>::value.
llvm-svn: 67265
2009-03-19 08:18:19 +08:00
|
|
|
if (T)
|
|
|
|
return QualType(T, 0);
|
|
|
|
|
Fix an obscure crash found in the Boost.MPL test suite, along with a
ton of potential crashes of the same kind. The fundamental problem is
that type creation was following a dangerous pattern when using its
FoldingSets:
1) Use FindNodeOrInsertPos to see if the type is available
2) If not, and we aren't looking at a canonical type, build the
canonical type
3) Build and insert the new node into the FoldingSet
The problem here is that building the canonical type can, in very rare
circumstances, force the hash table inside the FoldingSet to
reallocate. That invalidates the insertion position we computed in
step 1, and in step 3 we end up inserting the new node into the wrong
place. BOOM!
I've audited all of ASTContext, fixing this problem everywhere I found
it. The vast majority of wrong code was C++-specific (and *ahem*
written by me), so I also audited other major folding sets in the C++
code (e.g., template specializations), but found no other instances of
this problem.
llvm-svn: 95315
2010-02-05 02:10:26 +08:00
|
|
|
QualType Canon = NamedType;
|
|
|
|
if (!Canon.isCanonical()) {
|
|
|
|
Canon = getCanonicalType(NamedType);
|
2010-05-12 05:36:43 +08:00
|
|
|
ElaboratedType *CheckT = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
assert(!CheckT && "Elaborated canonical type broken");
|
Fix an obscure crash found in the Boost.MPL test suite, along with a
ton of potential crashes of the same kind. The fundamental problem is
that type creation was following a dangerous pattern when using its
FoldingSets:
1) Use FindNodeOrInsertPos to see if the type is available
2) If not, and we aren't looking at a canonical type, build the
canonical type
3) Build and insert the new node into the FoldingSet
The problem here is that building the canonical type can, in very rare
circumstances, force the hash table inside the FoldingSet to
reallocate. That invalidates the insertion position we computed in
step 1, and in step 3 we end up inserting the new node into the wrong
place. BOOM!
I've audited all of ASTContext, fixing this problem everywhere I found
it. The vast majority of wrong code was C++-specific (and *ahem*
written by me), so I also audited other major folding sets in the C++
code (e.g., template specializations), but found no other instances of
this problem.
llvm-svn: 95315
2010-02-05 02:10:26 +08:00
|
|
|
(void)CheckT;
|
|
|
|
}
|
|
|
|
|
2010-05-12 05:36:43 +08:00
|
|
|
T = new (*this) ElaboratedType(Keyword, NNS, NamedType, Canon);
|
Introduce a representation for types that we referred to via a
qualified name, e.g.,
foo::x
so that we retain the nested-name-specifier as written in the source
code and can reproduce that qualified name when printing the types
back (e.g., in diagnostics). This is PR3493, which won't be complete
until finished the other tasks mentioned near the end of this commit.
The parser's representation of nested-name-specifiers, CXXScopeSpec,
is now a bit fatter, because it needs to contain the scopes that
precede each '::' and keep track of whether the global scoping
operator '::' was at the beginning. For example, we need to keep track
of the leading '::', 'foo', and 'bar' in
::foo::bar::x
The Action's CXXScopeTy * is no longer a DeclContext *. It's now the
opaque version of the new NestedNameSpecifier, which contains a single
component of a nested-name-specifier (either a DeclContext * or a Type
*, bitmangled).
The new sugar type QualifiedNameType composes a sequence of
NestedNameSpecifiers with a representation of the type we're actually
referring to. At present, we only build QualifiedNameType nodes within
Sema::getTypeName. This will be extended to other type-constructing
actions (e.g., ActOnClassTemplateId).
Also on the way: QualifiedDeclRefExprs will also store a sequence of
NestedNameSpecifiers, so that we can print out the property
nested-name-specifier. I expect to also use this for handling
dependent names like Fibonacci<I - 1>::value.
llvm-svn: 67265
2009-03-19 08:18:19 +08:00
|
|
|
Types.push_back(T);
|
2010-05-12 05:36:43 +08:00
|
|
|
ElaboratedTypes.InsertNode(T, InsertPos);
|
Introduce a representation for types that we referred to via a
qualified name, e.g.,
foo::x
so that we retain the nested-name-specifier as written in the source
code and can reproduce that qualified name when printing the types
back (e.g., in diagnostics). This is PR3493, which won't be complete
until finished the other tasks mentioned near the end of this commit.
The parser's representation of nested-name-specifiers, CXXScopeSpec,
is now a bit fatter, because it needs to contain the scopes that
precede each '::' and keep track of whether the global scoping
operator '::' was at the beginning. For example, we need to keep track
of the leading '::', 'foo', and 'bar' in
::foo::bar::x
The Action's CXXScopeTy * is no longer a DeclContext *. It's now the
opaque version of the new NestedNameSpecifier, which contains a single
component of a nested-name-specifier (either a DeclContext * or a Type
*, bitmangled).
The new sugar type QualifiedNameType composes a sequence of
NestedNameSpecifiers with a representation of the type we're actually
referring to. At present, we only build QualifiedNameType nodes within
Sema::getTypeName. This will be extended to other type-constructing
actions (e.g., ActOnClassTemplateId).
Also on the way: QualifiedDeclRefExprs will also store a sequence of
NestedNameSpecifiers, so that we can print out the property
nested-name-specifier. I expect to also use this for handling
dependent names like Fibonacci<I - 1>::value.
llvm-svn: 67265
2009-03-19 08:18:19 +08:00
|
|
|
return QualType(T, 0);
|
|
|
|
}
|
|
|
|
|
2010-12-11 00:29:40 +08:00
|
|
|
QualType
|
2011-01-12 17:06:06 +08:00
|
|
|
ASTContext::getParenType(QualType InnerType) const {
|
2010-12-11 00:29:40 +08:00
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
ParenType::Profile(ID, InnerType);
|
|
|
|
|
|
|
|
void *InsertPos = 0;
|
|
|
|
ParenType *T = ParenTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
if (T)
|
|
|
|
return QualType(T, 0);
|
|
|
|
|
|
|
|
QualType Canon = InnerType;
|
|
|
|
if (!Canon.isCanonical()) {
|
|
|
|
Canon = getCanonicalType(InnerType);
|
|
|
|
ParenType *CheckT = ParenTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
assert(!CheckT && "Paren canonical type broken");
|
|
|
|
(void)CheckT;
|
|
|
|
}
|
|
|
|
|
|
|
|
T = new (*this) ParenType(InnerType, Canon);
|
|
|
|
Types.push_back(T);
|
|
|
|
ParenTypes.InsertNode(T, InsertPos);
|
|
|
|
return QualType(T, 0);
|
|
|
|
}
|
|
|
|
|
2010-04-01 04:19:30 +08:00
|
|
|
QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword,
|
|
|
|
NestedNameSpecifier *NNS,
|
|
|
|
const IdentifierInfo *Name,
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType Canon) const {
|
2009-03-28 07:10:48 +08:00
|
|
|
assert(NNS->isDependent() && "nested-name-specifier must be dependent");
|
|
|
|
|
|
|
|
if (Canon.isNull()) {
|
|
|
|
NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
|
2010-04-01 04:19:30 +08:00
|
|
|
ElaboratedTypeKeyword CanonKeyword = Keyword;
|
|
|
|
if (Keyword == ETK_None)
|
|
|
|
CanonKeyword = ETK_Typename;
|
|
|
|
|
|
|
|
if (CanonNNS != NNS || CanonKeyword != Keyword)
|
|
|
|
Canon = getDependentNameType(CanonKeyword, CanonNNS, Name);
|
2009-03-28 07:10:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
llvm::FoldingSetNodeID ID;
|
2010-04-01 04:19:30 +08:00
|
|
|
DependentNameType::Profile(ID, Keyword, NNS, Name);
|
2009-03-28 07:10:48 +08:00
|
|
|
|
|
|
|
void *InsertPos = 0;
|
2010-04-01 01:34:00 +08:00
|
|
|
DependentNameType *T
|
|
|
|
= DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos);
|
2009-03-28 07:10:48 +08:00
|
|
|
if (T)
|
|
|
|
return QualType(T, 0);
|
|
|
|
|
2010-04-01 04:19:30 +08:00
|
|
|
T = new (*this) DependentNameType(Keyword, NNS, Name, Canon);
|
2009-03-28 07:10:48 +08:00
|
|
|
Types.push_back(T);
|
2010-04-01 01:34:00 +08:00
|
|
|
DependentNameTypes.InsertNode(T, InsertPos);
|
2009-09-09 23:08:12 +08:00
|
|
|
return QualType(T, 0);
|
2009-03-28 07:10:48 +08:00
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
QualType
|
2010-06-11 08:33:02 +08:00
|
|
|
ASTContext::getDependentTemplateSpecializationType(
|
|
|
|
ElaboratedTypeKeyword Keyword,
|
2010-04-01 04:19:30 +08:00
|
|
|
NestedNameSpecifier *NNS,
|
2010-06-11 08:33:02 +08:00
|
|
|
const IdentifierInfo *Name,
|
2011-01-12 17:06:06 +08:00
|
|
|
const TemplateArgumentListInfo &Args) const {
|
2010-06-11 08:33:02 +08:00
|
|
|
// TODO: avoid this copy
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<TemplateArgument, 16> ArgCopy;
|
2010-06-11 08:33:02 +08:00
|
|
|
for (unsigned I = 0, E = Args.size(); I != E; ++I)
|
|
|
|
ArgCopy.push_back(Args[I].getArgument());
|
|
|
|
return getDependentTemplateSpecializationType(Keyword, NNS, Name,
|
|
|
|
ArgCopy.size(),
|
|
|
|
ArgCopy.data());
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType
|
|
|
|
ASTContext::getDependentTemplateSpecializationType(
|
|
|
|
ElaboratedTypeKeyword Keyword,
|
|
|
|
NestedNameSpecifier *NNS,
|
|
|
|
const IdentifierInfo *Name,
|
|
|
|
unsigned NumArgs,
|
2011-01-12 17:06:06 +08:00
|
|
|
const TemplateArgument *Args) const {
|
2011-02-28 08:04:36 +08:00
|
|
|
assert((!NNS || NNS->isDependent()) &&
|
|
|
|
"nested-name-specifier must be dependent");
|
2009-04-01 08:28:59 +08:00
|
|
|
|
Fix an obscure crash found in the Boost.MPL test suite, along with a
ton of potential crashes of the same kind. The fundamental problem is
that type creation was following a dangerous pattern when using its
FoldingSets:
1) Use FindNodeOrInsertPos to see if the type is available
2) If not, and we aren't looking at a canonical type, build the
canonical type
3) Build and insert the new node into the FoldingSet
The problem here is that building the canonical type can, in very rare
circumstances, force the hash table inside the FoldingSet to
reallocate. That invalidates the insertion position we computed in
step 1, and in step 3 we end up inserting the new node into the wrong
place. BOOM!
I've audited all of ASTContext, fixing this problem everywhere I found
it. The vast majority of wrong code was C++-specific (and *ahem*
written by me), so I also audited other major folding sets in the C++
code (e.g., template specializations), but found no other instances of
this problem.
llvm-svn: 95315
2010-02-05 02:10:26 +08:00
|
|
|
llvm::FoldingSetNodeID ID;
|
2010-06-11 08:33:02 +08:00
|
|
|
DependentTemplateSpecializationType::Profile(ID, *this, Keyword, NNS,
|
|
|
|
Name, NumArgs, Args);
|
Fix an obscure crash found in the Boost.MPL test suite, along with a
ton of potential crashes of the same kind. The fundamental problem is
that type creation was following a dangerous pattern when using its
FoldingSets:
1) Use FindNodeOrInsertPos to see if the type is available
2) If not, and we aren't looking at a canonical type, build the
canonical type
3) Build and insert the new node into the FoldingSet
The problem here is that building the canonical type can, in very rare
circumstances, force the hash table inside the FoldingSet to
reallocate. That invalidates the insertion position we computed in
step 1, and in step 3 we end up inserting the new node into the wrong
place. BOOM!
I've audited all of ASTContext, fixing this problem everywhere I found
it. The vast majority of wrong code was C++-specific (and *ahem*
written by me), so I also audited other major folding sets in the C++
code (e.g., template specializations), but found no other instances of
this problem.
llvm-svn: 95315
2010-02-05 02:10:26 +08:00
|
|
|
|
|
|
|
void *InsertPos = 0;
|
2010-06-11 08:33:02 +08:00
|
|
|
DependentTemplateSpecializationType *T
|
|
|
|
= DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
|
Fix an obscure crash found in the Boost.MPL test suite, along with a
ton of potential crashes of the same kind. The fundamental problem is
that type creation was following a dangerous pattern when using its
FoldingSets:
1) Use FindNodeOrInsertPos to see if the type is available
2) If not, and we aren't looking at a canonical type, build the
canonical type
3) Build and insert the new node into the FoldingSet
The problem here is that building the canonical type can, in very rare
circumstances, force the hash table inside the FoldingSet to
reallocate. That invalidates the insertion position we computed in
step 1, and in step 3 we end up inserting the new node into the wrong
place. BOOM!
I've audited all of ASTContext, fixing this problem everywhere I found
it. The vast majority of wrong code was C++-specific (and *ahem*
written by me), so I also audited other major folding sets in the C++
code (e.g., template specializations), but found no other instances of
this problem.
llvm-svn: 95315
2010-02-05 02:10:26 +08:00
|
|
|
if (T)
|
|
|
|
return QualType(T, 0);
|
|
|
|
|
2010-06-11 08:33:02 +08:00
|
|
|
NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
|
|
|
|
|
|
|
|
ElaboratedTypeKeyword CanonKeyword = Keyword;
|
|
|
|
if (Keyword == ETK_None) CanonKeyword = ETK_Typename;
|
2009-04-01 08:28:59 +08:00
|
|
|
|
2010-06-11 08:33:02 +08:00
|
|
|
bool AnyNonCanonArgs = false;
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<TemplateArgument, 16> CanonArgs(NumArgs);
|
2010-06-11 08:33:02 +08:00
|
|
|
for (unsigned I = 0; I != NumArgs; ++I) {
|
|
|
|
CanonArgs[I] = getCanonicalTemplateArgument(Args[I]);
|
|
|
|
if (!CanonArgs[I].structurallyEquals(Args[I]))
|
|
|
|
AnyNonCanonArgs = true;
|
Fix an obscure crash found in the Boost.MPL test suite, along with a
ton of potential crashes of the same kind. The fundamental problem is
that type creation was following a dangerous pattern when using its
FoldingSets:
1) Use FindNodeOrInsertPos to see if the type is available
2) If not, and we aren't looking at a canonical type, build the
canonical type
3) Build and insert the new node into the FoldingSet
The problem here is that building the canonical type can, in very rare
circumstances, force the hash table inside the FoldingSet to
reallocate. That invalidates the insertion position we computed in
step 1, and in step 3 we end up inserting the new node into the wrong
place. BOOM!
I've audited all of ASTContext, fixing this problem everywhere I found
it. The vast majority of wrong code was C++-specific (and *ahem*
written by me), so I also audited other major folding sets in the C++
code (e.g., template specializations), but found no other instances of
this problem.
llvm-svn: 95315
2010-02-05 02:10:26 +08:00
|
|
|
}
|
2009-04-01 08:28:59 +08:00
|
|
|
|
2010-06-11 08:33:02 +08:00
|
|
|
QualType Canon;
|
|
|
|
if (AnyNonCanonArgs || CanonNNS != NNS || CanonKeyword != Keyword) {
|
|
|
|
Canon = getDependentTemplateSpecializationType(CanonKeyword, CanonNNS,
|
|
|
|
Name, NumArgs,
|
|
|
|
CanonArgs.data());
|
|
|
|
|
|
|
|
// Find the insert position again.
|
|
|
|
DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *Mem = Allocate((sizeof(DependentTemplateSpecializationType) +
|
|
|
|
sizeof(TemplateArgument) * NumArgs),
|
|
|
|
TypeAlignment);
|
2010-06-11 19:07:21 +08:00
|
|
|
T = new (Mem) DependentTemplateSpecializationType(Keyword, NNS,
|
2010-06-11 08:33:02 +08:00
|
|
|
Name, NumArgs, Args, Canon);
|
2009-04-01 08:28:59 +08:00
|
|
|
Types.push_back(T);
|
2010-06-11 08:33:02 +08:00
|
|
|
DependentTemplateSpecializationTypes.InsertNode(T, InsertPos);
|
2009-09-09 23:08:12 +08:00
|
|
|
return QualType(T, 0);
|
2009-04-01 08:28:59 +08:00
|
|
|
}
|
|
|
|
|
2011-01-15 01:04:44 +08:00
|
|
|
QualType ASTContext::getPackExpansionType(QualType Pattern,
|
|
|
|
llvm::Optional<unsigned> NumExpansions) {
|
2010-12-20 10:24:11 +08:00
|
|
|
llvm::FoldingSetNodeID ID;
|
2011-01-15 01:04:44 +08:00
|
|
|
PackExpansionType::Profile(ID, Pattern, NumExpansions);
|
2010-12-20 10:24:11 +08:00
|
|
|
|
|
|
|
assert(Pattern->containsUnexpandedParameterPack() &&
|
|
|
|
"Pack expansions must expand one or more parameter packs");
|
|
|
|
void *InsertPos = 0;
|
|
|
|
PackExpansionType *T
|
|
|
|
= PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
if (T)
|
|
|
|
return QualType(T, 0);
|
|
|
|
|
|
|
|
QualType Canon;
|
|
|
|
if (!Pattern.isCanonical()) {
|
2012-07-16 08:20:35 +08:00
|
|
|
Canon = getCanonicalType(Pattern);
|
|
|
|
// The canonical type might not contain an unexpanded parameter pack, if it
|
|
|
|
// contains an alias template specialization which ignores one of its
|
|
|
|
// parameters.
|
|
|
|
if (Canon->containsUnexpandedParameterPack()) {
|
|
|
|
Canon = getPackExpansionType(getCanonicalType(Pattern), NumExpansions);
|
|
|
|
|
|
|
|
// Find the insert position again, in case we inserted an element into
|
|
|
|
// PackExpansionTypes and invalidated our insert position.
|
|
|
|
PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
}
|
2010-12-20 10:24:11 +08:00
|
|
|
}
|
|
|
|
|
2011-01-15 01:04:44 +08:00
|
|
|
T = new (*this) PackExpansionType(Pattern, Canon, NumExpansions);
|
2010-12-20 10:24:11 +08:00
|
|
|
Types.push_back(T);
|
|
|
|
PackExpansionTypes.InsertNode(T, InsertPos);
|
|
|
|
return QualType(T, 0);
|
|
|
|
}
|
|
|
|
|
2008-04-07 12:56:42 +08:00
|
|
|
/// CmpProtocolNames - Comparison predicate for sorting protocols
|
|
|
|
/// alphabetically.
|
|
|
|
static bool CmpProtocolNames(const ObjCProtocolDecl *LHS,
|
|
|
|
const ObjCProtocolDecl *RHS) {
|
2008-11-17 22:58:09 +08:00
|
|
|
return LHS->getDeclName() < RHS->getDeclName();
|
2008-04-07 12:56:42 +08:00
|
|
|
}
|
|
|
|
|
2010-05-15 19:32:37 +08:00
|
|
|
static bool areSortedAndUniqued(ObjCProtocolDecl * const *Protocols,
|
2009-10-23 06:37:11 +08:00
|
|
|
unsigned NumProtocols) {
|
|
|
|
if (NumProtocols == 0) return true;
|
|
|
|
|
2012-01-02 10:00:30 +08:00
|
|
|
if (Protocols[0]->getCanonicalDecl() != Protocols[0])
|
|
|
|
return false;
|
|
|
|
|
2009-10-23 06:37:11 +08:00
|
|
|
for (unsigned i = 1; i != NumProtocols; ++i)
|
2012-01-02 10:00:30 +08:00
|
|
|
if (!CmpProtocolNames(Protocols[i-1], Protocols[i]) ||
|
|
|
|
Protocols[i]->getCanonicalDecl() != Protocols[i])
|
2009-10-23 06:37:11 +08:00
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols,
|
2008-04-07 12:56:42 +08:00
|
|
|
unsigned &NumProtocols) {
|
|
|
|
ObjCProtocolDecl **ProtocolsEnd = Protocols+NumProtocols;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-04-07 12:56:42 +08:00
|
|
|
// Sort protocols, keyed by name.
|
|
|
|
std::sort(Protocols, Protocols+NumProtocols, CmpProtocolNames);
|
|
|
|
|
2012-01-02 10:00:30 +08:00
|
|
|
// Canonicalize.
|
|
|
|
for (unsigned I = 0, N = NumProtocols; I != N; ++I)
|
|
|
|
Protocols[I] = Protocols[I]->getCanonicalDecl();
|
|
|
|
|
2008-04-07 12:56:42 +08:00
|
|
|
// Remove duplicates.
|
|
|
|
ProtocolsEnd = std::unique(Protocols, ProtocolsEnd);
|
|
|
|
NumProtocols = ProtocolsEnd-Protocols;
|
|
|
|
}
|
|
|
|
|
2010-05-15 19:32:37 +08:00
|
|
|
QualType ASTContext::getObjCObjectType(QualType BaseType,
|
|
|
|
ObjCProtocolDecl * const *Protocols,
|
2011-01-12 17:06:06 +08:00
|
|
|
unsigned NumProtocols) const {
|
2010-05-15 19:32:37 +08:00
|
|
|
// If the base type is an interface and there aren't any protocols
|
|
|
|
// to add, then the interface type will do just fine.
|
|
|
|
if (!NumProtocols && isa<ObjCInterfaceType>(BaseType))
|
|
|
|
return BaseType;
|
2009-06-18 06:40:22 +08:00
|
|
|
|
2010-05-15 19:32:37 +08:00
|
|
|
// Look in the folding set for an existing type.
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
ObjCObjectTypeImpl::Profile(ID, BaseType, Protocols, NumProtocols);
|
2009-06-18 06:40:22 +08:00
|
|
|
void *InsertPos = 0;
|
2010-05-15 19:32:37 +08:00
|
|
|
if (ObjCObjectType *QT = ObjCObjectTypes.FindNodeOrInsertPos(ID, InsertPos))
|
|
|
|
return QualType(QT, 0);
|
2009-06-18 06:40:22 +08:00
|
|
|
|
2010-05-15 19:32:37 +08:00
|
|
|
// Build the canonical type, which has the canonical base type and
|
|
|
|
// a sorted-and-uniqued list of protocols.
|
2009-10-23 06:37:11 +08:00
|
|
|
QualType Canonical;
|
2010-05-15 19:32:37 +08:00
|
|
|
bool ProtocolsSorted = areSortedAndUniqued(Protocols, NumProtocols);
|
|
|
|
if (!ProtocolsSorted || !BaseType.isCanonical()) {
|
|
|
|
if (!ProtocolsSorted) {
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<ObjCProtocolDecl*, 8> Sorted(Protocols,
|
2010-04-28 01:12:11 +08:00
|
|
|
Protocols + NumProtocols);
|
2009-10-23 06:37:11 +08:00
|
|
|
unsigned UniqueCount = NumProtocols;
|
|
|
|
|
|
|
|
SortAndUniqueProtocols(&Sorted[0], UniqueCount);
|
2010-05-15 19:32:37 +08:00
|
|
|
Canonical = getObjCObjectType(getCanonicalType(BaseType),
|
|
|
|
&Sorted[0], UniqueCount);
|
2009-10-23 06:37:11 +08:00
|
|
|
} else {
|
2010-05-15 19:32:37 +08:00
|
|
|
Canonical = getObjCObjectType(getCanonicalType(BaseType),
|
|
|
|
Protocols, NumProtocols);
|
2009-10-23 06:37:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Regenerate InsertPos.
|
2010-05-15 19:32:37 +08:00
|
|
|
ObjCObjectTypes.FindNodeOrInsertPos(ID, InsertPos);
|
2009-10-23 06:37:11 +08:00
|
|
|
}
|
|
|
|
|
2010-05-15 19:32:37 +08:00
|
|
|
unsigned Size = sizeof(ObjCObjectTypeImpl);
|
|
|
|
Size += NumProtocols * sizeof(ObjCProtocolDecl *);
|
2010-02-09 06:59:26 +08:00
|
|
|
void *Mem = Allocate(Size, TypeAlignment);
|
2010-05-15 19:32:37 +08:00
|
|
|
ObjCObjectTypeImpl *T =
|
|
|
|
new (Mem) ObjCObjectTypeImpl(Canonical, BaseType, Protocols, NumProtocols);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-05-15 19:32:37 +08:00
|
|
|
Types.push_back(T);
|
|
|
|
ObjCObjectTypes.InsertNode(T, InsertPos);
|
|
|
|
return QualType(T, 0);
|
2009-06-18 06:40:22 +08:00
|
|
|
}
|
2008-04-07 12:56:42 +08:00
|
|
|
|
2010-05-15 19:32:37 +08:00
|
|
|
/// getObjCObjectPointerType - Return a ObjCObjectPointerType type for
|
|
|
|
/// the given object type.
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType ASTContext::getObjCObjectPointerType(QualType ObjectT) const {
|
2007-10-11 08:55:41 +08:00
|
|
|
llvm::FoldingSetNodeID ID;
|
2010-05-15 19:32:37 +08:00
|
|
|
ObjCObjectPointerType::Profile(ID, ObjectT);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-10-11 08:55:41 +08:00
|
|
|
void *InsertPos = 0;
|
2010-05-15 19:32:37 +08:00
|
|
|
if (ObjCObjectPointerType *QT =
|
|
|
|
ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
|
2007-10-11 08:55:41 +08:00
|
|
|
return QualType(QT, 0);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-05-15 19:32:37 +08:00
|
|
|
// Find the canonical object type.
|
2009-10-23 06:37:11 +08:00
|
|
|
QualType Canonical;
|
2010-05-15 19:32:37 +08:00
|
|
|
if (!ObjectT.isCanonical()) {
|
|
|
|
Canonical = getObjCObjectPointerType(getCanonicalType(ObjectT));
|
2009-10-23 06:37:11 +08:00
|
|
|
|
2010-05-15 19:32:37 +08:00
|
|
|
// Regenerate InsertPos.
|
|
|
|
ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
|
2009-10-23 06:37:11 +08:00
|
|
|
}
|
|
|
|
|
2010-05-15 19:32:37 +08:00
|
|
|
// No match.
|
|
|
|
void *Mem = Allocate(sizeof(ObjCObjectPointerType), TypeAlignment);
|
|
|
|
ObjCObjectPointerType *QType =
|
|
|
|
new (Mem) ObjCObjectPointerType(Canonical, ObjectT);
|
2009-09-30 03:42:55 +08:00
|
|
|
|
|
|
|
Types.push_back(QType);
|
2010-05-15 19:32:37 +08:00
|
|
|
ObjCObjectPointerTypes.InsertNode(QType, InsertPos);
|
2009-09-30 03:42:55 +08:00
|
|
|
return QualType(QType, 0);
|
|
|
|
}
|
|
|
|
|
2010-08-11 20:19:30 +08:00
|
|
|
/// getObjCInterfaceType - Return the unique reference to the type for the
|
|
|
|
/// specified ObjC interface decl. The list of protocols is optional.
|
2011-12-16 11:12:41 +08:00
|
|
|
QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
|
|
|
|
ObjCInterfaceDecl *PrevDecl) const {
|
2010-08-11 20:19:30 +08:00
|
|
|
if (Decl->TypeForDecl)
|
|
|
|
return QualType(Decl->TypeForDecl, 0);
|
2010-08-10 05:55:28 +08:00
|
|
|
|
2011-12-16 11:12:41 +08:00
|
|
|
if (PrevDecl) {
|
|
|
|
assert(PrevDecl->TypeForDecl && "previous decl has no TypeForDecl");
|
|
|
|
Decl->TypeForDecl = PrevDecl->TypeForDecl;
|
|
|
|
return QualType(PrevDecl->TypeForDecl, 0);
|
|
|
|
}
|
|
|
|
|
2011-12-17 00:34:57 +08:00
|
|
|
// Prefer the definition, if there is one.
|
|
|
|
if (const ObjCInterfaceDecl *Def = Decl->getDefinition())
|
|
|
|
Decl = Def;
|
|
|
|
|
2010-08-11 20:19:30 +08:00
|
|
|
void *Mem = Allocate(sizeof(ObjCInterfaceType), TypeAlignment);
|
|
|
|
ObjCInterfaceType *T = new (Mem) ObjCInterfaceType(Decl);
|
|
|
|
Decl->TypeForDecl = T;
|
|
|
|
Types.push_back(T);
|
|
|
|
return QualType(T, 0);
|
2010-05-15 19:32:37 +08:00
|
|
|
}
|
|
|
|
|
2009-02-27 07:50:07 +08:00
|
|
|
/// getTypeOfExprType - Unlike many "get<Type>" functions, we can't unique
|
|
|
|
/// TypeOfExprType AST's (since expression's are never shared). For example,
|
2007-08-02 02:02:17 +08:00
|
|
|
/// multiple declarations that refer to "typeof(x)" all contain different
|
2009-09-09 23:08:12 +08:00
|
|
|
/// DeclRefExpr's. This doesn't effect the type checker, since it operates
|
2007-08-02 02:02:17 +08:00
|
|
|
/// on canonical type's (which are always unique).
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType ASTContext::getTypeOfExprType(Expr *tofExpr) const {
|
2009-07-08 08:03:05 +08:00
|
|
|
TypeOfExprType *toe;
|
2009-07-31 07:18:24 +08:00
|
|
|
if (tofExpr->isTypeDependent()) {
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
DependentTypeOfExprType::Profile(ID, *this, tofExpr);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-31 07:18:24 +08:00
|
|
|
void *InsertPos = 0;
|
|
|
|
DependentTypeOfExprType *Canon
|
|
|
|
= DependentTypeOfExprTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
if (Canon) {
|
|
|
|
// We already have a "canonical" version of an identical, dependent
|
|
|
|
// typeof(expr) type. Use that as our canonical type.
|
2009-09-25 07:30:46 +08:00
|
|
|
toe = new (*this, TypeAlignment) TypeOfExprType(tofExpr,
|
2009-07-31 07:18:24 +08:00
|
|
|
QualType((TypeOfExprType*)Canon, 0));
|
2011-08-18 07:08:45 +08:00
|
|
|
} else {
|
2009-07-31 07:18:24 +08:00
|
|
|
// Build a new, canonical typeof(expr) type.
|
2009-09-25 07:30:46 +08:00
|
|
|
Canon
|
|
|
|
= new (*this, TypeAlignment) DependentTypeOfExprType(*this, tofExpr);
|
2009-07-31 07:18:24 +08:00
|
|
|
DependentTypeOfExprTypes.InsertNode(Canon, InsertPos);
|
|
|
|
toe = Canon;
|
|
|
|
}
|
|
|
|
} else {
|
2009-07-08 08:03:05 +08:00
|
|
|
QualType Canonical = getCanonicalType(tofExpr->getType());
|
2009-09-25 07:30:46 +08:00
|
|
|
toe = new (*this, TypeAlignment) TypeOfExprType(tofExpr, Canonical);
|
2009-07-08 08:03:05 +08:00
|
|
|
}
|
2007-08-02 02:02:17 +08:00
|
|
|
Types.push_back(toe);
|
|
|
|
return QualType(toe, 0);
|
2007-07-31 20:34:36 +08:00
|
|
|
}
|
|
|
|
|
2007-08-02 02:02:17 +08:00
|
|
|
/// getTypeOfType - Unlike many "get<Type>" functions, we don't unique
|
|
|
|
/// TypeOfType AST's. The only motivation to unique these nodes would be
|
|
|
|
/// memory savings. Since typeof(t) is fairly uncommon, space shouldn't be
|
2009-09-09 23:08:12 +08:00
|
|
|
/// an issue. This doesn't effect the type checker, since it operates
|
2007-08-02 02:02:17 +08:00
|
|
|
/// on canonical type's (which are always unique).
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType ASTContext::getTypeOfType(QualType tofType) const {
|
2008-04-07 06:59:24 +08:00
|
|
|
QualType Canonical = getCanonicalType(tofType);
|
2009-09-25 07:30:46 +08:00
|
|
|
TypeOfType *tot = new (*this, TypeAlignment) TypeOfType(tofType, Canonical);
|
2007-08-02 02:02:17 +08:00
|
|
|
Types.push_back(tot);
|
|
|
|
return QualType(tot, 0);
|
2007-07-31 20:34:36 +08:00
|
|
|
}
|
|
|
|
|
2009-06-25 05:24:56 +08:00
|
|
|
|
2009-06-25 03:06:50 +08:00
|
|
|
/// getDecltypeType - Unlike many "get<Type>" functions, we don't unique
|
|
|
|
/// DecltypeType AST's. The only motivation to unique these nodes would be
|
|
|
|
/// memory savings. Since decltype(t) is fairly uncommon, space shouldn't be
|
2009-09-09 23:08:12 +08:00
|
|
|
/// an issue. This doesn't effect the type checker, since it operates
|
2011-11-07 06:28:03 +08:00
|
|
|
/// on canonical types (which are always unique).
|
2012-02-13 02:42:33 +08:00
|
|
|
QualType ASTContext::getDecltypeType(Expr *e, QualType UnderlyingType) const {
|
2009-07-08 08:03:05 +08:00
|
|
|
DecltypeType *dt;
|
2011-07-01 09:22:09 +08:00
|
|
|
|
|
|
|
// C++0x [temp.type]p2:
|
|
|
|
// If an expression e involves a template parameter, decltype(e) denotes a
|
|
|
|
// unique dependent type. Two such decltype-specifiers refer to the same
|
|
|
|
// type only if their expressions are equivalent (14.5.6.1).
|
|
|
|
if (e->isInstantiationDependent()) {
|
2009-07-31 07:36:40 +08:00
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
DependentDecltypeType::Profile(ID, *this, e);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-31 07:36:40 +08:00
|
|
|
void *InsertPos = 0;
|
|
|
|
DependentDecltypeType *Canon
|
|
|
|
= DependentDecltypeTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
if (Canon) {
|
|
|
|
// We already have a "canonical" version of an equivalent, dependent
|
|
|
|
// decltype type. Use that as our canonical type.
|
2012-08-14 04:08:14 +08:00
|
|
|
dt = new (*this, TypeAlignment) DecltypeType(e, UnderlyingType,
|
2009-07-31 07:36:40 +08:00
|
|
|
QualType((DecltypeType*)Canon, 0));
|
2011-08-18 07:08:45 +08:00
|
|
|
} else {
|
2009-07-31 07:36:40 +08:00
|
|
|
// Build a new, canonical typeof(expr) type.
|
2009-09-25 07:30:46 +08:00
|
|
|
Canon = new (*this, TypeAlignment) DependentDecltypeType(*this, e);
|
2009-07-31 07:36:40 +08:00
|
|
|
DependentDecltypeTypes.InsertNode(Canon, InsertPos);
|
|
|
|
dt = Canon;
|
|
|
|
}
|
|
|
|
} else {
|
2012-02-13 02:42:33 +08:00
|
|
|
dt = new (*this, TypeAlignment) DecltypeType(e, UnderlyingType,
|
|
|
|
getCanonicalType(UnderlyingType));
|
2009-07-08 08:03:05 +08:00
|
|
|
}
|
2009-06-25 03:06:50 +08:00
|
|
|
Types.push_back(dt);
|
|
|
|
return QualType(dt, 0);
|
|
|
|
}
|
|
|
|
|
2011-05-25 06:41:36 +08:00
|
|
|
/// getUnaryTransformationType - We don't unique these, since the memory
|
|
|
|
/// savings are minimal and these are rare.
|
|
|
|
QualType ASTContext::getUnaryTransformType(QualType BaseType,
|
|
|
|
QualType UnderlyingType,
|
|
|
|
UnaryTransformType::UTTKind Kind)
|
|
|
|
const {
|
|
|
|
UnaryTransformType *Ty =
|
2011-05-26 01:51:54 +08:00
|
|
|
new (*this, TypeAlignment) UnaryTransformType (BaseType, UnderlyingType,
|
|
|
|
Kind,
|
|
|
|
UnderlyingType->isDependentType() ?
|
2012-03-06 00:02:06 +08:00
|
|
|
QualType() : getCanonicalType(UnderlyingType));
|
2011-05-25 06:41:36 +08:00
|
|
|
Types.push_back(Ty);
|
|
|
|
return QualType(Ty, 0);
|
|
|
|
}
|
|
|
|
|
2011-02-22 04:05:19 +08:00
|
|
|
/// getAutoType - We only unique auto types after they've been deduced.
|
2011-02-20 11:19:35 +08:00
|
|
|
QualType ASTContext::getAutoType(QualType DeducedType) const {
|
2011-02-22 04:05:19 +08:00
|
|
|
void *InsertPos = 0;
|
|
|
|
if (!DeducedType.isNull()) {
|
|
|
|
// Look in the folding set for an existing type.
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
AutoType::Profile(ID, DeducedType);
|
|
|
|
if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos))
|
|
|
|
return QualType(AT, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
AutoType *AT = new (*this, TypeAlignment) AutoType(DeducedType);
|
|
|
|
Types.push_back(AT);
|
|
|
|
if (InsertPos)
|
|
|
|
AutoTypes.InsertNode(AT, InsertPos);
|
|
|
|
return QualType(AT, 0);
|
2011-02-20 11:19:35 +08:00
|
|
|
}
|
|
|
|
|
2011-10-07 07:00:33 +08:00
|
|
|
/// getAtomicType - Return the uniqued reference to the atomic type for
|
|
|
|
/// the given value type.
|
|
|
|
QualType ASTContext::getAtomicType(QualType T) const {
|
|
|
|
// Unique pointers, to guarantee there is only one pointer of a particular
|
|
|
|
// structure.
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
AtomicType::Profile(ID, T);
|
|
|
|
|
|
|
|
void *InsertPos = 0;
|
|
|
|
if (AtomicType *AT = AtomicTypes.FindNodeOrInsertPos(ID, InsertPos))
|
|
|
|
return QualType(AT, 0);
|
|
|
|
|
|
|
|
// If the atomic value type isn't canonical, this won't be a canonical type
|
|
|
|
// either, so fill in the canonical type field.
|
|
|
|
QualType Canonical;
|
|
|
|
if (!T.isCanonical()) {
|
|
|
|
Canonical = getAtomicType(getCanonicalType(T));
|
|
|
|
|
|
|
|
// Get the new insert position for the node we care about.
|
|
|
|
AtomicType *NewIP = AtomicTypes.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
|
|
|
|
}
|
|
|
|
AtomicType *New = new (*this, TypeAlignment) AtomicType(T, Canonical);
|
|
|
|
Types.push_back(New);
|
|
|
|
AtomicTypes.InsertNode(New, InsertPos);
|
|
|
|
return QualType(New, 0);
|
|
|
|
}
|
|
|
|
|
2011-04-15 06:09:26 +08:00
|
|
|
/// getAutoDeductType - Get type pattern for deducing against 'auto'.
|
|
|
|
QualType ASTContext::getAutoDeductType() const {
|
|
|
|
if (AutoDeductTy.isNull())
|
|
|
|
AutoDeductTy = getAutoType(QualType());
|
|
|
|
assert(!AutoDeductTy.isNull() && "can't build 'auto' pattern");
|
|
|
|
return AutoDeductTy;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getAutoRRefDeductType - Get type pattern for deducing against 'auto &&'.
|
|
|
|
QualType ASTContext::getAutoRRefDeductType() const {
|
|
|
|
if (AutoRRefDeductTy.isNull())
|
|
|
|
AutoRRefDeductTy = getRValueReferenceType(getAutoDeductType());
|
|
|
|
assert(!AutoRRefDeductTy.isNull() && "can't build 'auto &&' pattern");
|
|
|
|
return AutoRRefDeductTy;
|
|
|
|
}
|
|
|
|
|
2007-01-23 13:45:31 +08:00
|
|
|
/// getTagDeclType - Return the unique reference to the type for the
|
|
|
|
/// specified TagDecl (struct/union/class/enum) decl.
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType ASTContext::getTagDeclType(const TagDecl *Decl) const {
|
2007-11-27 05:16:01 +08:00
|
|
|
assert (Decl);
|
2009-08-08 02:05:12 +08:00
|
|
|
// FIXME: What is the design on getTagDeclType when it requires casting
|
|
|
|
// away const? mutable?
|
|
|
|
return getTypeDeclType(const_cast<TagDecl*>(Decl));
|
2007-01-23 13:45:31 +08:00
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
/// getSizeType - Return the unique type for "size_t" (C99 7.17), the result
|
|
|
|
/// of the sizeof operator (C99 6.5.3.4p4). The value is target dependent and
|
|
|
|
/// needs to agree with the definition in <stddef.h>.
|
2009-12-12 08:26:23 +08:00
|
|
|
CanQualType ASTContext::getSizeType() const {
|
2011-09-02 08:18:52 +08:00
|
|
|
return getFromTargetType(Target->getSizeType());
|
2007-04-03 06:35:25 +08:00
|
|
|
}
|
2007-01-23 13:45:31 +08:00
|
|
|
|
2011-10-27 16:29:09 +08:00
|
|
|
/// getIntMaxType - Return the unique type for "intmax_t" (C99 7.18.1.5).
|
|
|
|
CanQualType ASTContext::getIntMaxType() const {
|
|
|
|
return getFromTargetType(Target->getIntMaxType());
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getUIntMaxType - Return the unique type for "uintmax_t" (C99 7.18.1.5).
|
|
|
|
CanQualType ASTContext::getUIntMaxType() const {
|
|
|
|
return getFromTargetType(Target->getUIntMaxType());
|
|
|
|
}
|
|
|
|
|
2008-08-10 00:51:54 +08:00
|
|
|
/// getSignedWCharType - Return the type of "signed wchar_t".
|
|
|
|
/// Used when in C++, as a GCC extension.
|
|
|
|
QualType ASTContext::getSignedWCharType() const {
|
|
|
|
// FIXME: derive from "Target" ?
|
|
|
|
return WCharTy;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// getUnsignedWCharType - Return the type of "unsigned wchar_t".
|
|
|
|
/// Used when in C++, as a GCC extension.
|
|
|
|
QualType ASTContext::getUnsignedWCharType() const {
|
|
|
|
// FIXME: derive from "Target" ?
|
|
|
|
return UnsignedIntTy;
|
|
|
|
}
|
|
|
|
|
2013-01-27 01:08:37 +08:00
|
|
|
QualType ASTContext::getIntPtrType() const {
|
|
|
|
return getFromTargetType(Target->getIntPtrType());
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType ASTContext::getUIntPtrType() const {
|
|
|
|
return getCorrespondingUnsignedType(getIntPtrType());
|
|
|
|
}
|
|
|
|
|
2011-10-27 16:29:09 +08:00
|
|
|
/// getPointerDiffType - Return the unique type for "ptrdiff_t" (C99 7.17)
|
2007-07-13 11:05:23 +08:00
|
|
|
/// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
|
|
|
|
QualType ASTContext::getPointerDiffType() const {
|
2011-09-02 08:18:52 +08:00
|
|
|
return getFromTargetType(Target->getPtrDiffType(0));
|
2007-07-13 11:05:23 +08:00
|
|
|
}
|
|
|
|
|
2012-11-27 10:58:24 +08:00
|
|
|
/// \brief Return the unique type for "pid_t" defined in
|
|
|
|
/// <sys/types.h>. We need this to compute the correct type for vfork().
|
|
|
|
QualType ASTContext::getProcessIDType() const {
|
|
|
|
return getFromTargetType(Target->getProcessIDType());
|
|
|
|
}
|
|
|
|
|
2008-04-02 13:18:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Type Operators
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-01-12 17:06:06 +08:00
|
|
|
CanQualType ASTContext::getCanonicalParamType(QualType T) const {
|
2009-10-23 06:37:11 +08:00
|
|
|
// Push qualifiers into arrays, and then discard any remaining
|
|
|
|
// qualifiers.
|
|
|
|
T = getCanonicalType(T);
|
2010-09-25 01:30:16 +08:00
|
|
|
T = getVariableArrayDecayedType(T);
|
2009-10-23 06:37:11 +08:00
|
|
|
const Type *Ty = T.getTypePtr();
|
|
|
|
QualType Result;
|
|
|
|
if (isa<ArrayType>(Ty)) {
|
|
|
|
Result = getArrayDecayedType(QualType(Ty,0));
|
|
|
|
} else if (isa<FunctionType>(Ty)) {
|
|
|
|
Result = getPointerType(QualType(Ty, 0));
|
|
|
|
} else {
|
|
|
|
Result = QualType(Ty, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return CanQualType::CreateUnsafe(Result);
|
|
|
|
}
|
|
|
|
|
2011-01-18 15:41:22 +08:00
|
|
|
QualType ASTContext::getUnqualifiedArrayType(QualType type,
|
|
|
|
Qualifiers &quals) {
|
|
|
|
SplitQualType splitType = type.getSplitUnqualifiedType();
|
|
|
|
|
|
|
|
// FIXME: getSplitUnqualifiedType() actually walks all the way to
|
|
|
|
// the unqualified desugared type and then drops it on the floor.
|
|
|
|
// We then have to strip that sugar back off with
|
|
|
|
// getUnqualifiedDesugaredType(), which is silly.
|
|
|
|
const ArrayType *AT =
|
2012-02-08 08:46:36 +08:00
|
|
|
dyn_cast<ArrayType>(splitType.Ty->getUnqualifiedDesugaredType());
|
2011-01-18 15:41:22 +08:00
|
|
|
|
|
|
|
// If we don't have an array, just use the results in splitType.
|
2010-05-18 02:45:21 +08:00
|
|
|
if (!AT) {
|
2012-02-08 08:46:36 +08:00
|
|
|
quals = splitType.Quals;
|
|
|
|
return QualType(splitType.Ty, 0);
|
2009-12-29 15:16:59 +08:00
|
|
|
}
|
|
|
|
|
2011-01-18 15:41:22 +08:00
|
|
|
// Otherwise, recurse on the array's element type.
|
|
|
|
QualType elementType = AT->getElementType();
|
|
|
|
QualType unqualElementType = getUnqualifiedArrayType(elementType, quals);
|
|
|
|
|
|
|
|
// If that didn't change the element type, AT has no qualifiers, so we
|
|
|
|
// can just use the results in splitType.
|
|
|
|
if (elementType == unqualElementType) {
|
|
|
|
assert(quals.empty()); // from the recursive call
|
2012-02-08 08:46:36 +08:00
|
|
|
quals = splitType.Quals;
|
|
|
|
return QualType(splitType.Ty, 0);
|
2011-01-18 15:41:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, add in the qualifiers from the outermost type, then
|
|
|
|
// build the type back up.
|
2012-02-08 08:46:36 +08:00
|
|
|
quals.addConsistentQualifiers(splitType.Quals);
|
2009-12-29 15:16:59 +08:00
|
|
|
|
2010-05-18 02:45:21 +08:00
|
|
|
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
|
2011-01-18 15:41:22 +08:00
|
|
|
return getConstantArrayType(unqualElementType, CAT->getSize(),
|
2009-12-29 15:16:59 +08:00
|
|
|
CAT->getSizeModifier(), 0);
|
|
|
|
}
|
|
|
|
|
2010-05-18 02:45:21 +08:00
|
|
|
if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) {
|
2011-01-18 15:41:22 +08:00
|
|
|
return getIncompleteArrayType(unqualElementType, IAT->getSizeModifier(), 0);
|
2009-12-29 15:16:59 +08:00
|
|
|
}
|
|
|
|
|
2010-05-18 02:45:21 +08:00
|
|
|
if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(AT)) {
|
2011-01-18 15:41:22 +08:00
|
|
|
return getVariableArrayType(unqualElementType,
|
2010-10-26 15:05:15 +08:00
|
|
|
VAT->getSizeExpr(),
|
2010-05-18 02:45:21 +08:00
|
|
|
VAT->getSizeModifier(),
|
|
|
|
VAT->getIndexTypeCVRQualifiers(),
|
|
|
|
VAT->getBracketsRange());
|
|
|
|
}
|
|
|
|
|
|
|
|
const DependentSizedArrayType *DSAT = cast<DependentSizedArrayType>(AT);
|
2011-01-18 15:41:22 +08:00
|
|
|
return getDependentSizedArrayType(unqualElementType, DSAT->getSizeExpr(),
|
2009-12-29 15:16:59 +08:00
|
|
|
DSAT->getSizeModifier(), 0,
|
|
|
|
SourceRange());
|
|
|
|
}
|
|
|
|
|
2010-06-09 11:53:18 +08:00
|
|
|
/// UnwrapSimilarPointerTypes - If T1 and T2 are pointer types that
|
|
|
|
/// may be similar (C++ 4.4), replaces T1 and T2 with the type that
|
|
|
|
/// they point to and return true. If T1 and T2 aren't pointer types
|
|
|
|
/// or pointer-to-member types, or if they are not similar at this
|
|
|
|
/// level, returns false and leaves T1 and T2 unchanged. Top-level
|
|
|
|
/// qualifiers on T1 and T2 are ignored. This function will typically
|
|
|
|
/// be called in a loop that successively "unwraps" pointer and
|
|
|
|
/// pointer-to-member types to compare them at each level.
|
|
|
|
bool ASTContext::UnwrapSimilarPointerTypes(QualType &T1, QualType &T2) {
|
|
|
|
const PointerType *T1PtrType = T1->getAs<PointerType>(),
|
|
|
|
*T2PtrType = T2->getAs<PointerType>();
|
|
|
|
if (T1PtrType && T2PtrType) {
|
|
|
|
T1 = T1PtrType->getPointeeType();
|
|
|
|
T2 = T2PtrType->getPointeeType();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(),
|
|
|
|
*T2MPType = T2->getAs<MemberPointerType>();
|
|
|
|
if (T1MPType && T2MPType &&
|
|
|
|
hasSameUnqualifiedType(QualType(T1MPType->getClass(), 0),
|
|
|
|
QualType(T2MPType->getClass(), 0))) {
|
|
|
|
T1 = T1MPType->getPointeeType();
|
|
|
|
T2 = T2MPType->getPointeeType();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-03-11 15:00:24 +08:00
|
|
|
if (getLangOpts().ObjC1) {
|
2010-06-09 11:53:18 +08:00
|
|
|
const ObjCObjectPointerType *T1OPType = T1->getAs<ObjCObjectPointerType>(),
|
|
|
|
*T2OPType = T2->getAs<ObjCObjectPointerType>();
|
|
|
|
if (T1OPType && T2OPType) {
|
|
|
|
T1 = T1OPType->getPointeeType();
|
|
|
|
T2 = T2OPType->getPointeeType();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: Block pointers, too?
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-01-12 17:06:06 +08:00
|
|
|
DeclarationNameInfo
|
|
|
|
ASTContext::getNameForTemplate(TemplateName Name,
|
|
|
|
SourceLocation NameLoc) const {
|
2011-06-30 16:33:18 +08:00
|
|
|
switch (Name.getKind()) {
|
|
|
|
case TemplateName::QualifiedTemplate:
|
|
|
|
case TemplateName::Template:
|
2010-08-12 06:01:17 +08:00
|
|
|
// DNInfo work in progress: CHECKME: what about DNLoc?
|
2011-06-30 16:33:18 +08:00
|
|
|
return DeclarationNameInfo(Name.getAsTemplateDecl()->getDeclName(),
|
|
|
|
NameLoc);
|
2010-08-12 06:01:17 +08:00
|
|
|
|
2011-06-30 16:33:18 +08:00
|
|
|
case TemplateName::OverloadedTemplate: {
|
|
|
|
OverloadedTemplateStorage *Storage = Name.getAsOverloadedTemplate();
|
|
|
|
// DNInfo work in progress: CHECKME: what about DNLoc?
|
|
|
|
return DeclarationNameInfo((*Storage->begin())->getDeclName(), NameLoc);
|
|
|
|
}
|
|
|
|
|
|
|
|
case TemplateName::DependentTemplate: {
|
|
|
|
DependentTemplateName *DTN = Name.getAsDependentTemplateName();
|
2010-08-12 06:01:17 +08:00
|
|
|
DeclarationName DName;
|
2009-11-25 02:42:40 +08:00
|
|
|
if (DTN->isIdentifier()) {
|
2010-08-12 06:01:17 +08:00
|
|
|
DName = DeclarationNames.getIdentifier(DTN->getIdentifier());
|
|
|
|
return DeclarationNameInfo(DName, NameLoc);
|
2009-11-25 02:42:40 +08:00
|
|
|
} else {
|
2010-08-12 06:01:17 +08:00
|
|
|
DName = DeclarationNames.getCXXOperatorName(DTN->getOperator());
|
|
|
|
// DNInfo work in progress: FIXME: source locations?
|
|
|
|
DeclarationNameLoc DNLoc;
|
|
|
|
DNLoc.CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
|
|
|
|
DNLoc.CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
|
|
|
|
return DeclarationNameInfo(DName, NameLoc, DNLoc);
|
2009-11-25 02:42:40 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-30 16:33:18 +08:00
|
|
|
case TemplateName::SubstTemplateTemplateParm: {
|
|
|
|
SubstTemplateTemplateParmStorage *subst
|
|
|
|
= Name.getAsSubstTemplateTemplateParm();
|
|
|
|
return DeclarationNameInfo(subst->getParameter()->getDeclName(),
|
|
|
|
NameLoc);
|
|
|
|
}
|
|
|
|
|
|
|
|
case TemplateName::SubstTemplateTemplateParmPack: {
|
|
|
|
SubstTemplateTemplateParmPackStorage *subst
|
|
|
|
= Name.getAsSubstTemplateTemplateParmPack();
|
|
|
|
return DeclarationNameInfo(subst->getParameterPack()->getDeclName(),
|
|
|
|
NameLoc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm_unreachable("bad template name kind!");
|
2009-11-25 02:42:40 +08:00
|
|
|
}
|
|
|
|
|
2011-01-12 17:06:06 +08:00
|
|
|
TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) const {
|
2011-06-30 16:33:18 +08:00
|
|
|
switch (Name.getKind()) {
|
|
|
|
case TemplateName::QualifiedTemplate:
|
|
|
|
case TemplateName::Template: {
|
|
|
|
TemplateDecl *Template = Name.getAsTemplateDecl();
|
2010-06-17 05:09:37 +08:00
|
|
|
if (TemplateTemplateParmDecl *TTP
|
2011-06-30 16:33:18 +08:00
|
|
|
= dyn_cast<TemplateTemplateParmDecl>(Template))
|
2010-06-17 05:09:37 +08:00
|
|
|
Template = getCanonicalTemplateTemplateParmDecl(TTP);
|
|
|
|
|
|
|
|
// The canonical template name is the canonical template declaration.
|
2009-07-18 08:34:25 +08:00
|
|
|
return TemplateName(cast<TemplateDecl>(Template->getCanonicalDecl()));
|
2010-06-17 05:09:37 +08:00
|
|
|
}
|
2009-05-07 14:41:52 +08:00
|
|
|
|
2011-06-30 16:33:18 +08:00
|
|
|
case TemplateName::OverloadedTemplate:
|
|
|
|
llvm_unreachable("cannot canonicalize overloaded template");
|
|
|
|
|
|
|
|
case TemplateName::DependentTemplate: {
|
|
|
|
DependentTemplateName *DTN = Name.getAsDependentTemplateName();
|
|
|
|
assert(DTN && "Non-dependent template names must refer to template decls.");
|
|
|
|
return DTN->CanonicalTemplateName;
|
|
|
|
}
|
|
|
|
|
|
|
|
case TemplateName::SubstTemplateTemplateParm: {
|
|
|
|
SubstTemplateTemplateParmStorage *subst
|
|
|
|
= Name.getAsSubstTemplateTemplateParm();
|
|
|
|
return getCanonicalTemplateName(subst->getReplacement());
|
2011-01-15 14:45:20 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-06-30 16:33:18 +08:00
|
|
|
case TemplateName::SubstTemplateTemplateParmPack: {
|
|
|
|
SubstTemplateTemplateParmPackStorage *subst
|
|
|
|
= Name.getAsSubstTemplateTemplateParmPack();
|
|
|
|
TemplateTemplateParmDecl *canonParameter
|
|
|
|
= getCanonicalTemplateTemplateParmDecl(subst->getParameterPack());
|
|
|
|
TemplateArgument canonArgPack
|
|
|
|
= getCanonicalTemplateArgument(subst->getArgumentPack());
|
|
|
|
return getSubstTemplateTemplateParmPack(canonParameter, canonArgPack);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm_unreachable("bad template name!");
|
2009-05-07 14:41:52 +08:00
|
|
|
}
|
|
|
|
|
2009-11-12 07:06:43 +08:00
|
|
|
bool ASTContext::hasSameTemplateName(TemplateName X, TemplateName Y) {
|
|
|
|
X = getCanonicalTemplateName(X);
|
|
|
|
Y = getCanonicalTemplateName(Y);
|
|
|
|
return X.getAsVoidPointer() == Y.getAsVoidPointer();
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
TemplateArgument
|
2011-01-12 17:06:06 +08:00
|
|
|
ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
|
2009-07-29 07:00:59 +08:00
|
|
|
switch (Arg.getKind()) {
|
|
|
|
case TemplateArgument::Null:
|
|
|
|
return Arg;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-29 07:00:59 +08:00
|
|
|
case TemplateArgument::Expression:
|
|
|
|
return Arg;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-04-07 06:40:38 +08:00
|
|
|
case TemplateArgument::Declaration: {
|
2012-09-26 10:36:12 +08:00
|
|
|
ValueDecl *D = cast<ValueDecl>(Arg.getAsDecl()->getCanonicalDecl());
|
|
|
|
return TemplateArgument(D, Arg.isDeclForReferenceParam());
|
2012-04-07 06:40:38 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-09-26 10:36:12 +08:00
|
|
|
case TemplateArgument::NullPtr:
|
|
|
|
return TemplateArgument(getCanonicalType(Arg.getNullPtrType()),
|
|
|
|
/*isNullPtr*/true);
|
|
|
|
|
2009-11-11 09:00:40 +08:00
|
|
|
case TemplateArgument::Template:
|
|
|
|
return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate()));
|
2011-01-06 02:58:31 +08:00
|
|
|
|
|
|
|
case TemplateArgument::TemplateExpansion:
|
|
|
|
return TemplateArgument(getCanonicalTemplateName(
|
|
|
|
Arg.getAsTemplateOrTemplatePattern()),
|
2011-01-15 07:41:42 +08:00
|
|
|
Arg.getNumTemplateExpansions());
|
2011-01-06 02:58:31 +08:00
|
|
|
|
2009-07-29 07:00:59 +08:00
|
|
|
case TemplateArgument::Integral:
|
2012-06-07 23:09:51 +08:00
|
|
|
return TemplateArgument(Arg, getCanonicalType(Arg.getIntegralType()));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-29 07:00:59 +08:00
|
|
|
case TemplateArgument::Type:
|
2009-10-29 16:12:44 +08:00
|
|
|
return TemplateArgument(getCanonicalType(Arg.getAsType()));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-29 07:00:59 +08:00
|
|
|
case TemplateArgument::Pack: {
|
2010-12-21 00:52:59 +08:00
|
|
|
if (Arg.pack_size() == 0)
|
|
|
|
return Arg;
|
|
|
|
|
2010-11-08 07:05:16 +08:00
|
|
|
TemplateArgument *CanonArgs
|
|
|
|
= new (*this) TemplateArgument[Arg.pack_size()];
|
2009-07-29 07:00:59 +08:00
|
|
|
unsigned Idx = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
for (TemplateArgument::pack_iterator A = Arg.pack_begin(),
|
2009-07-29 07:00:59 +08:00
|
|
|
AEnd = Arg.pack_end();
|
|
|
|
A != AEnd; (void)++A, ++Idx)
|
|
|
|
CanonArgs[Idx] = getCanonicalTemplateArgument(*A);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-11-08 07:05:16 +08:00
|
|
|
return TemplateArgument(CanonArgs, Arg.pack_size());
|
2009-07-29 07:00:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Silence GCC warning
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("Unhandled template argument kind");
|
2009-07-29 07:00:59 +08:00
|
|
|
}
|
|
|
|
|
2009-03-28 07:10:48 +08:00
|
|
|
NestedNameSpecifier *
|
2011-01-12 17:06:06 +08:00
|
|
|
ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
|
2009-09-09 23:08:12 +08:00
|
|
|
if (!NNS)
|
2009-03-28 07:10:48 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch (NNS->getKind()) {
|
|
|
|
case NestedNameSpecifier::Identifier:
|
|
|
|
// Canonicalize the prefix but keep the identifier the same.
|
2009-09-09 23:08:12 +08:00
|
|
|
return NestedNameSpecifier::Create(*this,
|
2009-03-28 07:10:48 +08:00
|
|
|
getCanonicalNestedNameSpecifier(NNS->getPrefix()),
|
|
|
|
NNS->getAsIdentifier());
|
|
|
|
|
|
|
|
case NestedNameSpecifier::Namespace:
|
|
|
|
// A namespace is canonical; build a nested-name-specifier with
|
|
|
|
// this namespace and no prefix.
|
2011-02-24 10:36:08 +08:00
|
|
|
return NestedNameSpecifier::Create(*this, 0,
|
|
|
|
NNS->getAsNamespace()->getOriginalNamespace());
|
|
|
|
|
|
|
|
case NestedNameSpecifier::NamespaceAlias:
|
|
|
|
// A namespace is canonical; build a nested-name-specifier with
|
|
|
|
// this namespace and no prefix.
|
|
|
|
return NestedNameSpecifier::Create(*this, 0,
|
|
|
|
NNS->getAsNamespaceAlias()->getNamespace()
|
|
|
|
->getOriginalNamespace());
|
2009-03-28 07:10:48 +08:00
|
|
|
|
|
|
|
case NestedNameSpecifier::TypeSpec:
|
|
|
|
case NestedNameSpecifier::TypeSpecWithTemplate: {
|
|
|
|
QualType T = getCanonicalType(QualType(NNS->getAsType(), 0));
|
2010-11-04 08:09:33 +08:00
|
|
|
|
|
|
|
// If we have some kind of dependent-named type (e.g., "typename T::type"),
|
|
|
|
// break it apart into its prefix and identifier, then reconsititute those
|
|
|
|
// as the canonical nested-name-specifier. This is required to canonicalize
|
|
|
|
// a dependent nested-name-specifier involving typedefs of dependent-name
|
|
|
|
// types, e.g.,
|
|
|
|
// typedef typename T::type T1;
|
|
|
|
// typedef typename T1::type T2;
|
2012-03-03 12:09:56 +08:00
|
|
|
if (const DependentNameType *DNT = T->getAs<DependentNameType>())
|
|
|
|
return NestedNameSpecifier::Create(*this, DNT->getQualifier(),
|
2010-11-04 08:09:33 +08:00
|
|
|
const_cast<IdentifierInfo *>(DNT->getIdentifier()));
|
|
|
|
|
2012-03-03 12:09:56 +08:00
|
|
|
// Otherwise, just canonicalize the type, and force it to be a TypeSpec.
|
|
|
|
// FIXME: Why are TypeSpec and TypeSpecWithTemplate distinct in the
|
|
|
|
// first place?
|
2011-01-19 18:06:00 +08:00
|
|
|
return NestedNameSpecifier::Create(*this, 0, false,
|
|
|
|
const_cast<Type*>(T.getTypePtr()));
|
2009-03-28 07:10:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
case NestedNameSpecifier::Global:
|
|
|
|
// The global specifier is canonical and unique.
|
|
|
|
return NNS;
|
|
|
|
}
|
|
|
|
|
2012-01-17 14:56:22 +08:00
|
|
|
llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
|
2009-03-28 07:10:48 +08:00
|
|
|
}
|
|
|
|
|
2008-08-04 15:31:14 +08:00
|
|
|
|
2011-01-12 17:06:06 +08:00
|
|
|
const ArrayType *ASTContext::getAsArrayType(QualType T) const {
|
2008-08-04 15:31:14 +08:00
|
|
|
// Handle the non-qualified case efficiently.
|
First part of changes to eliminate problems with cv-qualifiers and
sugared types. The basic problem is that our qualifier accessors
(getQualifiers, getCVRQualifiers, isConstQualified, etc.) only look at
the current QualType and not at any qualifiers that come from sugared
types, meaning that we won't see these qualifiers through, e.g.,
typedefs:
typedef const int CInt;
typedef CInt Self;
Self.isConstQualified() currently returns false!
Various bugs (e.g., PR5383) have cropped up all over the front end due
to such problems. I'm addressing this problem by splitting each
qualifier accessor into two versions:
- the "local" version only returns qualifiers on this particular
QualType instance
- the "normal" version that will eventually combine qualifiers from this
QualType instance with the qualifiers on the canonical type to
produce the full set of qualifiers.
This commit adds the local versions and switches a few callers from
the "normal" version (e.g., isConstQualified) over to the "local"
version (e.g., isLocalConstQualified) when that is the right thing to
do, e.g., because we're printing or serializing the qualifiers. Also,
switch a bunch of
Context.getCanonicalType(T1).getUnqualifiedType() == Context.getCanonicalType(T2).getQualifiedType()
expressions over to
Context.hasSameUnqualifiedType(T1, T2)
llvm-svn: 88969
2009-11-17 05:35:15 +08:00
|
|
|
if (!T.hasLocalQualifiers()) {
|
2008-08-04 15:31:14 +08:00
|
|
|
// Handle the common positive case fast.
|
|
|
|
if (const ArrayType *AT = dyn_cast<ArrayType>(T))
|
|
|
|
return AT;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-25 03:53:00 +08:00
|
|
|
// Handle the common negative case fast.
|
2011-01-19 18:06:00 +08:00
|
|
|
if (!isa<ArrayType>(T.getCanonicalType()))
|
2008-08-04 15:31:14 +08:00
|
|
|
return 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-25 03:53:00 +08:00
|
|
|
// Apply any qualifiers from the array type to the element type. This
|
2008-08-04 15:31:14 +08:00
|
|
|
// implements C99 6.7.3p8: "If the specification of an array type includes
|
|
|
|
// any type qualifiers, the element type is so qualified, not the array type."
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-08-04 15:31:14 +08:00
|
|
|
// If we get here, we either have type qualifiers on the type, or we have
|
|
|
|
// sugar such as a typedef in the way. If we have type qualifiers on the type
|
2009-08-05 13:36:45 +08:00
|
|
|
// we must propagate them down into the element type.
|
2009-09-25 03:53:00 +08:00
|
|
|
|
2011-01-19 18:06:00 +08:00
|
|
|
SplitQualType split = T.getSplitDesugaredType();
|
2012-02-08 08:46:36 +08:00
|
|
|
Qualifiers qs = split.Quals;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-08-04 15:31:14 +08:00
|
|
|
// If we have a simple case, just return now.
|
2012-02-08 08:46:36 +08:00
|
|
|
const ArrayType *ATy = dyn_cast<ArrayType>(split.Ty);
|
2011-01-19 18:06:00 +08:00
|
|
|
if (ATy == 0 || qs.empty())
|
2008-08-04 15:31:14 +08:00
|
|
|
return ATy;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-08-04 15:31:14 +08:00
|
|
|
// Otherwise, we have an array and we have qualifiers on it. Push the
|
|
|
|
// qualifiers into the array element type and return a new array type.
|
2011-01-19 18:06:00 +08:00
|
|
|
QualType NewEltTy = getQualifiedType(ATy->getElementType(), qs);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-08-04 15:31:14 +08:00
|
|
|
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(ATy))
|
|
|
|
return cast<ArrayType>(getConstantArrayType(NewEltTy, CAT->getSize(),
|
|
|
|
CAT->getSizeModifier(),
|
2009-09-25 03:53:00 +08:00
|
|
|
CAT->getIndexTypeCVRQualifiers()));
|
2008-08-04 15:31:14 +08:00
|
|
|
if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(ATy))
|
|
|
|
return cast<ArrayType>(getIncompleteArrayType(NewEltTy,
|
|
|
|
IAT->getSizeModifier(),
|
2009-09-25 03:53:00 +08:00
|
|
|
IAT->getIndexTypeCVRQualifiers()));
|
2008-12-06 07:32:09 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
if (const DependentSizedArrayType *DSAT
|
2008-12-06 07:32:09 +08:00
|
|
|
= dyn_cast<DependentSizedArrayType>(ATy))
|
|
|
|
return cast<ArrayType>(
|
2009-09-09 23:08:12 +08:00
|
|
|
getDependentSizedArrayType(NewEltTy,
|
2010-10-26 15:05:15 +08:00
|
|
|
DSAT->getSizeExpr(),
|
2008-12-06 07:32:09 +08:00
|
|
|
DSAT->getSizeModifier(),
|
2009-09-25 03:53:00 +08:00
|
|
|
DSAT->getIndexTypeCVRQualifiers(),
|
2009-07-06 23:59:29 +08:00
|
|
|
DSAT->getBracketsRange()));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-08-04 15:31:14 +08:00
|
|
|
const VariableArrayType *VAT = cast<VariableArrayType>(ATy);
|
2009-07-06 23:59:29 +08:00
|
|
|
return cast<ArrayType>(getVariableArrayType(NewEltTy,
|
2010-10-26 15:05:15 +08:00
|
|
|
VAT->getSizeExpr(),
|
2008-08-04 15:31:14 +08:00
|
|
|
VAT->getSizeModifier(),
|
2009-09-25 03:53:00 +08:00
|
|
|
VAT->getIndexTypeCVRQualifiers(),
|
2009-07-06 23:59:29 +08:00
|
|
|
VAT->getBracketsRange()));
|
2008-04-07 06:41:35 +08:00
|
|
|
}
|
|
|
|
|
2012-05-17 20:44:05 +08:00
|
|
|
QualType ASTContext::getAdjustedParameterType(QualType T) const {
|
2011-07-12 12:42:08 +08:00
|
|
|
// C99 6.7.5.3p7:
|
|
|
|
// A declaration of a parameter as "array of type" shall be
|
|
|
|
// adjusted to "qualified pointer to type", where the type
|
|
|
|
// qualifiers (if any) are those specified within the [ and ] of
|
|
|
|
// the array type derivation.
|
|
|
|
if (T->isArrayType())
|
|
|
|
return getArrayDecayedType(T);
|
|
|
|
|
|
|
|
// C99 6.7.5.3p8:
|
|
|
|
// A declaration of a parameter as "function returning type"
|
|
|
|
// shall be adjusted to "pointer to function returning type", as
|
|
|
|
// in 6.3.2.1.
|
|
|
|
if (T->isFunctionType())
|
|
|
|
return getPointerType(T);
|
|
|
|
|
|
|
|
return T;
|
|
|
|
}
|
|
|
|
|
2012-05-17 20:44:05 +08:00
|
|
|
QualType ASTContext::getSignatureParameterType(QualType T) const {
|
2011-07-12 12:42:08 +08:00
|
|
|
T = getVariableArrayDecayedType(T);
|
|
|
|
T = getAdjustedParameterType(T);
|
|
|
|
return T.getUnqualifiedType();
|
|
|
|
}
|
|
|
|
|
2008-04-02 13:18:44 +08:00
|
|
|
/// getArrayDecayedType - Return the properly qualified result of decaying the
|
|
|
|
/// specified array type to a pointer. This operation is non-trivial when
|
|
|
|
/// handling typedefs etc. The canonical type of "T" must be an array type,
|
|
|
|
/// this returns a pointer to a properly qualified element of the array.
|
|
|
|
///
|
|
|
|
/// See C99 6.7.5.3p7 and C99 6.3.2.1p3.
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType ASTContext::getArrayDecayedType(QualType Ty) const {
|
2008-08-04 15:31:14 +08:00
|
|
|
// Get the element type with 'getAsArrayType' so that we don't lose any
|
|
|
|
// typedefs in the element type of the array. This also handles propagation
|
|
|
|
// of type qualifiers from the array type into the element type if present
|
|
|
|
// (C99 6.7.3p8).
|
|
|
|
const ArrayType *PrettyArrayType = getAsArrayType(Ty);
|
|
|
|
assert(PrettyArrayType && "Not an array type!");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-08-04 15:31:14 +08:00
|
|
|
QualType PtrTy = getPointerType(PrettyArrayType->getElementType());
|
2008-04-02 13:18:44 +08:00
|
|
|
|
|
|
|
// int x[restrict 4] -> int *restrict
|
2009-09-25 03:53:00 +08:00
|
|
|
return getQualifiedType(PtrTy, PrettyArrayType->getIndexTypeQualifiers());
|
2008-04-02 13:18:44 +08:00
|
|
|
}
|
|
|
|
|
2011-01-19 18:06:00 +08:00
|
|
|
QualType ASTContext::getBaseElementType(const ArrayType *array) const {
|
|
|
|
return getBaseElementType(array->getElementType());
|
2009-07-24 07:49:00 +08:00
|
|
|
}
|
|
|
|
|
2011-01-19 18:06:00 +08:00
|
|
|
QualType ASTContext::getBaseElementType(QualType type) const {
|
|
|
|
Qualifiers qs;
|
|
|
|
while (true) {
|
|
|
|
SplitQualType split = type.getSplitDesugaredType();
|
2012-02-08 08:46:36 +08:00
|
|
|
const ArrayType *array = split.Ty->getAsArrayTypeUnsafe();
|
2011-01-19 18:06:00 +08:00
|
|
|
if (!array) break;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-01-19 18:06:00 +08:00
|
|
|
type = array->getElementType();
|
2012-02-08 08:46:36 +08:00
|
|
|
qs.addConsistentQualifiers(split.Quals);
|
2011-01-19 18:06:00 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-01-19 18:06:00 +08:00
|
|
|
return getQualifiedType(type, qs);
|
2008-12-21 11:44:36 +08:00
|
|
|
}
|
|
|
|
|
2009-08-22 00:31:06 +08:00
|
|
|
/// getConstantArrayElementCount - Returns number of constant array elements.
|
2009-09-09 23:08:12 +08:00
|
|
|
uint64_t
|
2009-08-22 00:31:06 +08:00
|
|
|
ASTContext::getConstantArrayElementCount(const ConstantArrayType *CA) const {
|
|
|
|
uint64_t ElementCount = 1;
|
|
|
|
do {
|
|
|
|
ElementCount *= CA->getSize().getZExtValue();
|
2012-12-06 11:04:50 +08:00
|
|
|
CA = dyn_cast_or_null<ConstantArrayType>(
|
|
|
|
CA->getElementType()->getAsArrayTypeUnsafe());
|
2009-08-22 00:31:06 +08:00
|
|
|
} while (CA);
|
|
|
|
return ElementCount;
|
|
|
|
}
|
|
|
|
|
2007-04-28 05:51:21 +08:00
|
|
|
/// getFloatingRank - Return a relative rank for floating point types.
|
|
|
|
/// This routine will assert if passed a built-in type that isn't a float.
|
2008-04-07 07:38:49 +08:00
|
|
|
static FloatingRank getFloatingRank(QualType T) {
|
2009-09-22 07:43:11 +08:00
|
|
|
if (const ComplexType *CT = T->getAs<ComplexType>())
|
2007-06-23 04:56:16 +08:00
|
|
|
return getFloatingRank(CT->getElementType());
|
2008-04-07 07:38:49 +08:00
|
|
|
|
2009-09-22 07:43:11 +08:00
|
|
|
assert(T->getAs<BuiltinType>() && "getFloatingRank(): not a floating type");
|
|
|
|
switch (T->getAs<BuiltinType>()->getKind()) {
|
2011-09-23 13:06:16 +08:00
|
|
|
default: llvm_unreachable("getFloatingRank(): not a floating type");
|
2011-10-15 07:23:15 +08:00
|
|
|
case BuiltinType::Half: return HalfRank;
|
2007-06-23 04:56:16 +08:00
|
|
|
case BuiltinType::Float: return FloatRank;
|
|
|
|
case BuiltinType::Double: return DoubleRank;
|
|
|
|
case BuiltinType::LongDouble: return LongDoubleRank;
|
2007-04-28 02:30:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
/// getFloatingTypeOfSizeWithinDomain - Returns a real floating
|
|
|
|
/// point or a complex type (based on typeDomain/typeSize).
|
2007-08-27 09:41:48 +08:00
|
|
|
/// 'typeDomain' is a real floating point or complex type.
|
|
|
|
/// 'typeSize' is a real floating point or complex type.
|
2008-04-07 07:58:54 +08:00
|
|
|
QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size,
|
|
|
|
QualType Domain) const {
|
|
|
|
FloatingRank EltRank = getFloatingRank(Size);
|
|
|
|
if (Domain->isComplexType()) {
|
|
|
|
switch (EltRank) {
|
2012-01-17 10:30:50 +08:00
|
|
|
case HalfRank: llvm_unreachable("Complex half is not supported");
|
2007-08-27 09:27:54 +08:00
|
|
|
case FloatRank: return FloatComplexTy;
|
|
|
|
case DoubleRank: return DoubleComplexTy;
|
|
|
|
case LongDoubleRank: return LongDoubleComplexTy;
|
|
|
|
}
|
|
|
|
}
|
2008-04-07 07:58:54 +08:00
|
|
|
|
|
|
|
assert(Domain->isRealFloatingType() && "Unknown domain!");
|
|
|
|
switch (EltRank) {
|
2013-01-23 19:56:20 +08:00
|
|
|
case HalfRank: return HalfTy;
|
2008-04-07 07:58:54 +08:00
|
|
|
case FloatRank: return FloatTy;
|
|
|
|
case DoubleRank: return DoubleTy;
|
|
|
|
case LongDoubleRank: return LongDoubleTy;
|
2007-04-28 05:51:21 +08:00
|
|
|
}
|
2012-01-17 10:30:50 +08:00
|
|
|
llvm_unreachable("getFloatingRank(): illegal value for rank");
|
2007-04-28 02:30:00 +08:00
|
|
|
}
|
|
|
|
|
2008-04-07 07:55:33 +08:00
|
|
|
/// getFloatingTypeOrder - Compare the rank of the two specified floating
|
|
|
|
/// point types, ignoring the domain of the type (i.e. 'double' ==
|
|
|
|
/// '_Complex double'). If LHS > RHS, return 1. If LHS == RHS, return 0. If
|
2009-09-09 23:08:12 +08:00
|
|
|
/// LHS < RHS, return -1.
|
2011-01-12 17:06:06 +08:00
|
|
|
int ASTContext::getFloatingTypeOrder(QualType LHS, QualType RHS) const {
|
2008-04-07 07:38:49 +08:00
|
|
|
FloatingRank LHSR = getFloatingRank(LHS);
|
|
|
|
FloatingRank RHSR = getFloatingRank(RHS);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-04-07 07:38:49 +08:00
|
|
|
if (LHSR == RHSR)
|
2007-08-27 23:30:22 +08:00
|
|
|
return 0;
|
2008-04-07 07:38:49 +08:00
|
|
|
if (LHSR > RHSR)
|
2007-08-27 23:30:22 +08:00
|
|
|
return 1;
|
|
|
|
return -1;
|
2007-04-28 02:30:00 +08:00
|
|
|
}
|
|
|
|
|
2008-04-07 06:59:24 +08:00
|
|
|
/// getIntegerRank - Return an integer conversion rank (C99 6.3.1.1p1). This
|
|
|
|
/// routine will assert if passed a built-in type that isn't an integer or enum,
|
|
|
|
/// or if it is not canonicalized.
|
2011-01-19 14:33:43 +08:00
|
|
|
unsigned ASTContext::getIntegerRank(const Type *T) const {
|
2009-10-23 04:10:53 +08:00
|
|
|
assert(T->isCanonicalUnqualified() && "T should be canonicalized");
|
2009-07-14 14:30:34 +08:00
|
|
|
|
2008-04-07 06:59:24 +08:00
|
|
|
switch (cast<BuiltinType>(T)->getKind()) {
|
2011-09-23 13:06:16 +08:00
|
|
|
default: llvm_unreachable("getIntegerRank(): not a built-in integer");
|
2008-04-07 07:55:33 +08:00
|
|
|
case BuiltinType::Bool:
|
2009-02-13 10:31:07 +08:00
|
|
|
return 1 + (getIntWidth(BoolTy) << 3);
|
2008-04-07 07:55:33 +08:00
|
|
|
case BuiltinType::Char_S:
|
|
|
|
case BuiltinType::Char_U:
|
|
|
|
case BuiltinType::SChar:
|
|
|
|
case BuiltinType::UChar:
|
2009-02-13 10:31:07 +08:00
|
|
|
return 2 + (getIntWidth(CharTy) << 3);
|
2008-04-07 07:55:33 +08:00
|
|
|
case BuiltinType::Short:
|
|
|
|
case BuiltinType::UShort:
|
2009-02-13 10:31:07 +08:00
|
|
|
return 3 + (getIntWidth(ShortTy) << 3);
|
2008-04-07 07:55:33 +08:00
|
|
|
case BuiltinType::Int:
|
|
|
|
case BuiltinType::UInt:
|
2009-02-13 10:31:07 +08:00
|
|
|
return 4 + (getIntWidth(IntTy) << 3);
|
2008-04-07 07:55:33 +08:00
|
|
|
case BuiltinType::Long:
|
|
|
|
case BuiltinType::ULong:
|
2009-02-13 10:31:07 +08:00
|
|
|
return 5 + (getIntWidth(LongTy) << 3);
|
2008-04-07 07:55:33 +08:00
|
|
|
case BuiltinType::LongLong:
|
|
|
|
case BuiltinType::ULongLong:
|
2009-02-13 10:31:07 +08:00
|
|
|
return 6 + (getIntWidth(LongLongTy) << 3);
|
2009-04-30 10:43:43 +08:00
|
|
|
case BuiltinType::Int128:
|
|
|
|
case BuiltinType::UInt128:
|
|
|
|
return 7 + (getIntWidth(Int128Ty) << 3);
|
2008-04-07 06:59:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-20 12:21:42 +08:00
|
|
|
/// \brief Whether this is a promotable bitfield reference according
|
|
|
|
/// to C99 6.3.1.1p2, bullet 2 (and GCC extensions).
|
|
|
|
///
|
|
|
|
/// \returns the type this bit-field will promote to, or NULL if no
|
|
|
|
/// promotion occurs.
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType ASTContext::isPromotableBitField(Expr *E) const {
|
2010-05-25 04:13:53 +08:00
|
|
|
if (E->isTypeDependent() || E->isValueDependent())
|
|
|
|
return QualType();
|
|
|
|
|
2009-08-20 12:21:42 +08:00
|
|
|
FieldDecl *Field = E->getBitField();
|
|
|
|
if (!Field)
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
QualType FT = Field->getType();
|
|
|
|
|
2011-10-11 02:28:20 +08:00
|
|
|
uint64_t BitWidth = Field->getBitWidthValue(*this);
|
2009-08-20 12:21:42 +08:00
|
|
|
uint64_t IntSize = getTypeSize(IntTy);
|
|
|
|
// GCC extension compatibility: if the bit-field size is less than or equal
|
|
|
|
// to the size of int, it gets promoted no matter what its type is.
|
|
|
|
// For instance, unsigned long bf : 4 gets promoted to signed int.
|
|
|
|
if (BitWidth < IntSize)
|
|
|
|
return IntTy;
|
|
|
|
|
|
|
|
if (BitWidth == IntSize)
|
|
|
|
return FT->isSignedIntegerType() ? IntTy : UnsignedIntTy;
|
|
|
|
|
|
|
|
// Types bigger than int are not subject to promotions, and therefore act
|
|
|
|
// like the base type.
|
|
|
|
// FIXME: This doesn't quite match what gcc does, but what gcc does here
|
|
|
|
// is ridiculous.
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2009-08-19 15:44:53 +08:00
|
|
|
/// getPromotedIntegerType - Returns the type that Promotable will
|
|
|
|
/// promote to: C99 6.3.1.1p2, assuming that Promotable is a promotable
|
|
|
|
/// integer type.
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType ASTContext::getPromotedIntegerType(QualType Promotable) const {
|
2009-08-19 15:44:53 +08:00
|
|
|
assert(!Promotable.isNull());
|
|
|
|
assert(Promotable->isPromotableIntegerType());
|
2009-12-09 17:09:27 +08:00
|
|
|
if (const EnumType *ET = Promotable->getAs<EnumType>())
|
|
|
|
return ET->getDecl()->getPromotionType();
|
2011-10-26 15:22:48 +08:00
|
|
|
|
|
|
|
if (const BuiltinType *BT = Promotable->getAs<BuiltinType>()) {
|
|
|
|
// C++ [conv.prom]: A prvalue of type char16_t, char32_t, or wchar_t
|
|
|
|
// (3.9.1) can be converted to a prvalue of the first of the following
|
|
|
|
// types that can represent all the values of its underlying type:
|
|
|
|
// int, unsigned int, long int, unsigned long int, long long int, or
|
|
|
|
// unsigned long long int [...]
|
|
|
|
// FIXME: Is there some better way to compute this?
|
|
|
|
if (BT->getKind() == BuiltinType::WChar_S ||
|
|
|
|
BT->getKind() == BuiltinType::WChar_U ||
|
|
|
|
BT->getKind() == BuiltinType::Char16 ||
|
|
|
|
BT->getKind() == BuiltinType::Char32) {
|
|
|
|
bool FromIsSigned = BT->getKind() == BuiltinType::WChar_S;
|
|
|
|
uint64_t FromSize = getTypeSize(BT);
|
|
|
|
QualType PromoteTypes[] = { IntTy, UnsignedIntTy, LongTy, UnsignedLongTy,
|
|
|
|
LongLongTy, UnsignedLongLongTy };
|
|
|
|
for (size_t Idx = 0; Idx < llvm::array_lengthof(PromoteTypes); ++Idx) {
|
|
|
|
uint64_t ToSize = getTypeSize(PromoteTypes[Idx]);
|
|
|
|
if (FromSize < ToSize ||
|
|
|
|
(FromSize == ToSize &&
|
|
|
|
FromIsSigned == PromoteTypes[Idx]->isSignedIntegerType()))
|
|
|
|
return PromoteTypes[Idx];
|
|
|
|
}
|
|
|
|
llvm_unreachable("char type should fit into long long");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// At this point, we should have a signed or unsigned integer type.
|
2009-08-19 15:44:53 +08:00
|
|
|
if (Promotable->isSignedIntegerType())
|
|
|
|
return IntTy;
|
2012-11-15 09:21:59 +08:00
|
|
|
uint64_t PromotableSize = getIntWidth(Promotable);
|
|
|
|
uint64_t IntSize = getIntWidth(IntTy);
|
2009-08-19 15:44:53 +08:00
|
|
|
assert(Promotable->isUnsignedIntegerType() && PromotableSize <= IntSize);
|
|
|
|
return (PromotableSize != IntSize) ? IntTy : UnsignedIntTy;
|
|
|
|
}
|
|
|
|
|
2011-07-02 06:22:50 +08:00
|
|
|
/// \brief Recurses in pointer/array types until it finds an objc retainable
|
|
|
|
/// type and returns its ownership.
|
|
|
|
Qualifiers::ObjCLifetime ASTContext::getInnerObjCOwnership(QualType T) const {
|
|
|
|
while (!T.isNull()) {
|
|
|
|
if (T.getObjCLifetime() != Qualifiers::OCL_None)
|
|
|
|
return T.getObjCLifetime();
|
|
|
|
if (T->isArrayType())
|
|
|
|
T = getBaseElementType(T);
|
|
|
|
else if (const PointerType *PT = T->getAs<PointerType>())
|
|
|
|
T = PT->getPointeeType();
|
|
|
|
else if (const ReferenceType *RT = T->getAs<ReferenceType>())
|
2011-07-02 07:01:46 +08:00
|
|
|
T = RT->getPointeeType();
|
2011-07-02 06:22:50 +08:00
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Qualifiers::OCL_None;
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
/// getIntegerTypeOrder - Returns the highest ranked integer type:
|
2008-04-07 07:55:33 +08:00
|
|
|
/// C99 6.3.1.8p1. If LHS > RHS, return 1. If LHS == RHS, return 0. If
|
2009-09-09 23:08:12 +08:00
|
|
|
/// LHS < RHS, return -1.
|
2011-01-12 17:06:06 +08:00
|
|
|
int ASTContext::getIntegerTypeOrder(QualType LHS, QualType RHS) const {
|
2011-01-19 14:33:43 +08:00
|
|
|
const Type *LHSC = getCanonicalType(LHS).getTypePtr();
|
|
|
|
const Type *RHSC = getCanonicalType(RHS).getTypePtr();
|
2008-04-07 07:55:33 +08:00
|
|
|
if (LHSC == RHSC) return 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-04-07 06:59:24 +08:00
|
|
|
bool LHSUnsigned = LHSC->isUnsignedIntegerType();
|
|
|
|
bool RHSUnsigned = RHSC->isUnsignedIntegerType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-04-07 07:55:33 +08:00
|
|
|
unsigned LHSRank = getIntegerRank(LHSC);
|
|
|
|
unsigned RHSRank = getIntegerRank(RHSC);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-04-07 07:55:33 +08:00
|
|
|
if (LHSUnsigned == RHSUnsigned) { // Both signed or both unsigned.
|
|
|
|
if (LHSRank == RHSRank) return 0;
|
|
|
|
return LHSRank > RHSRank ? 1 : -1;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-04-07 07:55:33 +08:00
|
|
|
// Otherwise, the LHS is signed and the RHS is unsigned or visa versa.
|
|
|
|
if (LHSUnsigned) {
|
|
|
|
// If the unsigned [LHS] type is larger, return it.
|
|
|
|
if (LHSRank >= RHSRank)
|
|
|
|
return 1;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-04-07 07:55:33 +08:00
|
|
|
// If the signed type can represent all values of the unsigned type, it
|
|
|
|
// wins. Because we are dealing with 2's complement and types that are
|
2009-09-09 23:08:12 +08:00
|
|
|
// powers of two larger than each other, this is always safe.
|
2008-04-07 07:55:33 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the unsigned [RHS] type is larger, return it.
|
|
|
|
if (RHSRank >= LHSRank)
|
|
|
|
return -1;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-04-07 07:55:33 +08:00
|
|
|
// If the signed type can represent all values of the unsigned type, it
|
|
|
|
// wins. Because we are dealing with 2's complement and types that are
|
2009-09-09 23:08:12 +08:00
|
|
|
// powers of two larger than each other, this is always safe.
|
2008-04-07 07:55:33 +08:00
|
|
|
return 1;
|
2007-04-28 02:30:00 +08:00
|
|
|
}
|
2007-08-17 13:31:46 +08:00
|
|
|
|
2009-11-15 05:45:58 +08:00
|
|
|
static RecordDecl *
|
2011-03-09 22:09:51 +08:00
|
|
|
CreateRecordDecl(const ASTContext &Ctx, RecordDecl::TagKind TK,
|
|
|
|
DeclContext *DC, IdentifierInfo *Id) {
|
|
|
|
SourceLocation Loc;
|
2012-03-11 15:00:24 +08:00
|
|
|
if (Ctx.getLangOpts().CPlusPlus)
|
2011-03-09 22:09:51 +08:00
|
|
|
return CXXRecordDecl::Create(Ctx, TK, DC, Loc, Loc, Id);
|
2009-11-15 05:45:58 +08:00
|
|
|
else
|
2011-03-09 22:09:51 +08:00
|
|
|
return RecordDecl::Create(Ctx, TK, DC, Loc, Loc, Id);
|
2009-11-15 05:45:58 +08:00
|
|
|
}
|
2011-03-09 22:09:51 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
// getCFConstantStringType - Return the type used for constant CFStrings.
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType ASTContext::getCFConstantStringType() const {
|
2007-08-17 13:31:46 +08:00
|
|
|
if (!CFConstantStringTypeDecl) {
|
2009-09-09 23:08:12 +08:00
|
|
|
CFConstantStringTypeDecl =
|
2011-03-09 22:09:51 +08:00
|
|
|
CreateRecordDecl(*this, TTK_Struct, TUDecl,
|
2009-11-15 05:45:58 +08:00
|
|
|
&Idents.get("NSConstantString"));
|
2010-02-05 09:33:36 +08:00
|
|
|
CFConstantStringTypeDecl->startDefinition();
|
2009-11-15 05:45:58 +08:00
|
|
|
|
2007-11-19 08:25:30 +08:00
|
|
|
QualType FieldTypes[4];
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-17 13:31:46 +08:00
|
|
|
// const int *isa;
|
2009-09-25 03:53:00 +08:00
|
|
|
FieldTypes[0] = getPointerType(IntTy.withConst());
|
2007-11-19 08:25:30 +08:00
|
|
|
// int flags;
|
|
|
|
FieldTypes[1] = IntTy;
|
2007-08-17 13:31:46 +08:00
|
|
|
// const char *str;
|
2009-09-25 03:53:00 +08:00
|
|
|
FieldTypes[2] = getPointerType(CharTy.withConst());
|
2007-08-17 13:31:46 +08:00
|
|
|
// long length;
|
2009-09-09 23:08:12 +08:00
|
|
|
FieldTypes[3] = LongTy;
|
|
|
|
|
2008-12-12 00:49:14 +08:00
|
|
|
// Create fields
|
|
|
|
for (unsigned i = 0; i < 4; ++i) {
|
2009-09-09 23:08:12 +08:00
|
|
|
FieldDecl *Field = FieldDecl::Create(*this, CFConstantStringTypeDecl,
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation(),
|
2008-12-12 00:49:14 +08:00
|
|
|
SourceLocation(), 0,
|
2009-12-07 10:54:59 +08:00
|
|
|
FieldTypes[i], /*TInfo=*/0,
|
2009-09-09 23:08:12 +08:00
|
|
|
/*BitWidth=*/0,
|
2011-06-12 01:19:42 +08:00
|
|
|
/*Mutable=*/false,
|
2012-06-10 11:12:00 +08:00
|
|
|
ICIS_NoInit);
|
2010-05-01 05:35:41 +08:00
|
|
|
Field->setAccess(AS_public);
|
2009-06-30 10:36:12 +08:00
|
|
|
CFConstantStringTypeDecl->addDecl(Field);
|
2008-12-12 00:49:14 +08:00
|
|
|
}
|
|
|
|
|
2010-02-11 09:19:42 +08:00
|
|
|
CFConstantStringTypeDecl->completeDefinition();
|
2007-08-17 13:31:46 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-17 13:31:46 +08:00
|
|
|
return getTagDeclType(CFConstantStringTypeDecl);
|
2007-09-11 23:32:40 +08:00
|
|
|
}
|
2007-10-11 09:00:40 +08:00
|
|
|
|
2013-01-05 02:45:40 +08:00
|
|
|
QualType ASTContext::getObjCSuperType() const {
|
|
|
|
if (ObjCSuperType.isNull()) {
|
|
|
|
RecordDecl *ObjCSuperTypeDecl =
|
|
|
|
CreateRecordDecl(*this, TTK_Struct, TUDecl, &Idents.get("objc_super"));
|
|
|
|
TUDecl->addDecl(ObjCSuperTypeDecl);
|
|
|
|
ObjCSuperType = getTagDeclType(ObjCSuperTypeDecl);
|
|
|
|
}
|
|
|
|
return ObjCSuperType;
|
|
|
|
}
|
|
|
|
|
2009-04-24 06:29:11 +08:00
|
|
|
void ASTContext::setCFConstantStringType(QualType T) {
|
2009-07-30 05:53:49 +08:00
|
|
|
const RecordType *Rec = T->getAs<RecordType>();
|
2009-04-24 06:29:11 +08:00
|
|
|
assert(Rec && "Invalid CFConstantStringType");
|
|
|
|
CFConstantStringTypeDecl = Rec->getDecl();
|
|
|
|
}
|
|
|
|
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType ASTContext::getBlockDescriptorType() const {
|
2009-10-20 10:12:22 +08:00
|
|
|
if (BlockDescriptorType)
|
|
|
|
return getTagDeclType(BlockDescriptorType);
|
|
|
|
|
|
|
|
RecordDecl *T;
|
|
|
|
// FIXME: Needs the FlagAppleBlock bit.
|
2011-03-09 22:09:51 +08:00
|
|
|
T = CreateRecordDecl(*this, TTK_Struct, TUDecl,
|
2009-11-15 05:45:58 +08:00
|
|
|
&Idents.get("__block_descriptor"));
|
2010-02-05 09:33:36 +08:00
|
|
|
T->startDefinition();
|
2009-10-20 10:12:22 +08:00
|
|
|
|
|
|
|
QualType FieldTypes[] = {
|
|
|
|
UnsignedLongTy,
|
|
|
|
UnsignedLongTy,
|
|
|
|
};
|
|
|
|
|
|
|
|
const char *FieldNames[] = {
|
|
|
|
"reserved",
|
2009-10-22 08:49:09 +08:00
|
|
|
"Size"
|
2009-10-20 10:12:22 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
for (size_t i = 0; i < 2; ++i) {
|
2011-03-08 16:55:46 +08:00
|
|
|
FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
|
2009-10-20 10:12:22 +08:00
|
|
|
SourceLocation(),
|
|
|
|
&Idents.get(FieldNames[i]),
|
2009-12-07 10:54:59 +08:00
|
|
|
FieldTypes[i], /*TInfo=*/0,
|
2009-10-20 10:12:22 +08:00
|
|
|
/*BitWidth=*/0,
|
2011-06-12 01:19:42 +08:00
|
|
|
/*Mutable=*/false,
|
2012-06-10 11:12:00 +08:00
|
|
|
ICIS_NoInit);
|
2010-05-01 05:35:41 +08:00
|
|
|
Field->setAccess(AS_public);
|
2009-10-20 10:12:22 +08:00
|
|
|
T->addDecl(Field);
|
|
|
|
}
|
|
|
|
|
2010-02-11 09:19:42 +08:00
|
|
|
T->completeDefinition();
|
2009-10-20 10:12:22 +08:00
|
|
|
|
|
|
|
BlockDescriptorType = T;
|
|
|
|
|
|
|
|
return getTagDeclType(BlockDescriptorType);
|
|
|
|
}
|
|
|
|
|
2011-01-12 17:06:06 +08:00
|
|
|
QualType ASTContext::getBlockDescriptorExtendedType() const {
|
2009-10-22 08:49:09 +08:00
|
|
|
if (BlockDescriptorExtendedType)
|
|
|
|
return getTagDeclType(BlockDescriptorExtendedType);
|
|
|
|
|
|
|
|
RecordDecl *T;
|
|
|
|
// FIXME: Needs the FlagAppleBlock bit.
|
2011-03-09 22:09:51 +08:00
|
|
|
T = CreateRecordDecl(*this, TTK_Struct, TUDecl,
|
2009-11-15 05:45:58 +08:00
|
|
|
&Idents.get("__block_descriptor_withcopydispose"));
|
2010-02-05 09:33:36 +08:00
|
|
|
T->startDefinition();
|
2009-10-22 08:49:09 +08:00
|
|
|
|
|
|
|
QualType FieldTypes[] = {
|
|
|
|
UnsignedLongTy,
|
|
|
|
UnsignedLongTy,
|
|
|
|
getPointerType(VoidPtrTy),
|
|
|
|
getPointerType(VoidPtrTy)
|
|
|
|
};
|
|
|
|
|
|
|
|
const char *FieldNames[] = {
|
|
|
|
"reserved",
|
|
|
|
"Size",
|
|
|
|
"CopyFuncPtr",
|
|
|
|
"DestroyFuncPtr"
|
|
|
|
};
|
|
|
|
|
|
|
|
for (size_t i = 0; i < 4; ++i) {
|
2011-03-08 16:55:46 +08:00
|
|
|
FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(),
|
2009-10-22 08:49:09 +08:00
|
|
|
SourceLocation(),
|
|
|
|
&Idents.get(FieldNames[i]),
|
2009-12-07 10:54:59 +08:00
|
|
|
FieldTypes[i], /*TInfo=*/0,
|
2009-10-22 08:49:09 +08:00
|
|
|
/*BitWidth=*/0,
|
2011-06-12 01:19:42 +08:00
|
|
|
/*Mutable=*/false,
|
2012-06-10 11:12:00 +08:00
|
|
|
ICIS_NoInit);
|
2010-05-01 05:35:41 +08:00
|
|
|
Field->setAccess(AS_public);
|
2009-10-22 08:49:09 +08:00
|
|
|
T->addDecl(Field);
|
|
|
|
}
|
|
|
|
|
2010-02-11 09:19:42 +08:00
|
|
|
T->completeDefinition();
|
2009-10-22 08:49:09 +08:00
|
|
|
|
|
|
|
BlockDescriptorExtendedType = T;
|
|
|
|
|
|
|
|
return getTagDeclType(BlockDescriptorExtendedType);
|
|
|
|
}
|
|
|
|
|
2012-11-29 07:12:17 +08:00
|
|
|
/// BlockRequiresCopying - Returns true if byref variable "D" of type "Ty"
|
|
|
|
/// requires copy/dispose. Note that this must match the logic
|
|
|
|
/// in buildByrefHelpers.
|
|
|
|
bool ASTContext::BlockRequiresCopying(QualType Ty,
|
|
|
|
const VarDecl *D) {
|
|
|
|
if (const CXXRecordDecl *record = Ty->getAsCXXRecordDecl()) {
|
|
|
|
const Expr *copyExpr = getBlockVarCopyInits(D);
|
|
|
|
if (!copyExpr && record->hasTrivialDestructor()) return false;
|
|
|
|
|
2009-10-22 02:16:27 +08:00
|
|
|
return true;
|
2012-11-29 07:12:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!Ty->isObjCRetainableType()) return false;
|
|
|
|
|
|
|
|
Qualifiers qs = Ty.getQualifiers();
|
|
|
|
|
|
|
|
// If we have lifetime, that dominates.
|
|
|
|
if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) {
|
|
|
|
assert(getLangOpts().ObjCAutoRefCount);
|
|
|
|
|
|
|
|
switch (lifetime) {
|
|
|
|
case Qualifiers::OCL_None: llvm_unreachable("impossible");
|
|
|
|
|
|
|
|
// These are just bits as far as the runtime is concerned.
|
|
|
|
case Qualifiers::OCL_ExplicitNone:
|
|
|
|
case Qualifiers::OCL_Autoreleasing:
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Tell the runtime that this is ARC __weak, called by the
|
|
|
|
// byref routines.
|
|
|
|
case Qualifiers::OCL_Weak:
|
|
|
|
// ARC __strong __block variables need to be retained.
|
|
|
|
case Qualifiers::OCL_Strong:
|
|
|
|
return true;
|
2010-11-17 08:21:28 +08:00
|
|
|
}
|
2012-11-29 07:12:17 +08:00
|
|
|
llvm_unreachable("fell out of lifetime switch!");
|
2010-11-17 08:21:28 +08:00
|
|
|
}
|
2012-11-29 07:12:17 +08:00
|
|
|
return (Ty->isBlockPointerType() || isObjCNSObjectType(Ty) ||
|
|
|
|
Ty->isObjCObjectPointerType());
|
2009-10-22 02:16:27 +08:00
|
|
|
}
|
|
|
|
|
2012-11-15 01:15:51 +08:00
|
|
|
bool ASTContext::getByrefLifetime(QualType Ty,
|
|
|
|
Qualifiers::ObjCLifetime &LifeTime,
|
|
|
|
bool &HasByrefExtendedLayout) const {
|
|
|
|
|
|
|
|
if (!getLangOpts().ObjC1 ||
|
|
|
|
getLangOpts().getGC() != LangOptions::NonGC)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
HasByrefExtendedLayout = false;
|
2012-12-12 03:58:01 +08:00
|
|
|
if (Ty->isRecordType()) {
|
2012-11-15 01:15:51 +08:00
|
|
|
HasByrefExtendedLayout = true;
|
|
|
|
LifeTime = Qualifiers::OCL_None;
|
|
|
|
}
|
|
|
|
else if (getLangOpts().ObjCAutoRefCount)
|
|
|
|
LifeTime = Ty.getObjCLifetime();
|
|
|
|
// MRR.
|
|
|
|
else if (Ty->isObjCObjectPointerType() || Ty->isBlockPointerType())
|
|
|
|
LifeTime = Qualifiers::OCL_ExplicitNone;
|
|
|
|
else
|
|
|
|
LifeTime = Qualifiers::OCL_None;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-09-08 09:46:34 +08:00
|
|
|
TypedefDecl *ASTContext::getObjCInstanceTypeDecl() {
|
|
|
|
if (!ObjCInstanceTypeDecl)
|
|
|
|
ObjCInstanceTypeDecl = TypedefDecl::Create(*this,
|
|
|
|
getTranslationUnitDecl(),
|
|
|
|
SourceLocation(),
|
|
|
|
SourceLocation(),
|
|
|
|
&Idents.get("instancetype"),
|
|
|
|
getTrivialTypeSourceInfo(getObjCIdType()));
|
|
|
|
return ObjCInstanceTypeDecl;
|
|
|
|
}
|
|
|
|
|
2007-10-29 14:33:42 +08:00
|
|
|
// This returns true if a type has been typedefed to BOOL:
|
|
|
|
// typedef <type> BOOL;
|
2007-10-31 04:27:44 +08:00
|
|
|
static bool isTypeTypedefedAsBOOL(QualType T) {
|
2007-10-29 14:33:42 +08:00
|
|
|
if (const TypedefType *TT = dyn_cast<TypedefType>(T))
|
2008-11-24 11:52:59 +08:00
|
|
|
if (IdentifierInfo *II = TT->getDecl()->getIdentifier())
|
|
|
|
return II->isStr("BOOL");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-10-29 13:01:08 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-01-08 03:49:32 +08:00
|
|
|
/// getObjCEncodingTypeSize returns size of type for objective-c encoding
|
2007-10-30 06:57:28 +08:00
|
|
|
/// purpose.
|
2011-01-12 17:06:06 +08:00
|
|
|
CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) const {
|
2011-05-27 09:19:52 +08:00
|
|
|
if (!type->isIncompleteArrayType() && type->isIncompleteType())
|
|
|
|
return CharUnits::Zero();
|
|
|
|
|
2010-01-12 01:06:35 +08:00
|
|
|
CharUnits sz = getTypeSizeInChars(type);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-10-30 06:57:28 +08:00
|
|
|
// Make all integer and enum types at least as large as an int
|
2010-06-16 08:17:44 +08:00
|
|
|
if (sz.isPositive() && type->isIntegralOrEnumerationType())
|
2010-01-12 01:06:35 +08:00
|
|
|
sz = std::max(sz, getTypeSizeInChars(IntTy));
|
2007-10-30 06:57:28 +08:00
|
|
|
// Treat arrays as pointers, since that's how they're passed in.
|
|
|
|
else if (type->isArrayType())
|
2010-01-12 01:06:35 +08:00
|
|
|
sz = getTypeSizeInChars(VoidPtrTy);
|
2010-01-12 03:19:56 +08:00
|
|
|
return sz;
|
2010-01-12 01:06:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline
|
|
|
|
std::string charUnitsToString(const CharUnits &CU) {
|
|
|
|
return llvm::itostr(CU.getQuantity());
|
2007-10-30 06:57:28 +08:00
|
|
|
}
|
|
|
|
|
2011-02-07 18:33:21 +08:00
|
|
|
/// getObjCEncodingForBlock - Return the encoded type for this block
|
2009-11-18 03:33:30 +08:00
|
|
|
/// declaration.
|
2011-02-07 18:33:21 +08:00
|
|
|
std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const {
|
|
|
|
std::string S;
|
|
|
|
|
2009-11-18 03:33:30 +08:00
|
|
|
const BlockDecl *Decl = Expr->getBlockDecl();
|
|
|
|
QualType BlockTy =
|
|
|
|
Expr->getType()->getAs<BlockPointerType>()->getPointeeType();
|
|
|
|
// Encode result type.
|
2012-11-16 03:02:45 +08:00
|
|
|
if (getLangOpts().EncodeExtendedBlockSig)
|
2012-11-15 07:11:38 +08:00
|
|
|
getObjCEncodingForMethodParameter(Decl::OBJC_TQ_None,
|
|
|
|
BlockTy->getAs<FunctionType>()->getResultType(),
|
|
|
|
S, true /*Extended*/);
|
|
|
|
else
|
|
|
|
getObjCEncodingForType(BlockTy->getAs<FunctionType>()->getResultType(),
|
|
|
|
S);
|
2009-11-18 03:33:30 +08:00
|
|
|
// Compute size of all parameters.
|
|
|
|
// 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;
|
2010-01-12 01:06:35 +08:00
|
|
|
CharUnits PtrSize = getTypeSizeInChars(VoidPtrTy);
|
|
|
|
CharUnits ParmOffset = PtrSize;
|
2010-04-09 02:06:22 +08:00
|
|
|
for (BlockDecl::param_const_iterator PI = Decl->param_begin(),
|
2009-11-18 03:33:30 +08:00
|
|
|
E = Decl->param_end(); PI != E; ++PI) {
|
|
|
|
QualType PType = (*PI)->getType();
|
2010-01-12 03:19:56 +08:00
|
|
|
CharUnits sz = getObjCEncodingTypeSize(PType);
|
2012-06-30 08:48:59 +08:00
|
|
|
if (sz.isZero())
|
|
|
|
continue;
|
2010-01-12 01:06:35 +08:00
|
|
|
assert (sz.isPositive() && "BlockExpr - Incomplete param type");
|
2009-11-18 03:33:30 +08:00
|
|
|
ParmOffset += sz;
|
|
|
|
}
|
|
|
|
// Size of the argument frame
|
2010-01-12 01:06:35 +08:00
|
|
|
S += charUnitsToString(ParmOffset);
|
2009-11-18 03:33:30 +08:00
|
|
|
// Block pointer and offset.
|
|
|
|
S += "@?0";
|
|
|
|
|
|
|
|
// Argument types.
|
|
|
|
ParmOffset = PtrSize;
|
|
|
|
for (BlockDecl::param_const_iterator PI = Decl->param_begin(), E =
|
|
|
|
Decl->param_end(); PI != E; ++PI) {
|
|
|
|
ParmVarDecl *PVDecl = *PI;
|
|
|
|
QualType PType = PVDecl->getOriginalType();
|
|
|
|
if (const ArrayType *AT =
|
|
|
|
dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) {
|
|
|
|
// Use array's original type only if it has known number of
|
2010-12-30 22:05:53 +08:00
|
|
|
// elements.
|
|
|
|
if (!isa<ConstantArrayType>(AT))
|
|
|
|
PType = PVDecl->getType();
|
|
|
|
} else if (PType->isFunctionType())
|
|
|
|
PType = PVDecl->getType();
|
2012-11-16 03:02:45 +08:00
|
|
|
if (getLangOpts().EncodeExtendedBlockSig)
|
2012-11-15 07:11:38 +08:00
|
|
|
getObjCEncodingForMethodParameter(Decl::OBJC_TQ_None, PType,
|
|
|
|
S, true /*Extended*/);
|
|
|
|
else
|
|
|
|
getObjCEncodingForType(PType, S);
|
2010-12-30 22:05:53 +08:00
|
|
|
S += charUnitsToString(ParmOffset);
|
|
|
|
ParmOffset += getObjCEncodingTypeSize(PType);
|
|
|
|
}
|
2011-02-07 18:33:21 +08:00
|
|
|
|
|
|
|
return S;
|
2010-12-30 22:05:53 +08:00
|
|
|
}
|
|
|
|
|
2011-05-27 09:19:52 +08:00
|
|
|
bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl,
|
2010-12-30 22:05:53 +08:00
|
|
|
std::string& S) {
|
|
|
|
// Encode result type.
|
|
|
|
getObjCEncodingForType(Decl->getResultType(), S);
|
|
|
|
CharUnits ParmOffset;
|
|
|
|
// Compute size of all parameters.
|
|
|
|
for (FunctionDecl::param_const_iterator PI = Decl->param_begin(),
|
|
|
|
E = Decl->param_end(); PI != E; ++PI) {
|
|
|
|
QualType PType = (*PI)->getType();
|
|
|
|
CharUnits sz = getObjCEncodingTypeSize(PType);
|
2011-05-27 09:19:52 +08:00
|
|
|
if (sz.isZero())
|
2012-06-30 06:54:56 +08:00
|
|
|
continue;
|
|
|
|
|
2010-12-30 22:05:53 +08:00
|
|
|
assert (sz.isPositive() &&
|
2011-05-27 09:19:52 +08:00
|
|
|
"getObjCEncodingForFunctionDecl - Incomplete param type");
|
2010-12-30 22:05:53 +08:00
|
|
|
ParmOffset += sz;
|
|
|
|
}
|
|
|
|
S += charUnitsToString(ParmOffset);
|
|
|
|
ParmOffset = CharUnits::Zero();
|
|
|
|
|
|
|
|
// Argument types.
|
|
|
|
for (FunctionDecl::param_const_iterator PI = Decl->param_begin(),
|
|
|
|
E = Decl->param_end(); PI != E; ++PI) {
|
|
|
|
ParmVarDecl *PVDecl = *PI;
|
|
|
|
QualType PType = PVDecl->getOriginalType();
|
|
|
|
if (const ArrayType *AT =
|
|
|
|
dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) {
|
|
|
|
// Use array's original type only if it has known number of
|
2009-11-18 03:33:30 +08:00
|
|
|
// elements.
|
|
|
|
if (!isa<ConstantArrayType>(AT))
|
|
|
|
PType = PVDecl->getType();
|
|
|
|
} else if (PType->isFunctionType())
|
|
|
|
PType = PVDecl->getType();
|
|
|
|
getObjCEncodingForType(PType, S);
|
2010-01-12 01:06:35 +08:00
|
|
|
S += charUnitsToString(ParmOffset);
|
2010-01-12 03:19:56 +08:00
|
|
|
ParmOffset += getObjCEncodingTypeSize(PType);
|
2009-11-18 03:33:30 +08:00
|
|
|
}
|
2011-05-27 09:19:52 +08:00
|
|
|
|
|
|
|
return false;
|
2009-11-18 03:33:30 +08:00
|
|
|
}
|
|
|
|
|
2011-11-30 09:57:58 +08:00
|
|
|
/// getObjCEncodingForMethodParameter - Return the encoded type for a single
|
|
|
|
/// method parameter or return type. If Extended, include class names and
|
|
|
|
/// block object types.
|
|
|
|
void ASTContext::getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT,
|
|
|
|
QualType T, std::string& S,
|
|
|
|
bool Extended) const {
|
|
|
|
// Encode type qualifer, 'in', 'inout', etc. for the parameter.
|
|
|
|
getObjCEncodingForTypeQualifier(QT, S);
|
|
|
|
// Encode parameter type.
|
|
|
|
getObjCEncodingForTypeImpl(T, S, true, true, 0,
|
|
|
|
true /*OutermostType*/,
|
|
|
|
false /*EncodingProperty*/,
|
|
|
|
false /*StructField*/,
|
|
|
|
Extended /*EncodeBlockParameters*/,
|
|
|
|
Extended /*EncodeClassNames*/);
|
|
|
|
}
|
|
|
|
|
2008-01-08 03:49:32 +08:00
|
|
|
/// getObjCEncodingForMethodDecl - Return the encoded type for this method
|
2007-10-30 06:57:28 +08:00
|
|
|
/// declaration.
|
2011-05-27 09:19:52 +08:00
|
|
|
bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
|
2011-11-30 09:57:58 +08:00
|
|
|
std::string& S,
|
|
|
|
bool Extended) const {
|
2008-08-28 12:38:10 +08:00
|
|
|
// FIXME: This is not very efficient.
|
2011-11-30 09:57:58 +08:00
|
|
|
// Encode return type.
|
|
|
|
getObjCEncodingForMethodParameter(Decl->getObjCDeclQualifier(),
|
|
|
|
Decl->getResultType(), S, Extended);
|
2007-10-30 06:57:28 +08:00
|
|
|
// Compute size of all parameters.
|
|
|
|
// 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;
|
2010-01-12 01:06:35 +08:00
|
|
|
CharUnits PtrSize = getTypeSizeInChars(VoidPtrTy);
|
2007-10-30 06:57:28 +08:00
|
|
|
// The first two arguments (self and _cmd) are pointers; account for
|
|
|
|
// their size.
|
2010-01-12 01:06:35 +08:00
|
|
|
CharUnits ParmOffset = 2 * PtrSize;
|
2011-10-03 14:37:04 +08:00
|
|
|
for (ObjCMethodDecl::param_const_iterator PI = Decl->param_begin(),
|
2010-04-09 05:29:11 +08:00
|
|
|
E = Decl->sel_param_end(); PI != E; ++PI) {
|
2009-02-21 02:43:26 +08:00
|
|
|
QualType PType = (*PI)->getType();
|
2010-01-12 03:19:56 +08:00
|
|
|
CharUnits sz = getObjCEncodingTypeSize(PType);
|
2011-05-27 09:19:52 +08:00
|
|
|
if (sz.isZero())
|
2012-06-30 06:54:56 +08:00
|
|
|
continue;
|
|
|
|
|
2010-01-12 01:06:35 +08:00
|
|
|
assert (sz.isPositive() &&
|
|
|
|
"getObjCEncodingForMethodDecl - Incomplete param type");
|
2007-10-30 06:57:28 +08:00
|
|
|
ParmOffset += sz;
|
|
|
|
}
|
2010-01-12 01:06:35 +08:00
|
|
|
S += charUnitsToString(ParmOffset);
|
2007-10-30 06:57:28 +08:00
|
|
|
S += "@0:";
|
2010-01-12 01:06:35 +08:00
|
|
|
S += charUnitsToString(PtrSize);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-10-30 06:57:28 +08:00
|
|
|
// Argument types.
|
|
|
|
ParmOffset = 2 * PtrSize;
|
2011-10-03 14:37:04 +08:00
|
|
|
for (ObjCMethodDecl::param_const_iterator PI = Decl->param_begin(),
|
2010-04-09 05:29:11 +08:00
|
|
|
E = Decl->sel_param_end(); PI != E; ++PI) {
|
2011-10-03 14:37:04 +08:00
|
|
|
const ParmVarDecl *PVDecl = *PI;
|
2009-09-09 23:08:12 +08:00
|
|
|
QualType PType = PVDecl->getOriginalType();
|
2008-12-21 07:29:59 +08:00
|
|
|
if (const ArrayType *AT =
|
2009-04-14 08:03:58 +08:00
|
|
|
dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) {
|
|
|
|
// Use array's original type only if it has known number of
|
|
|
|
// elements.
|
2009-04-14 08:40:09 +08:00
|
|
|
if (!isa<ConstantArrayType>(AT))
|
2009-04-14 08:03:58 +08:00
|
|
|
PType = PVDecl->getType();
|
|
|
|
} else if (PType->isFunctionType())
|
|
|
|
PType = PVDecl->getType();
|
2011-11-30 09:57:58 +08:00
|
|
|
getObjCEncodingForMethodParameter(PVDecl->getObjCDeclQualifier(),
|
|
|
|
PType, S, Extended);
|
2010-01-12 01:06:35 +08:00
|
|
|
S += charUnitsToString(ParmOffset);
|
2010-01-12 03:19:56 +08:00
|
|
|
ParmOffset += getObjCEncodingTypeSize(PType);
|
2007-10-30 06:57:28 +08:00
|
|
|
}
|
2011-05-27 09:19:52 +08:00
|
|
|
|
|
|
|
return false;
|
2007-10-30 06:57:28 +08:00
|
|
|
}
|
|
|
|
|
2008-08-28 12:38:10 +08:00
|
|
|
/// getObjCEncodingForPropertyDecl - Return the encoded type for this
|
2009-01-21 04:04:12 +08:00
|
|
|
/// property declaration. If non-NULL, Container must be either an
|
2008-08-28 12:38:10 +08:00
|
|
|
/// ObjCCategoryImplDecl or ObjCImplementationDecl; it should only be
|
|
|
|
/// NULL when getting encodings for protocol properties.
|
2009-09-09 23:08:12 +08:00
|
|
|
/// Property attributes are stored as a comma-delimited C string. The simple
|
|
|
|
/// attributes readonly and bycopy are encoded as single characters. The
|
|
|
|
/// parametrized attributes, getter=name, setter=name, and ivar=name, are
|
|
|
|
/// encoded as single characters, followed by an identifier. Property types
|
|
|
|
/// are also encoded as a parametrized attribute. The characters used to encode
|
2009-01-21 04:04:12 +08:00
|
|
|
/// these attributes are defined by the following enumeration:
|
|
|
|
/// @code
|
|
|
|
/// enum PropertyAttributes {
|
|
|
|
/// kPropertyReadOnly = 'R', // property is read-only.
|
|
|
|
/// kPropertyBycopy = 'C', // property is a copy of the value last assigned
|
|
|
|
/// kPropertyByref = '&', // property is a reference to the value last assigned
|
|
|
|
/// kPropertyDynamic = 'D', // property is dynamic
|
|
|
|
/// kPropertyGetter = 'G', // followed by getter selector name
|
|
|
|
/// kPropertySetter = 'S', // followed by setter selector name
|
|
|
|
/// kPropertyInstanceVariable = 'V' // followed by instance variable name
|
2012-03-23 01:48:02 +08:00
|
|
|
/// kPropertyType = 'T' // followed by old-style type encoding.
|
2009-01-21 04:04:12 +08:00
|
|
|
/// kPropertyWeak = 'W' // 'weak' property
|
|
|
|
/// kPropertyStrong = 'P' // property GC'able
|
|
|
|
/// kPropertyNonAtomic = 'N' // property non-atomic
|
|
|
|
/// };
|
|
|
|
/// @endcode
|
2009-09-09 23:08:12 +08:00
|
|
|
void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
|
2008-08-28 12:38:10 +08:00
|
|
|
const Decl *Container,
|
2011-01-12 17:06:06 +08:00
|
|
|
std::string& S) const {
|
2008-08-28 12:38:10 +08:00
|
|
|
// Collect information from the property implementation decl(s).
|
|
|
|
bool Dynamic = false;
|
|
|
|
ObjCPropertyImplDecl *SynthesizePID = 0;
|
|
|
|
|
|
|
|
// FIXME: Duplicated code due to poor abstraction.
|
|
|
|
if (Container) {
|
2009-09-09 23:08:12 +08:00
|
|
|
if (const ObjCCategoryImplDecl *CID =
|
2008-08-28 12:38:10 +08:00
|
|
|
dyn_cast<ObjCCategoryImplDecl>(Container)) {
|
|
|
|
for (ObjCCategoryImplDecl::propimpl_iterator
|
2009-06-30 10:36:12 +08:00
|
|
|
i = CID->propimpl_begin(), e = CID->propimpl_end();
|
2009-04-23 09:02:12 +08:00
|
|
|
i != e; ++i) {
|
2012-06-07 04:45:41 +08:00
|
|
|
ObjCPropertyImplDecl *PID = *i;
|
2008-08-28 12:38:10 +08:00
|
|
|
if (PID->getPropertyDecl() == PD) {
|
|
|
|
if (PID->getPropertyImplementation()==ObjCPropertyImplDecl::Dynamic) {
|
|
|
|
Dynamic = true;
|
|
|
|
} else {
|
|
|
|
SynthesizePID = PID;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2008-10-06 01:34:18 +08:00
|
|
|
const ObjCImplementationDecl *OID=cast<ObjCImplementationDecl>(Container);
|
2008-08-28 12:38:10 +08:00
|
|
|
for (ObjCCategoryImplDecl::propimpl_iterator
|
2009-06-30 10:36:12 +08:00
|
|
|
i = OID->propimpl_begin(), e = OID->propimpl_end();
|
2009-04-23 09:02:12 +08:00
|
|
|
i != e; ++i) {
|
2012-06-07 04:45:41 +08:00
|
|
|
ObjCPropertyImplDecl *PID = *i;
|
2008-08-28 12:38:10 +08:00
|
|
|
if (PID->getPropertyDecl() == PD) {
|
|
|
|
if (PID->getPropertyImplementation()==ObjCPropertyImplDecl::Dynamic) {
|
|
|
|
Dynamic = true;
|
|
|
|
} else {
|
|
|
|
SynthesizePID = PID;
|
|
|
|
}
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2008-08-28 12:38:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: This is not very efficient.
|
|
|
|
S = "T";
|
|
|
|
|
|
|
|
// Encode result type.
|
2009-01-21 03:14:18 +08:00
|
|
|
// GCC has some special rules regarding encoding of properties which
|
|
|
|
// closely resembles encoding of ivars.
|
2009-09-09 23:08:12 +08:00
|
|
|
getObjCEncodingForTypeImpl(PD->getType(), S, true, true, 0,
|
2009-01-21 03:14:18 +08:00
|
|
|
true /* outermost type */,
|
|
|
|
true /* encoding for property */);
|
2008-08-28 12:38:10 +08:00
|
|
|
|
|
|
|
if (PD->isReadOnly()) {
|
|
|
|
S += ",R";
|
|
|
|
} else {
|
|
|
|
switch (PD->getSetterKind()) {
|
|
|
|
case ObjCPropertyDecl::Assign: break;
|
|
|
|
case ObjCPropertyDecl::Copy: S += ",C"; break;
|
2009-09-09 23:08:12 +08:00
|
|
|
case ObjCPropertyDecl::Retain: S += ",&"; break;
|
2011-08-13 04:47:08 +08:00
|
|
|
case ObjCPropertyDecl::Weak: S += ",W"; break;
|
2008-08-28 12:38:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// It really isn't clear at all what this means, since properties
|
|
|
|
// are "dynamic by default".
|
|
|
|
if (Dynamic)
|
|
|
|
S += ",D";
|
|
|
|
|
2009-01-21 03:14:18 +08:00
|
|
|
if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic)
|
|
|
|
S += ",N";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-08-28 12:38:10 +08:00
|
|
|
if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) {
|
|
|
|
S += ",G";
|
2008-11-24 11:33:13 +08:00
|
|
|
S += PD->getGetterName().getAsString();
|
2008-08-28 12:38:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) {
|
|
|
|
S += ",S";
|
2008-11-24 11:33:13 +08:00
|
|
|
S += PD->getSetterName().getAsString();
|
2008-08-28 12:38:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (SynthesizePID) {
|
|
|
|
const ObjCIvarDecl *OID = SynthesizePID->getPropertyIvarDecl();
|
|
|
|
S += ",V";
|
2008-11-24 12:00:27 +08:00
|
|
|
S += OID->getNameAsString();
|
2008-08-28 12:38:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: OBJCGC: weak & strong
|
|
|
|
}
|
|
|
|
|
2008-12-24 03:56:47 +08:00
|
|
|
/// getLegacyIntegralTypeEncoding -
|
2009-09-09 23:08:12 +08:00
|
|
|
/// Another legacy compatibility encoding: 32-bit longs are encoded as
|
|
|
|
/// 'l' or 'L' , but not always. For typedefs, we need to use
|
2008-12-24 03:56:47 +08:00
|
|
|
/// 'i' or 'I' instead if encoding a struct field, or a pointer!
|
|
|
|
///
|
|
|
|
void ASTContext::getLegacyIntegralTypeEncoding (QualType &PointeeTy) const {
|
2009-07-23 02:58:19 +08:00
|
|
|
if (isa<TypedefType>(PointeeTy.getTypePtr())) {
|
2009-09-22 07:43:11 +08:00
|
|
|
if (const BuiltinType *BT = PointeeTy->getAs<BuiltinType>()) {
|
2011-01-12 17:06:06 +08:00
|
|
|
if (BT->getKind() == BuiltinType::ULong && getIntWidth(PointeeTy) == 32)
|
2008-12-24 03:56:47 +08:00
|
|
|
PointeeTy = UnsignedIntTy;
|
2009-09-09 23:08:12 +08:00
|
|
|
else
|
2011-01-12 17:06:06 +08:00
|
|
|
if (BT->getKind() == BuiltinType::Long && getIntWidth(PointeeTy) == 32)
|
2008-12-24 03:56:47 +08:00
|
|
|
PointeeTy = IntTy;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-23 06:44:46 +08:00
|
|
|
void ASTContext::getObjCEncodingForType(QualType T, std::string& S,
|
2011-01-12 17:06:06 +08:00
|
|
|
const FieldDecl *Field) const {
|
2008-10-17 15:30:50 +08:00
|
|
|
// We follow the behavior of gcc, expanding structures which are
|
|
|
|
// directly pointed to, and expanding embedded structures. Note that
|
|
|
|
// these rules are sufficient to prevent recursive encoding of the
|
|
|
|
// same type.
|
2009-09-09 23:08:12 +08:00
|
|
|
getObjCEncodingForTypeImpl(T, S, true, true, Field,
|
2008-12-23 07:22:27 +08:00
|
|
|
true /* outermost type */);
|
2008-10-17 15:30:50 +08:00
|
|
|
}
|
|
|
|
|
2012-12-20 10:45:14 +08:00
|
|
|
static char getObjCEncodingForPrimitiveKind(const ASTContext *C,
|
|
|
|
BuiltinType::Kind kind) {
|
|
|
|
switch (kind) {
|
2010-06-04 09:10:52 +08:00
|
|
|
case BuiltinType::Void: return 'v';
|
|
|
|
case BuiltinType::Bool: return 'B';
|
|
|
|
case BuiltinType::Char_U:
|
|
|
|
case BuiltinType::UChar: return 'C';
|
2012-12-20 10:45:14 +08:00
|
|
|
case BuiltinType::Char16:
|
2010-06-04 09:10:52 +08:00
|
|
|
case BuiltinType::UShort: return 'S';
|
2012-12-20 10:45:14 +08:00
|
|
|
case BuiltinType::Char32:
|
2010-06-04 09:10:52 +08:00
|
|
|
case BuiltinType::UInt: return 'I';
|
|
|
|
case BuiltinType::ULong:
|
2012-12-20 10:45:14 +08:00
|
|
|
return C->getTargetInfo().getLongWidth() == 32 ? 'L' : 'Q';
|
2010-06-04 09:10:52 +08:00
|
|
|
case BuiltinType::UInt128: return 'T';
|
|
|
|
case BuiltinType::ULongLong: return 'Q';
|
|
|
|
case BuiltinType::Char_S:
|
|
|
|
case BuiltinType::SChar: return 'c';
|
|
|
|
case BuiltinType::Short: return 's';
|
2010-12-26 07:25:43 +08:00
|
|
|
case BuiltinType::WChar_S:
|
|
|
|
case BuiltinType::WChar_U:
|
2010-06-04 09:10:52 +08:00
|
|
|
case BuiltinType::Int: return 'i';
|
|
|
|
case BuiltinType::Long:
|
2012-12-20 10:45:14 +08:00
|
|
|
return C->getTargetInfo().getLongWidth() == 32 ? 'l' : 'q';
|
2010-06-04 09:10:52 +08:00
|
|
|
case BuiltinType::LongLong: return 'q';
|
|
|
|
case BuiltinType::Int128: return 't';
|
|
|
|
case BuiltinType::Float: return 'f';
|
|
|
|
case BuiltinType::Double: return 'd';
|
2010-10-12 05:13:48 +08:00
|
|
|
case BuiltinType::LongDouble: return 'D';
|
2012-12-20 10:45:14 +08:00
|
|
|
case BuiltinType::NullPtr: return '*'; // like char*
|
|
|
|
|
|
|
|
case BuiltinType::Half:
|
|
|
|
// FIXME: potentially need @encodes for these!
|
|
|
|
return ' ';
|
|
|
|
|
|
|
|
case BuiltinType::ObjCId:
|
|
|
|
case BuiltinType::ObjCClass:
|
|
|
|
case BuiltinType::ObjCSel:
|
|
|
|
llvm_unreachable("@encoding ObjC primitive type");
|
|
|
|
|
|
|
|
// OpenCL and placeholder types don't need @encodings.
|
|
|
|
case BuiltinType::OCLImage1d:
|
|
|
|
case BuiltinType::OCLImage1dArray:
|
|
|
|
case BuiltinType::OCLImage1dBuffer:
|
|
|
|
case BuiltinType::OCLImage2d:
|
|
|
|
case BuiltinType::OCLImage2dArray:
|
|
|
|
case BuiltinType::OCLImage3d:
|
2013-01-20 20:31:11 +08:00
|
|
|
case BuiltinType::OCLEvent:
|
2013-02-07 18:55:47 +08:00
|
|
|
case BuiltinType::OCLSampler:
|
2012-12-20 10:45:14 +08:00
|
|
|
case BuiltinType::Dependent:
|
|
|
|
#define BUILTIN_TYPE(KIND, ID)
|
|
|
|
#define PLACEHOLDER_TYPE(KIND, ID) \
|
|
|
|
case BuiltinType::KIND:
|
|
|
|
#include "clang/AST/BuiltinTypes.def"
|
|
|
|
llvm_unreachable("invalid builtin type for @encode");
|
2010-06-04 09:10:52 +08:00
|
|
|
}
|
2013-01-10 01:48:41 +08:00
|
|
|
llvm_unreachable("invalid BuiltinType::Kind value");
|
2010-06-04 09:10:52 +08:00
|
|
|
}
|
|
|
|
|
2011-09-09 01:18:35 +08:00
|
|
|
static char ObjCEncodingForEnumType(const ASTContext *C, const EnumType *ET) {
|
|
|
|
EnumDecl *Enum = ET->getDecl();
|
|
|
|
|
|
|
|
// The encoding of an non-fixed enum type is always 'i', regardless of size.
|
|
|
|
if (!Enum->isFixed())
|
|
|
|
return 'i';
|
|
|
|
|
|
|
|
// The encoding of a fixed enum type matches its fixed underlying type.
|
2012-12-20 10:45:14 +08:00
|
|
|
const BuiltinType *BT = Enum->getIntegerType()->castAs<BuiltinType>();
|
|
|
|
return getObjCEncodingForPrimitiveKind(C, BT->getKind());
|
2011-09-09 01:18:35 +08:00
|
|
|
}
|
|
|
|
|
2011-01-12 17:06:06 +08:00
|
|
|
static void EncodeBitField(const ASTContext *Ctx, std::string& S,
|
2010-06-04 09:10:52 +08:00
|
|
|
QualType T, const FieldDecl *FD) {
|
2011-10-11 02:28:20 +08:00
|
|
|
assert(FD->isBitField() && "not a bitfield - getObjCEncodingForTypeImpl");
|
2009-01-13 09:18:13 +08:00
|
|
|
S += 'b';
|
2010-06-04 09:10:52 +08:00
|
|
|
// The NeXT runtime encodes bit fields as b followed by the number of bits.
|
|
|
|
// The GNU runtime requires more information; bitfields are encoded as b,
|
|
|
|
// then the offset (in bits) of the first element, then the type of the
|
|
|
|
// bitfield, then the size in bits. For example, in this structure:
|
|
|
|
//
|
|
|
|
// struct
|
|
|
|
// {
|
|
|
|
// int integer;
|
|
|
|
// int flags:2;
|
|
|
|
// };
|
|
|
|
// On a 32-bit system, the encoding for flags would be b2 for the NeXT
|
|
|
|
// runtime, but b32i2 for the GNU runtime. The reason for this extra
|
|
|
|
// information is not especially sensible, but we're stuck with it for
|
|
|
|
// compatibility with GCC, although providing it breaks anything that
|
|
|
|
// actually uses runtime introspection and wants to work on both runtimes...
|
2012-06-20 14:18:46 +08:00
|
|
|
if (Ctx->getLangOpts().ObjCRuntime.isGNUFamily()) {
|
2010-06-04 09:10:52 +08:00
|
|
|
const RecordDecl *RD = FD->getParent();
|
|
|
|
const ASTRecordLayout &RL = Ctx->getASTRecordLayout(RD);
|
2011-07-07 09:54:01 +08:00
|
|
|
S += llvm::utostr(RL.getFieldOffset(FD->getFieldIndex()));
|
2011-09-09 01:18:35 +08:00
|
|
|
if (const EnumType *ET = T->getAs<EnumType>())
|
|
|
|
S += ObjCEncodingForEnumType(Ctx, ET);
|
2012-12-20 10:45:14 +08:00
|
|
|
else {
|
|
|
|
const BuiltinType *BT = T->castAs<BuiltinType>();
|
|
|
|
S += getObjCEncodingForPrimitiveKind(Ctx, BT->getKind());
|
|
|
|
}
|
2010-06-04 09:10:52 +08:00
|
|
|
}
|
2011-10-11 02:28:20 +08:00
|
|
|
S += llvm::utostr(FD->getBitWidthValue(*Ctx));
|
2009-01-13 09:18:13 +08:00
|
|
|
}
|
|
|
|
|
2009-10-19 05:17:35 +08:00
|
|
|
// FIXME: Use SmallString for accumulating string.
|
2008-10-17 15:30:50 +08:00
|
|
|
void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
|
|
|
bool ExpandPointedToStructures,
|
|
|
|
bool ExpandStructures,
|
2009-04-20 14:37:24 +08:00
|
|
|
const FieldDecl *FD,
|
2009-01-21 03:14:18 +08:00
|
|
|
bool OutermostType,
|
2011-05-17 08:46:38 +08:00
|
|
|
bool EncodingProperty,
|
2011-11-30 09:57:58 +08:00
|
|
|
bool StructField,
|
|
|
|
bool EncodeBlockParameters,
|
|
|
|
bool EncodeClassNames) const {
|
2012-12-20 10:45:14 +08:00
|
|
|
CanQualType CT = getCanonicalType(T);
|
|
|
|
switch (CT->getTypeClass()) {
|
|
|
|
case Type::Builtin:
|
|
|
|
case Type::Enum:
|
2009-07-13 08:10:46 +08:00
|
|
|
if (FD && FD->isBitField())
|
2010-06-04 09:10:52 +08:00
|
|
|
return EncodeBitField(this, S, T, FD);
|
2012-12-20 10:45:14 +08:00
|
|
|
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CT))
|
|
|
|
S += getObjCEncodingForPrimitiveKind(this, BT->getKind());
|
|
|
|
else
|
|
|
|
S += ObjCEncodingForEnumType(this, cast<EnumType>(CT));
|
2009-07-13 08:10:46 +08:00
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-12-20 10:45:14 +08:00
|
|
|
case Type::Complex: {
|
|
|
|
const ComplexType *CT = T->castAs<ComplexType>();
|
2009-04-10 05:55:45 +08:00
|
|
|
S += 'j';
|
2009-09-09 23:08:12 +08:00
|
|
|
getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, 0, false,
|
2009-04-10 05:55:45 +08:00
|
|
|
false);
|
2009-07-13 08:10:46 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-12-20 10:45:14 +08:00
|
|
|
|
|
|
|
case Type::Atomic: {
|
|
|
|
const AtomicType *AT = T->castAs<AtomicType>();
|
|
|
|
S += 'A';
|
|
|
|
getObjCEncodingForTypeImpl(AT->getValueType(), S, false, false, 0,
|
|
|
|
false, false);
|
|
|
|
return;
|
2010-04-14 07:45:47 +08:00
|
|
|
}
|
2012-12-20 10:45:14 +08:00
|
|
|
|
|
|
|
// encoding for pointer or reference types.
|
|
|
|
case Type::Pointer:
|
|
|
|
case Type::LValueReference:
|
|
|
|
case Type::RValueReference: {
|
|
|
|
QualType PointeeTy;
|
|
|
|
if (isa<PointerType>(CT)) {
|
|
|
|
const PointerType *PT = T->castAs<PointerType>();
|
|
|
|
if (PT->isObjCSelType()) {
|
|
|
|
S += ':';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
PointeeTy = PT->getPointeeType();
|
|
|
|
} else {
|
|
|
|
PointeeTy = T->castAs<ReferenceType>()->getPointeeType();
|
|
|
|
}
|
|
|
|
|
2008-12-24 03:56:47 +08:00
|
|
|
bool isReadOnly = false;
|
|
|
|
// For historical/compatibility reasons, the read-only qualifier of the
|
|
|
|
// pointee gets emitted _before_ the '^'. The read-only qualifier of
|
|
|
|
// the pointer itself gets ignored, _unless_ we are looking at a typedef!
|
2009-09-09 23:08:12 +08:00
|
|
|
// Also, do not emit the 'r' for anything but the outermost type!
|
2009-07-23 02:58:19 +08:00
|
|
|
if (isa<TypedefType>(T.getTypePtr())) {
|
2008-12-24 03:56:47 +08:00
|
|
|
if (OutermostType && T.isConstQualified()) {
|
|
|
|
isReadOnly = true;
|
|
|
|
S += 'r';
|
|
|
|
}
|
2009-07-31 10:02:20 +08:00
|
|
|
} else if (OutermostType) {
|
2008-12-24 03:56:47 +08:00
|
|
|
QualType P = PointeeTy;
|
2009-07-30 05:53:49 +08:00
|
|
|
while (P->getAs<PointerType>())
|
|
|
|
P = P->getAs<PointerType>()->getPointeeType();
|
2008-12-24 03:56:47 +08:00
|
|
|
if (P.isConstQualified()) {
|
|
|
|
isReadOnly = true;
|
|
|
|
S += 'r';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (isReadOnly) {
|
|
|
|
// Another legacy compatibility encoding. Some ObjC qualifier and type
|
|
|
|
// combinations need to be rearranged.
|
|
|
|
// Rewrite "in const" from "nr" to "rn"
|
2011-07-23 18:55:15 +08:00
|
|
|
if (StringRef(S).endswith("nr"))
|
2010-04-28 01:12:11 +08:00
|
|
|
S.replace(S.end()-2, S.end(), "rn");
|
2008-12-24 03:56:47 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-10-29 13:01:08 +08:00
|
|
|
if (PointeeTy->isCharType()) {
|
|
|
|
// char pointer types should be encoded as '*' unless it is a
|
|
|
|
// type that has been typedef'd to 'BOOL'.
|
2007-10-29 14:33:42 +08:00
|
|
|
if (!isTypeTypedefedAsBOOL(PointeeTy)) {
|
2007-10-29 13:01:08 +08:00
|
|
|
S += '*';
|
|
|
|
return;
|
|
|
|
}
|
2009-07-30 05:53:49 +08:00
|
|
|
} else if (const RecordType *RTy = PointeeTy->getAs<RecordType>()) {
|
2009-07-23 01:14:51 +08:00
|
|
|
// GCC binary compat: Need to convert "struct objc_class *" to "#".
|
|
|
|
if (RTy->getDecl()->getIdentifier() == &Idents.get("objc_class")) {
|
|
|
|
S += '#';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// GCC binary compat: Need to convert "struct objc_object *" to "@".
|
|
|
|
if (RTy->getDecl()->getIdentifier() == &Idents.get("objc_object")) {
|
|
|
|
S += '@';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// fall through...
|
2007-10-29 13:01:08 +08:00
|
|
|
}
|
|
|
|
S += '^';
|
2008-12-24 03:56:47 +08:00
|
|
|
getLegacyIntegralTypeEncoding(PointeeTy);
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
getObjCEncodingForTypeImpl(PointeeTy, S, false, ExpandPointedToStructures,
|
2008-12-20 07:34:38 +08:00
|
|
|
NULL);
|
2009-07-13 08:10:46 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-12-20 10:45:14 +08:00
|
|
|
|
|
|
|
case Type::ConstantArray:
|
|
|
|
case Type::IncompleteArray:
|
|
|
|
case Type::VariableArray: {
|
|
|
|
const ArrayType *AT = cast<ArrayType>(CT);
|
|
|
|
|
2011-05-17 08:46:38 +08:00
|
|
|
if (isa<IncompleteArrayType>(AT) && !StructField) {
|
2009-02-22 09:38:57 +08:00
|
|
|
// Incomplete arrays are encoded as a pointer to the array element.
|
|
|
|
S += '^';
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
getObjCEncodingForTypeImpl(AT->getElementType(), S,
|
2009-02-22 09:38:57 +08:00
|
|
|
false, ExpandStructures, FD);
|
|
|
|
} else {
|
|
|
|
S += '[';
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-05-17 08:46:38 +08:00
|
|
|
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
|
|
|
|
if (getTypeSize(CAT->getElementType()) == 0)
|
|
|
|
S += '0';
|
|
|
|
else
|
|
|
|
S += llvm::utostr(CAT->getSize().getZExtValue());
|
|
|
|
} else {
|
2009-02-22 09:38:57 +08:00
|
|
|
//Variable length arrays are encoded as a regular array with 0 elements.
|
2011-05-17 08:46:38 +08:00
|
|
|
assert((isa<VariableArrayType>(AT) || isa<IncompleteArrayType>(AT)) &&
|
|
|
|
"Unknown array type!");
|
2009-02-22 09:38:57 +08:00
|
|
|
S += '0';
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
getObjCEncodingForTypeImpl(AT->getElementType(), S,
|
2009-02-22 09:38:57 +08:00
|
|
|
false, ExpandStructures, FD);
|
|
|
|
S += ']';
|
|
|
|
}
|
2009-07-13 08:10:46 +08:00
|
|
|
return;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-12-20 10:45:14 +08:00
|
|
|
case Type::FunctionNoProto:
|
|
|
|
case Type::FunctionProto:
|
2007-10-30 08:06:20 +08:00
|
|
|
S += '?';
|
2009-07-13 08:10:46 +08:00
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-12-20 10:45:14 +08:00
|
|
|
case Type::Record: {
|
|
|
|
RecordDecl *RDecl = cast<RecordType>(CT)->getDecl();
|
2008-10-18 00:17:37 +08:00
|
|
|
S += RDecl->isUnion() ? '(' : '{';
|
2008-10-17 14:22:57 +08:00
|
|
|
// Anonymous structures print as '?'
|
|
|
|
if (const IdentifierInfo *II = RDecl->getIdentifier()) {
|
|
|
|
S += II->getName();
|
2010-05-07 08:28:49 +08:00
|
|
|
if (ClassTemplateSpecializationDecl *Spec
|
|
|
|
= dyn_cast<ClassTemplateSpecializationDecl>(RDecl)) {
|
|
|
|
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
|
|
|
|
std::string TemplateArgsStr
|
|
|
|
= TemplateSpecializationType::PrintTemplateArgumentList(
|
2010-11-08 07:05:16 +08:00
|
|
|
TemplateArgs.data(),
|
|
|
|
TemplateArgs.size(),
|
2011-09-28 06:38:19 +08:00
|
|
|
(*this).getPrintingPolicy());
|
2010-05-07 08:28:49 +08:00
|
|
|
|
|
|
|
S += TemplateArgsStr;
|
|
|
|
}
|
2008-10-17 14:22:57 +08:00
|
|
|
} else {
|
|
|
|
S += '?';
|
|
|
|
}
|
2008-10-18 04:21:44 +08:00
|
|
|
if (ExpandStructures) {
|
2008-01-23 06:44:46 +08:00
|
|
|
S += '=';
|
2011-05-17 08:46:38 +08:00
|
|
|
if (!RDecl->isUnion()) {
|
|
|
|
getObjCEncodingForStructureImpl(RDecl, S, FD);
|
|
|
|
} else {
|
|
|
|
for (RecordDecl::field_iterator Field = RDecl->field_begin(),
|
|
|
|
FieldEnd = RDecl->field_end();
|
|
|
|
Field != FieldEnd; ++Field) {
|
|
|
|
if (FD) {
|
|
|
|
S += '"';
|
|
|
|
S += Field->getNameAsString();
|
|
|
|
S += '"';
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-05-17 08:46:38 +08:00
|
|
|
// Special case bit-fields.
|
|
|
|
if (Field->isBitField()) {
|
|
|
|
getObjCEncodingForTypeImpl(Field->getType(), S, false, true,
|
2012-06-07 04:45:41 +08:00
|
|
|
*Field);
|
2011-05-17 08:46:38 +08:00
|
|
|
} else {
|
|
|
|
QualType qt = Field->getType();
|
|
|
|
getLegacyIntegralTypeEncoding(qt);
|
|
|
|
getObjCEncodingForTypeImpl(qt, S, false, true,
|
|
|
|
FD, /*OutermostType*/false,
|
|
|
|
/*EncodingProperty*/false,
|
|
|
|
/*StructField*/true);
|
|
|
|
}
|
2008-10-18 00:17:37 +08:00
|
|
|
}
|
2008-01-23 06:44:46 +08:00
|
|
|
}
|
2007-11-14 07:21:38 +08:00
|
|
|
}
|
2008-10-18 00:17:37 +08:00
|
|
|
S += RDecl->isUnion() ? ')' : '}';
|
2009-07-13 08:10:46 +08:00
|
|
|
return;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-12-20 10:45:14 +08:00
|
|
|
case Type::BlockPointer: {
|
|
|
|
const BlockPointerType *BT = T->castAs<BlockPointerType>();
|
2009-02-03 02:24:29 +08:00
|
|
|
S += "@?"; // Unlike a pointer-to-function, which is "^?".
|
2011-11-30 09:57:58 +08:00
|
|
|
if (EncodeBlockParameters) {
|
2012-12-20 10:45:14 +08:00
|
|
|
const FunctionType *FT = BT->getPointeeType()->castAs<FunctionType>();
|
2011-11-30 09:57:58 +08:00
|
|
|
|
|
|
|
S += '<';
|
|
|
|
// Block return type
|
|
|
|
getObjCEncodingForTypeImpl(FT->getResultType(), S,
|
|
|
|
ExpandPointedToStructures, ExpandStructures,
|
|
|
|
FD,
|
|
|
|
false /* OutermostType */,
|
|
|
|
EncodingProperty,
|
|
|
|
false /* StructField */,
|
|
|
|
EncodeBlockParameters,
|
|
|
|
EncodeClassNames);
|
|
|
|
// Block self
|
|
|
|
S += "@?";
|
|
|
|
// Block parameters
|
|
|
|
if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT)) {
|
|
|
|
for (FunctionProtoType::arg_type_iterator I = FPT->arg_type_begin(),
|
|
|
|
E = FPT->arg_type_end(); I && (I != E); ++I) {
|
|
|
|
getObjCEncodingForTypeImpl(*I, S,
|
|
|
|
ExpandPointedToStructures,
|
|
|
|
ExpandStructures,
|
|
|
|
FD,
|
|
|
|
false /* OutermostType */,
|
|
|
|
EncodingProperty,
|
|
|
|
false /* StructField */,
|
|
|
|
EncodeBlockParameters,
|
|
|
|
EncodeClassNames);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
S += '>';
|
|
|
|
}
|
2009-07-13 08:10:46 +08:00
|
|
|
return;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-12-20 10:45:14 +08:00
|
|
|
case Type::ObjCObject:
|
|
|
|
case Type::ObjCInterface: {
|
|
|
|
// Ignore protocol qualifiers when mangling at this level.
|
|
|
|
T = T->castAs<ObjCObjectType>()->getBaseType();
|
2010-05-15 19:32:37 +08:00
|
|
|
|
2012-12-20 10:45:14 +08:00
|
|
|
// The assumption seems to be that this assert will succeed
|
|
|
|
// because nested levels will have filtered out 'id' and 'Class'.
|
|
|
|
const ObjCInterfaceType *OIT = T->castAs<ObjCInterfaceType>();
|
2008-12-20 07:34:38 +08:00
|
|
|
// @encode(class_name)
|
2009-09-25 03:53:00 +08:00
|
|
|
ObjCInterfaceDecl *OI = OIT->getDecl();
|
2008-12-20 07:34:38 +08:00
|
|
|
S += '{';
|
|
|
|
const IdentifierInfo *II = OI->getIdentifier();
|
|
|
|
S += II->getName();
|
|
|
|
S += '=';
|
2011-07-22 10:08:32 +08:00
|
|
|
SmallVector<const ObjCIvarDecl*, 32> Ivars;
|
2010-08-21 05:21:08 +08:00
|
|
|
DeepCollectObjCIvars(OI, true, Ivars);
|
|
|
|
for (unsigned i = 0, e = Ivars.size(); i != e; ++i) {
|
2011-07-22 10:08:32 +08:00
|
|
|
const FieldDecl *Field = cast<FieldDecl>(Ivars[i]);
|
2010-08-21 05:21:08 +08:00
|
|
|
if (Field->isBitField())
|
|
|
|
getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field);
|
2008-12-20 07:34:38 +08:00
|
|
|
else
|
2010-08-21 05:21:08 +08:00
|
|
|
getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD);
|
2008-12-20 07:34:38 +08:00
|
|
|
}
|
|
|
|
S += '}';
|
2009-07-13 08:10:46 +08:00
|
|
|
return;
|
2008-12-20 07:34:38 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-12-20 10:45:14 +08:00
|
|
|
case Type::ObjCObjectPointer: {
|
|
|
|
const ObjCObjectPointerType *OPT = T->castAs<ObjCObjectPointerType>();
|
2009-07-11 07:34:53 +08:00
|
|
|
if (OPT->isObjCIdType()) {
|
|
|
|
S += '@';
|
|
|
|
return;
|
2009-07-13 08:10:46 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-29 06:03:49 +08:00
|
|
|
if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) {
|
|
|
|
// FIXME: Consider if we need to output qualifiers for 'Class<p>'.
|
|
|
|
// Since this is a binary compatibility issue, need to consult with runtime
|
|
|
|
// folks. Fortunately, this is a *very* obsure construct.
|
2009-07-11 07:34:53 +08:00
|
|
|
S += '#';
|
|
|
|
return;
|
2009-07-13 08:10:46 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-13 08:10:46 +08:00
|
|
|
if (OPT->isObjCQualifiedIdType()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
getObjCEncodingForTypeImpl(getObjCIdType(), S,
|
2009-07-11 07:34:53 +08:00
|
|
|
ExpandPointedToStructures,
|
|
|
|
ExpandStructures, FD);
|
2011-11-30 09:57:58 +08:00
|
|
|
if (FD || EncodingProperty || EncodeClassNames) {
|
2009-07-11 07:34:53 +08:00
|
|
|
// Note that we do extended encoding of protocol qualifer list
|
|
|
|
// Only when doing ivar or property encoding.
|
|
|
|
S += '"';
|
2009-07-21 01:56:53 +08:00
|
|
|
for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
|
|
|
|
E = OPT->qual_end(); I != E; ++I) {
|
2009-07-11 07:34:53 +08:00
|
|
|
S += '<';
|
|
|
|
S += (*I)->getNameAsString();
|
|
|
|
S += '>';
|
|
|
|
}
|
|
|
|
S += '"';
|
|
|
|
}
|
|
|
|
return;
|
2009-07-13 08:10:46 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-13 08:10:46 +08:00
|
|
|
QualType PointeeTy = OPT->getPointeeType();
|
|
|
|
if (!EncodingProperty &&
|
|
|
|
isa<TypedefType>(PointeeTy.getTypePtr())) {
|
|
|
|
// Another historical/compatibility reason.
|
2009-09-09 23:08:12 +08:00
|
|
|
// We encode the underlying type which comes out as
|
2009-07-13 08:10:46 +08:00
|
|
|
// {...};
|
|
|
|
S += '^';
|
2009-09-09 23:08:12 +08:00
|
|
|
getObjCEncodingForTypeImpl(PointeeTy, S,
|
|
|
|
false, ExpandPointedToStructures,
|
2009-07-13 08:10:46 +08:00
|
|
|
NULL);
|
2009-07-11 07:34:53 +08:00
|
|
|
return;
|
|
|
|
}
|
2009-07-13 08:10:46 +08:00
|
|
|
|
|
|
|
S += '@';
|
2011-11-30 09:57:58 +08:00
|
|
|
if (OPT->getInterfaceDecl() &&
|
|
|
|
(FD || EncodingProperty || EncodeClassNames)) {
|
2009-07-13 08:10:46 +08:00
|
|
|
S += '"';
|
2009-10-29 06:03:49 +08:00
|
|
|
S += OPT->getInterfaceDecl()->getIdentifier()->getName();
|
2009-07-21 01:56:53 +08:00
|
|
|
for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
|
|
|
|
E = OPT->qual_end(); I != E; ++I) {
|
2009-07-13 08:10:46 +08:00
|
|
|
S += '<';
|
|
|
|
S += (*I)->getNameAsString();
|
|
|
|
S += '>';
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-07-13 08:10:46 +08:00
|
|
|
S += '"';
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-05-18 07:56:34 +08:00
|
|
|
// gcc just blithely ignores member pointers.
|
2012-12-20 10:45:14 +08:00
|
|
|
// FIXME: we shoul do better than that. 'M' is available.
|
|
|
|
case Type::MemberPointer:
|
2010-05-18 07:56:34 +08:00
|
|
|
return;
|
2010-10-08 05:25:25 +08:00
|
|
|
|
2012-12-20 10:45:14 +08:00
|
|
|
case Type::Vector:
|
|
|
|
case Type::ExtVector:
|
2010-10-08 05:25:25 +08:00
|
|
|
// This matches gcc's encoding, even though technically it is
|
|
|
|
// insufficient.
|
|
|
|
// FIXME. We should do a better job than gcc.
|
|
|
|
return;
|
2012-12-20 10:45:14 +08:00
|
|
|
|
|
|
|
#define ABSTRACT_TYPE(KIND, BASE)
|
|
|
|
#define TYPE(KIND, BASE)
|
|
|
|
#define DEPENDENT_TYPE(KIND, BASE) \
|
|
|
|
case Type::KIND:
|
|
|
|
#define NON_CANONICAL_TYPE(KIND, BASE) \
|
|
|
|
case Type::KIND:
|
|
|
|
#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(KIND, BASE) \
|
|
|
|
case Type::KIND:
|
|
|
|
#include "clang/AST/TypeNodes.def"
|
|
|
|
llvm_unreachable("@encode for dependent type!");
|
2010-10-08 05:25:25 +08:00
|
|
|
}
|
2012-12-20 10:45:14 +08:00
|
|
|
llvm_unreachable("bad type kind!");
|
2007-10-29 13:01:08 +08:00
|
|
|
}
|
|
|
|
|
2011-05-17 08:46:38 +08:00
|
|
|
void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
|
|
|
|
std::string &S,
|
|
|
|
const FieldDecl *FD,
|
|
|
|
bool includeVBases) const {
|
|
|
|
assert(RDecl && "Expected non-null RecordDecl");
|
|
|
|
assert(!RDecl->isUnion() && "Should not be called for unions");
|
|
|
|
if (!RDecl->getDefinition())
|
|
|
|
return;
|
|
|
|
|
|
|
|
CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(RDecl);
|
|
|
|
std::multimap<uint64_t, NamedDecl *> FieldOrBaseOffsets;
|
|
|
|
const ASTRecordLayout &layout = getASTRecordLayout(RDecl);
|
|
|
|
|
|
|
|
if (CXXRec) {
|
|
|
|
for (CXXRecordDecl::base_class_iterator
|
|
|
|
BI = CXXRec->bases_begin(),
|
|
|
|
BE = CXXRec->bases_end(); BI != BE; ++BI) {
|
|
|
|
if (!BI->isVirtual()) {
|
|
|
|
CXXRecordDecl *base = BI->getType()->getAsCXXRecordDecl();
|
2011-06-18 07:19:38 +08:00
|
|
|
if (base->isEmpty())
|
|
|
|
continue;
|
2012-07-05 02:45:14 +08:00
|
|
|
uint64_t offs = toBits(layout.getBaseClassOffset(base));
|
2011-05-17 08:46:38 +08:00
|
|
|
FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs),
|
|
|
|
std::make_pair(offs, base));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned i = 0;
|
|
|
|
for (RecordDecl::field_iterator Field = RDecl->field_begin(),
|
|
|
|
FieldEnd = RDecl->field_end();
|
|
|
|
Field != FieldEnd; ++Field, ++i) {
|
|
|
|
uint64_t offs = layout.getFieldOffset(i);
|
|
|
|
FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs),
|
2012-06-07 04:45:41 +08:00
|
|
|
std::make_pair(offs, *Field));
|
2011-05-17 08:46:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (CXXRec && includeVBases) {
|
|
|
|
for (CXXRecordDecl::base_class_iterator
|
|
|
|
BI = CXXRec->vbases_begin(),
|
|
|
|
BE = CXXRec->vbases_end(); BI != BE; ++BI) {
|
|
|
|
CXXRecordDecl *base = BI->getType()->getAsCXXRecordDecl();
|
2011-06-18 07:19:38 +08:00
|
|
|
if (base->isEmpty())
|
|
|
|
continue;
|
2012-07-05 02:45:14 +08:00
|
|
|
uint64_t offs = toBits(layout.getVBaseClassOffset(base));
|
2011-09-27 02:14:24 +08:00
|
|
|
if (FieldOrBaseOffsets.find(offs) == FieldOrBaseOffsets.end())
|
|
|
|
FieldOrBaseOffsets.insert(FieldOrBaseOffsets.end(),
|
|
|
|
std::make_pair(offs, base));
|
2011-05-17 08:46:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CharUnits size;
|
|
|
|
if (CXXRec) {
|
|
|
|
size = includeVBases ? layout.getSize() : layout.getNonVirtualSize();
|
|
|
|
} else {
|
|
|
|
size = layout.getSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t CurOffs = 0;
|
|
|
|
std::multimap<uint64_t, NamedDecl *>::iterator
|
|
|
|
CurLayObj = FieldOrBaseOffsets.begin();
|
|
|
|
|
2012-04-28 06:30:01 +08:00
|
|
|
if (CXXRec && CXXRec->isDynamicClass() &&
|
|
|
|
(CurLayObj == FieldOrBaseOffsets.end() || CurLayObj->first != 0)) {
|
2011-05-17 08:46:38 +08:00
|
|
|
if (FD) {
|
|
|
|
S += "\"_vptr$";
|
|
|
|
std::string recname = CXXRec->getNameAsString();
|
|
|
|
if (recname.empty()) recname = "?";
|
|
|
|
S += recname;
|
|
|
|
S += '"';
|
|
|
|
}
|
|
|
|
S += "^^?";
|
|
|
|
CurOffs += getTypeSize(VoidPtrTy);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!RDecl->hasFlexibleArrayMember()) {
|
|
|
|
// Mark the end of the structure.
|
|
|
|
uint64_t offs = toBits(size);
|
|
|
|
FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs),
|
|
|
|
std::make_pair(offs, (NamedDecl*)0));
|
|
|
|
}
|
|
|
|
|
|
|
|
for (; CurLayObj != FieldOrBaseOffsets.end(); ++CurLayObj) {
|
|
|
|
assert(CurOffs <= CurLayObj->first);
|
|
|
|
|
|
|
|
if (CurOffs < CurLayObj->first) {
|
|
|
|
uint64_t padding = CurLayObj->first - CurOffs;
|
|
|
|
// FIXME: There doesn't seem to be a way to indicate in the encoding that
|
|
|
|
// packing/alignment of members is different that normal, in which case
|
|
|
|
// the encoding will be out-of-sync with the real layout.
|
|
|
|
// If the runtime switches to just consider the size of types without
|
|
|
|
// taking into account alignment, we could make padding explicit in the
|
|
|
|
// encoding (e.g. using arrays of chars). The encoding strings would be
|
|
|
|
// longer then though.
|
|
|
|
CurOffs += padding;
|
|
|
|
}
|
|
|
|
|
|
|
|
NamedDecl *dcl = CurLayObj->second;
|
|
|
|
if (dcl == 0)
|
|
|
|
break; // reached end of structure.
|
|
|
|
|
|
|
|
if (CXXRecordDecl *base = dyn_cast<CXXRecordDecl>(dcl)) {
|
|
|
|
// We expand the bases without their virtual bases since those are going
|
|
|
|
// in the initial structure. Note that this differs from gcc which
|
|
|
|
// expands virtual bases each time one is encountered in the hierarchy,
|
|
|
|
// making the encoding type bigger than it really is.
|
|
|
|
getObjCEncodingForStructureImpl(base, S, FD, /*includeVBases*/false);
|
2011-06-18 07:19:38 +08:00
|
|
|
assert(!base->isEmpty());
|
|
|
|
CurOffs += toBits(getASTRecordLayout(base).getNonVirtualSize());
|
2011-05-17 08:46:38 +08:00
|
|
|
} else {
|
|
|
|
FieldDecl *field = cast<FieldDecl>(dcl);
|
|
|
|
if (FD) {
|
|
|
|
S += '"';
|
|
|
|
S += field->getNameAsString();
|
|
|
|
S += '"';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (field->isBitField()) {
|
|
|
|
EncodeBitField(this, S, field->getType(), field);
|
2011-10-11 02:28:20 +08:00
|
|
|
CurOffs += field->getBitWidthValue(*this);
|
2011-05-17 08:46:38 +08:00
|
|
|
} else {
|
|
|
|
QualType qt = field->getType();
|
|
|
|
getLegacyIntegralTypeEncoding(qt);
|
|
|
|
getObjCEncodingForTypeImpl(qt, S, false, true, FD,
|
|
|
|
/*OutermostType*/false,
|
|
|
|
/*EncodingProperty*/false,
|
|
|
|
/*StructField*/true);
|
|
|
|
CurOffs += getTypeSize(field->getType());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
void ASTContext::getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT,
|
2007-11-02 01:18:37 +08:00
|
|
|
std::string& S) const {
|
|
|
|
if (QT & Decl::OBJC_TQ_In)
|
|
|
|
S += 'n';
|
|
|
|
if (QT & Decl::OBJC_TQ_Inout)
|
|
|
|
S += 'N';
|
|
|
|
if (QT & Decl::OBJC_TQ_Out)
|
|
|
|
S += 'o';
|
|
|
|
if (QT & Decl::OBJC_TQ_Bycopy)
|
|
|
|
S += 'O';
|
|
|
|
if (QT & Decl::OBJC_TQ_Byref)
|
|
|
|
S += 'R';
|
|
|
|
if (QT & Decl::OBJC_TQ_Oneway)
|
|
|
|
S += 'V';
|
|
|
|
}
|
|
|
|
|
2011-08-12 13:46:01 +08:00
|
|
|
TypedefDecl *ASTContext::getObjCIdDecl() const {
|
|
|
|
if (!ObjCIdDecl) {
|
|
|
|
QualType T = getObjCObjectType(ObjCBuiltinIdTy, 0, 0);
|
|
|
|
T = getObjCObjectPointerType(T);
|
|
|
|
TypeSourceInfo *IdInfo = getTrivialTypeSourceInfo(T);
|
|
|
|
ObjCIdDecl = TypedefDecl::Create(const_cast<ASTContext &>(*this),
|
|
|
|
getTranslationUnitDecl(),
|
|
|
|
SourceLocation(), SourceLocation(),
|
|
|
|
&Idents.get("id"), IdInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ObjCIdDecl;
|
2007-10-15 22:41:52 +08:00
|
|
|
}
|
|
|
|
|
2011-08-12 14:17:30 +08:00
|
|
|
TypedefDecl *ASTContext::getObjCSelDecl() const {
|
|
|
|
if (!ObjCSelDecl) {
|
|
|
|
QualType SelT = getPointerType(ObjCBuiltinSelTy);
|
|
|
|
TypeSourceInfo *SelInfo = getTrivialTypeSourceInfo(SelT);
|
|
|
|
ObjCSelDecl = TypedefDecl::Create(const_cast<ASTContext &>(*this),
|
|
|
|
getTranslationUnitDecl(),
|
|
|
|
SourceLocation(), SourceLocation(),
|
|
|
|
&Idents.get("SEL"), SelInfo);
|
|
|
|
}
|
|
|
|
return ObjCSelDecl;
|
2007-10-17 04:40:23 +08:00
|
|
|
}
|
|
|
|
|
2011-08-12 13:59:41 +08:00
|
|
|
TypedefDecl *ASTContext::getObjCClassDecl() const {
|
|
|
|
if (!ObjCClassDecl) {
|
|
|
|
QualType T = getObjCObjectType(ObjCBuiltinClassTy, 0, 0);
|
|
|
|
T = getObjCObjectPointerType(T);
|
|
|
|
TypeSourceInfo *ClassInfo = getTrivialTypeSourceInfo(T);
|
|
|
|
ObjCClassDecl = TypedefDecl::Create(const_cast<ASTContext &>(*this),
|
|
|
|
getTranslationUnitDecl(),
|
|
|
|
SourceLocation(), SourceLocation(),
|
|
|
|
&Idents.get("Class"), ClassInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ObjCClassDecl;
|
2012-01-18 02:09:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ObjCInterfaceDecl *ASTContext::getObjCProtocolDecl() const {
|
|
|
|
if (!ObjCProtocolClassDecl) {
|
|
|
|
ObjCProtocolClassDecl
|
|
|
|
= ObjCInterfaceDecl::Create(*this, getTranslationUnitDecl(),
|
|
|
|
SourceLocation(),
|
|
|
|
&Idents.get("Protocol"),
|
|
|
|
/*PrevDecl=*/0,
|
|
|
|
SourceLocation(), true);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ObjCProtocolClassDecl;
|
2007-10-31 10:53:19 +08:00
|
|
|
}
|
|
|
|
|
2012-06-16 11:34:49 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// __builtin_va_list Construction Functions
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
static TypedefDecl *CreateCharPtrBuiltinVaListDecl(const ASTContext *Context) {
|
|
|
|
// typedef char* __builtin_va_list;
|
|
|
|
QualType CharPtrType = Context->getPointerType(Context->CharTy);
|
|
|
|
TypeSourceInfo *TInfo
|
|
|
|
= Context->getTrivialTypeSourceInfo(CharPtrType);
|
|
|
|
|
|
|
|
TypedefDecl *VaListTypeDecl
|
|
|
|
= TypedefDecl::Create(const_cast<ASTContext &>(*Context),
|
|
|
|
Context->getTranslationUnitDecl(),
|
|
|
|
SourceLocation(), SourceLocation(),
|
|
|
|
&Context->Idents.get("__builtin_va_list"),
|
|
|
|
TInfo);
|
|
|
|
return VaListTypeDecl;
|
|
|
|
}
|
|
|
|
|
|
|
|
static TypedefDecl *CreateVoidPtrBuiltinVaListDecl(const ASTContext *Context) {
|
|
|
|
// typedef void* __builtin_va_list;
|
|
|
|
QualType VoidPtrType = Context->getPointerType(Context->VoidTy);
|
|
|
|
TypeSourceInfo *TInfo
|
|
|
|
= Context->getTrivialTypeSourceInfo(VoidPtrType);
|
|
|
|
|
|
|
|
TypedefDecl *VaListTypeDecl
|
|
|
|
= TypedefDecl::Create(const_cast<ASTContext &>(*Context),
|
|
|
|
Context->getTranslationUnitDecl(),
|
|
|
|
SourceLocation(), SourceLocation(),
|
|
|
|
&Context->Idents.get("__builtin_va_list"),
|
|
|
|
TInfo);
|
|
|
|
return VaListTypeDecl;
|
|
|
|
}
|
|
|
|
|
2013-01-31 20:13:10 +08:00
|
|
|
static TypedefDecl *
|
|
|
|
CreateAArch64ABIBuiltinVaListDecl(const ASTContext *Context) {
|
|
|
|
RecordDecl *VaListTagDecl;
|
|
|
|
if (Context->getLangOpts().CPlusPlus) {
|
|
|
|
// namespace std { struct __va_list {
|
|
|
|
NamespaceDecl *NS;
|
|
|
|
NS = NamespaceDecl::Create(const_cast<ASTContext &>(*Context),
|
|
|
|
Context->getTranslationUnitDecl(),
|
|
|
|
/*Inline*/false, SourceLocation(),
|
|
|
|
SourceLocation(), &Context->Idents.get("std"),
|
|
|
|
/*PrevDecl*/0);
|
|
|
|
|
|
|
|
VaListTagDecl = CXXRecordDecl::Create(*Context, TTK_Struct,
|
|
|
|
Context->getTranslationUnitDecl(),
|
|
|
|
SourceLocation(), SourceLocation(),
|
|
|
|
&Context->Idents.get("__va_list"));
|
|
|
|
VaListTagDecl->setDeclContext(NS);
|
|
|
|
} else {
|
|
|
|
// struct __va_list
|
|
|
|
VaListTagDecl = CreateRecordDecl(*Context, TTK_Struct,
|
|
|
|
Context->getTranslationUnitDecl(),
|
|
|
|
&Context->Idents.get("__va_list"));
|
|
|
|
}
|
|
|
|
|
|
|
|
VaListTagDecl->startDefinition();
|
|
|
|
|
|
|
|
const size_t NumFields = 5;
|
|
|
|
QualType FieldTypes[NumFields];
|
|
|
|
const char *FieldNames[NumFields];
|
|
|
|
|
|
|
|
// void *__stack;
|
|
|
|
FieldTypes[0] = Context->getPointerType(Context->VoidTy);
|
|
|
|
FieldNames[0] = "__stack";
|
|
|
|
|
|
|
|
// void *__gr_top;
|
|
|
|
FieldTypes[1] = Context->getPointerType(Context->VoidTy);
|
|
|
|
FieldNames[1] = "__gr_top";
|
|
|
|
|
|
|
|
// void *__vr_top;
|
|
|
|
FieldTypes[2] = Context->getPointerType(Context->VoidTy);
|
|
|
|
FieldNames[2] = "__vr_top";
|
|
|
|
|
|
|
|
// int __gr_offs;
|
|
|
|
FieldTypes[3] = Context->IntTy;
|
|
|
|
FieldNames[3] = "__gr_offs";
|
|
|
|
|
|
|
|
// int __vr_offs;
|
|
|
|
FieldTypes[4] = Context->IntTy;
|
|
|
|
FieldNames[4] = "__vr_offs";
|
|
|
|
|
|
|
|
// Create fields
|
|
|
|
for (unsigned i = 0; i < NumFields; ++i) {
|
|
|
|
FieldDecl *Field = FieldDecl::Create(const_cast<ASTContext &>(*Context),
|
|
|
|
VaListTagDecl,
|
|
|
|
SourceLocation(),
|
|
|
|
SourceLocation(),
|
|
|
|
&Context->Idents.get(FieldNames[i]),
|
|
|
|
FieldTypes[i], /*TInfo=*/0,
|
|
|
|
/*BitWidth=*/0,
|
|
|
|
/*Mutable=*/false,
|
|
|
|
ICIS_NoInit);
|
|
|
|
Field->setAccess(AS_public);
|
|
|
|
VaListTagDecl->addDecl(Field);
|
|
|
|
}
|
|
|
|
VaListTagDecl->completeDefinition();
|
|
|
|
QualType VaListTagType = Context->getRecordType(VaListTagDecl);
|
|
|
|
Context->VaListTagTy = VaListTagType;
|
|
|
|
|
|
|
|
// } __builtin_va_list;
|
|
|
|
TypedefDecl *VaListTypedefDecl
|
|
|
|
= TypedefDecl::Create(const_cast<ASTContext &>(*Context),
|
|
|
|
Context->getTranslationUnitDecl(),
|
|
|
|
SourceLocation(), SourceLocation(),
|
|
|
|
&Context->Idents.get("__builtin_va_list"),
|
|
|
|
Context->getTrivialTypeSourceInfo(VaListTagType));
|
|
|
|
|
|
|
|
return VaListTypedefDecl;
|
|
|
|
}
|
|
|
|
|
2012-06-16 11:34:49 +08:00
|
|
|
static TypedefDecl *CreatePowerABIBuiltinVaListDecl(const ASTContext *Context) {
|
|
|
|
// typedef struct __va_list_tag {
|
|
|
|
RecordDecl *VaListTagDecl;
|
|
|
|
|
|
|
|
VaListTagDecl = CreateRecordDecl(*Context, TTK_Struct,
|
|
|
|
Context->getTranslationUnitDecl(),
|
|
|
|
&Context->Idents.get("__va_list_tag"));
|
|
|
|
VaListTagDecl->startDefinition();
|
|
|
|
|
|
|
|
const size_t NumFields = 5;
|
|
|
|
QualType FieldTypes[NumFields];
|
|
|
|
const char *FieldNames[NumFields];
|
|
|
|
|
|
|
|
// unsigned char gpr;
|
|
|
|
FieldTypes[0] = Context->UnsignedCharTy;
|
|
|
|
FieldNames[0] = "gpr";
|
|
|
|
|
|
|
|
// unsigned char fpr;
|
|
|
|
FieldTypes[1] = Context->UnsignedCharTy;
|
|
|
|
FieldNames[1] = "fpr";
|
|
|
|
|
|
|
|
// unsigned short reserved;
|
|
|
|
FieldTypes[2] = Context->UnsignedShortTy;
|
|
|
|
FieldNames[2] = "reserved";
|
|
|
|
|
|
|
|
// void* overflow_arg_area;
|
|
|
|
FieldTypes[3] = Context->getPointerType(Context->VoidTy);
|
|
|
|
FieldNames[3] = "overflow_arg_area";
|
|
|
|
|
|
|
|
// void* reg_save_area;
|
|
|
|
FieldTypes[4] = Context->getPointerType(Context->VoidTy);
|
|
|
|
FieldNames[4] = "reg_save_area";
|
|
|
|
|
|
|
|
// Create fields
|
|
|
|
for (unsigned i = 0; i < NumFields; ++i) {
|
|
|
|
FieldDecl *Field = FieldDecl::Create(*Context, VaListTagDecl,
|
|
|
|
SourceLocation(),
|
|
|
|
SourceLocation(),
|
|
|
|
&Context->Idents.get(FieldNames[i]),
|
|
|
|
FieldTypes[i], /*TInfo=*/0,
|
|
|
|
/*BitWidth=*/0,
|
|
|
|
/*Mutable=*/false,
|
|
|
|
ICIS_NoInit);
|
|
|
|
Field->setAccess(AS_public);
|
|
|
|
VaListTagDecl->addDecl(Field);
|
|
|
|
}
|
|
|
|
VaListTagDecl->completeDefinition();
|
|
|
|
QualType VaListTagType = Context->getRecordType(VaListTagDecl);
|
2012-07-01 23:57:25 +08:00
|
|
|
Context->VaListTagTy = VaListTagType;
|
2012-06-16 11:34:49 +08:00
|
|
|
|
|
|
|
// } __va_list_tag;
|
|
|
|
TypedefDecl *VaListTagTypedefDecl
|
|
|
|
= TypedefDecl::Create(const_cast<ASTContext &>(*Context),
|
|
|
|
Context->getTranslationUnitDecl(),
|
|
|
|
SourceLocation(), SourceLocation(),
|
|
|
|
&Context->Idents.get("__va_list_tag"),
|
|
|
|
Context->getTrivialTypeSourceInfo(VaListTagType));
|
|
|
|
QualType VaListTagTypedefType =
|
|
|
|
Context->getTypedefType(VaListTagTypedefDecl);
|
|
|
|
|
|
|
|
// typedef __va_list_tag __builtin_va_list[1];
|
|
|
|
llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 1);
|
|
|
|
QualType VaListTagArrayType
|
|
|
|
= Context->getConstantArrayType(VaListTagTypedefType,
|
|
|
|
Size, ArrayType::Normal, 0);
|
|
|
|
TypeSourceInfo *TInfo
|
|
|
|
= Context->getTrivialTypeSourceInfo(VaListTagArrayType);
|
|
|
|
TypedefDecl *VaListTypedefDecl
|
|
|
|
= TypedefDecl::Create(const_cast<ASTContext &>(*Context),
|
|
|
|
Context->getTranslationUnitDecl(),
|
|
|
|
SourceLocation(), SourceLocation(),
|
|
|
|
&Context->Idents.get("__builtin_va_list"),
|
|
|
|
TInfo);
|
|
|
|
|
|
|
|
return VaListTypedefDecl;
|
|
|
|
}
|
|
|
|
|
|
|
|
static TypedefDecl *
|
|
|
|
CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) {
|
|
|
|
// typedef struct __va_list_tag {
|
|
|
|
RecordDecl *VaListTagDecl;
|
|
|
|
VaListTagDecl = CreateRecordDecl(*Context, TTK_Struct,
|
|
|
|
Context->getTranslationUnitDecl(),
|
|
|
|
&Context->Idents.get("__va_list_tag"));
|
|
|
|
VaListTagDecl->startDefinition();
|
|
|
|
|
|
|
|
const size_t NumFields = 4;
|
|
|
|
QualType FieldTypes[NumFields];
|
|
|
|
const char *FieldNames[NumFields];
|
|
|
|
|
|
|
|
// unsigned gp_offset;
|
|
|
|
FieldTypes[0] = Context->UnsignedIntTy;
|
|
|
|
FieldNames[0] = "gp_offset";
|
|
|
|
|
|
|
|
// unsigned fp_offset;
|
|
|
|
FieldTypes[1] = Context->UnsignedIntTy;
|
|
|
|
FieldNames[1] = "fp_offset";
|
|
|
|
|
|
|
|
// void* overflow_arg_area;
|
|
|
|
FieldTypes[2] = Context->getPointerType(Context->VoidTy);
|
|
|
|
FieldNames[2] = "overflow_arg_area";
|
|
|
|
|
|
|
|
// void* reg_save_area;
|
|
|
|
FieldTypes[3] = Context->getPointerType(Context->VoidTy);
|
|
|
|
FieldNames[3] = "reg_save_area";
|
|
|
|
|
|
|
|
// Create fields
|
|
|
|
for (unsigned i = 0; i < NumFields; ++i) {
|
|
|
|
FieldDecl *Field = FieldDecl::Create(const_cast<ASTContext &>(*Context),
|
|
|
|
VaListTagDecl,
|
|
|
|
SourceLocation(),
|
|
|
|
SourceLocation(),
|
|
|
|
&Context->Idents.get(FieldNames[i]),
|
|
|
|
FieldTypes[i], /*TInfo=*/0,
|
|
|
|
/*BitWidth=*/0,
|
|
|
|
/*Mutable=*/false,
|
|
|
|
ICIS_NoInit);
|
|
|
|
Field->setAccess(AS_public);
|
|
|
|
VaListTagDecl->addDecl(Field);
|
|
|
|
}
|
|
|
|
VaListTagDecl->completeDefinition();
|
|
|
|
QualType VaListTagType = Context->getRecordType(VaListTagDecl);
|
2012-07-01 23:57:25 +08:00
|
|
|
Context->VaListTagTy = VaListTagType;
|
2012-06-16 11:34:49 +08:00
|
|
|
|
|
|
|
// } __va_list_tag;
|
|
|
|
TypedefDecl *VaListTagTypedefDecl
|
|
|
|
= TypedefDecl::Create(const_cast<ASTContext &>(*Context),
|
|
|
|
Context->getTranslationUnitDecl(),
|
|
|
|
SourceLocation(), SourceLocation(),
|
|
|
|
&Context->Idents.get("__va_list_tag"),
|
|
|
|
Context->getTrivialTypeSourceInfo(VaListTagType));
|
|
|
|
QualType VaListTagTypedefType =
|
|
|
|
Context->getTypedefType(VaListTagTypedefDecl);
|
|
|
|
|
|
|
|
// typedef __va_list_tag __builtin_va_list[1];
|
|
|
|
llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 1);
|
|
|
|
QualType VaListTagArrayType
|
|
|
|
= Context->getConstantArrayType(VaListTagTypedefType,
|
|
|
|
Size, ArrayType::Normal,0);
|
|
|
|
TypeSourceInfo *TInfo
|
|
|
|
= Context->getTrivialTypeSourceInfo(VaListTagArrayType);
|
|
|
|
TypedefDecl *VaListTypedefDecl
|
|
|
|
= TypedefDecl::Create(const_cast<ASTContext &>(*Context),
|
|
|
|
Context->getTranslationUnitDecl(),
|
|
|
|
SourceLocation(), SourceLocation(),
|
|
|
|
&Context->Idents.get("__builtin_va_list"),
|
|
|
|
TInfo);
|
|
|
|
|
|
|
|
return VaListTypedefDecl;
|
|
|
|
}
|
|
|
|
|
|
|
|
static TypedefDecl *CreatePNaClABIBuiltinVaListDecl(const ASTContext *Context) {
|
|
|
|
// typedef int __builtin_va_list[4];
|
|
|
|
llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 4);
|
|
|
|
QualType IntArrayType
|
|
|
|
= Context->getConstantArrayType(Context->IntTy,
|
|
|
|
Size, ArrayType::Normal, 0);
|
|
|
|
TypedefDecl *VaListTypedefDecl
|
|
|
|
= TypedefDecl::Create(const_cast<ASTContext &>(*Context),
|
|
|
|
Context->getTranslationUnitDecl(),
|
|
|
|
SourceLocation(), SourceLocation(),
|
|
|
|
&Context->Idents.get("__builtin_va_list"),
|
|
|
|
Context->getTrivialTypeSourceInfo(IntArrayType));
|
|
|
|
|
|
|
|
return VaListTypedefDecl;
|
|
|
|
}
|
|
|
|
|
2012-10-10 14:56:20 +08:00
|
|
|
static TypedefDecl *
|
|
|
|
CreateAAPCSABIBuiltinVaListDecl(const ASTContext *Context) {
|
|
|
|
RecordDecl *VaListDecl;
|
|
|
|
if (Context->getLangOpts().CPlusPlus) {
|
|
|
|
// namespace std { struct __va_list {
|
|
|
|
NamespaceDecl *NS;
|
|
|
|
NS = NamespaceDecl::Create(const_cast<ASTContext &>(*Context),
|
|
|
|
Context->getTranslationUnitDecl(),
|
|
|
|
/*Inline*/false, SourceLocation(),
|
|
|
|
SourceLocation(), &Context->Idents.get("std"),
|
|
|
|
/*PrevDecl*/0);
|
|
|
|
|
|
|
|
VaListDecl = CXXRecordDecl::Create(*Context, TTK_Struct,
|
|
|
|
Context->getTranslationUnitDecl(),
|
|
|
|
SourceLocation(), SourceLocation(),
|
|
|
|
&Context->Idents.get("__va_list"));
|
|
|
|
|
|
|
|
VaListDecl->setDeclContext(NS);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// struct __va_list {
|
|
|
|
VaListDecl = CreateRecordDecl(*Context, TTK_Struct,
|
|
|
|
Context->getTranslationUnitDecl(),
|
|
|
|
&Context->Idents.get("__va_list"));
|
|
|
|
}
|
|
|
|
|
|
|
|
VaListDecl->startDefinition();
|
|
|
|
|
|
|
|
// void * __ap;
|
|
|
|
FieldDecl *Field = FieldDecl::Create(const_cast<ASTContext &>(*Context),
|
|
|
|
VaListDecl,
|
|
|
|
SourceLocation(),
|
|
|
|
SourceLocation(),
|
|
|
|
&Context->Idents.get("__ap"),
|
|
|
|
Context->getPointerType(Context->VoidTy),
|
|
|
|
/*TInfo=*/0,
|
|
|
|
/*BitWidth=*/0,
|
|
|
|
/*Mutable=*/false,
|
|
|
|
ICIS_NoInit);
|
|
|
|
Field->setAccess(AS_public);
|
|
|
|
VaListDecl->addDecl(Field);
|
|
|
|
|
|
|
|
// };
|
|
|
|
VaListDecl->completeDefinition();
|
|
|
|
|
|
|
|
// typedef struct __va_list __builtin_va_list;
|
|
|
|
TypeSourceInfo *TInfo
|
|
|
|
= Context->getTrivialTypeSourceInfo(Context->getRecordType(VaListDecl));
|
|
|
|
|
|
|
|
TypedefDecl *VaListTypeDecl
|
|
|
|
= TypedefDecl::Create(const_cast<ASTContext &>(*Context),
|
|
|
|
Context->getTranslationUnitDecl(),
|
|
|
|
SourceLocation(), SourceLocation(),
|
|
|
|
&Context->Idents.get("__builtin_va_list"),
|
|
|
|
TInfo);
|
|
|
|
|
|
|
|
return VaListTypeDecl;
|
|
|
|
}
|
|
|
|
|
2012-06-16 11:34:49 +08:00
|
|
|
static TypedefDecl *CreateVaListDecl(const ASTContext *Context,
|
|
|
|
TargetInfo::BuiltinVaListKind Kind) {
|
|
|
|
switch (Kind) {
|
|
|
|
case TargetInfo::CharPtrBuiltinVaList:
|
|
|
|
return CreateCharPtrBuiltinVaListDecl(Context);
|
|
|
|
case TargetInfo::VoidPtrBuiltinVaList:
|
|
|
|
return CreateVoidPtrBuiltinVaListDecl(Context);
|
2013-01-31 20:13:10 +08:00
|
|
|
case TargetInfo::AArch64ABIBuiltinVaList:
|
|
|
|
return CreateAArch64ABIBuiltinVaListDecl(Context);
|
2012-06-16 11:34:49 +08:00
|
|
|
case TargetInfo::PowerABIBuiltinVaList:
|
|
|
|
return CreatePowerABIBuiltinVaListDecl(Context);
|
|
|
|
case TargetInfo::X86_64ABIBuiltinVaList:
|
|
|
|
return CreateX86_64ABIBuiltinVaListDecl(Context);
|
|
|
|
case TargetInfo::PNaClABIBuiltinVaList:
|
|
|
|
return CreatePNaClABIBuiltinVaListDecl(Context);
|
2012-10-10 14:56:20 +08:00
|
|
|
case TargetInfo::AAPCSABIBuiltinVaList:
|
|
|
|
return CreateAAPCSABIBuiltinVaListDecl(Context);
|
2012-06-16 11:34:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
llvm_unreachable("Unhandled __builtin_va_list type kind");
|
|
|
|
}
|
|
|
|
|
|
|
|
TypedefDecl *ASTContext::getBuiltinVaListDecl() const {
|
|
|
|
if (!BuiltinVaListDecl)
|
|
|
|
BuiltinVaListDecl = CreateVaListDecl(this, Target->getBuiltinVaListKind());
|
|
|
|
|
|
|
|
return BuiltinVaListDecl;
|
|
|
|
}
|
|
|
|
|
2012-07-01 23:57:25 +08:00
|
|
|
QualType ASTContext::getVaListTagType() const {
|
|
|
|
// Force the creation of VaListTagTy by building the __builtin_va_list
|
|
|
|
// declaration.
|
|
|
|
if (VaListTagTy.isNull())
|
|
|
|
(void) getBuiltinVaListDecl();
|
|
|
|
|
|
|
|
return VaListTagTy;
|
|
|
|
}
|
|
|
|
|
2008-01-08 03:49:32 +08:00
|
|
|
void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) {
|
2009-09-09 23:08:12 +08:00
|
|
|
assert(ObjCConstantStringType.isNull() &&
|
2007-10-16 07:35:17 +08:00
|
|
|
"'NSConstantString' type already set!");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-01-08 03:49:32 +08:00
|
|
|
ObjCConstantStringType = getObjCInterfaceType(Decl);
|
2007-10-16 07:35:17 +08:00
|
|
|
}
|
|
|
|
|
2009-12-02 16:04:21 +08:00
|
|
|
/// \brief Retrieve the template name that corresponds to a non-empty
|
|
|
|
/// lookup.
|
2011-01-12 17:06:06 +08:00
|
|
|
TemplateName
|
|
|
|
ASTContext::getOverloadedTemplateName(UnresolvedSetIterator Begin,
|
|
|
|
UnresolvedSetIterator End) const {
|
2009-12-02 16:04:21 +08:00
|
|
|
unsigned size = End - Begin;
|
|
|
|
assert(size > 1 && "set is not overloaded!");
|
2009-03-31 06:58:21 +08:00
|
|
|
|
2009-12-02 16:04:21 +08:00
|
|
|
void *memory = Allocate(sizeof(OverloadedTemplateStorage) +
|
|
|
|
size * sizeof(FunctionTemplateDecl*));
|
|
|
|
OverloadedTemplateStorage *OT = new(memory) OverloadedTemplateStorage(size);
|
|
|
|
|
|
|
|
NamedDecl **Storage = OT->getStorage();
|
2010-01-20 08:46:10 +08:00
|
|
|
for (UnresolvedSetIterator I = Begin; I != End; ++I) {
|
2009-12-02 16:04:21 +08:00
|
|
|
NamedDecl *D = *I;
|
|
|
|
assert(isa<FunctionTemplateDecl>(D) ||
|
|
|
|
(isa<UsingShadowDecl>(D) &&
|
|
|
|
isa<FunctionTemplateDecl>(D->getUnderlyingDecl())));
|
|
|
|
*Storage++ = D;
|
2009-03-31 06:58:21 +08:00
|
|
|
}
|
|
|
|
|
2009-12-02 16:04:21 +08:00
|
|
|
return TemplateName(OT);
|
2009-03-31 06:58:21 +08:00
|
|
|
}
|
|
|
|
|
2009-07-30 02:26:50 +08:00
|
|
|
/// \brief Retrieve the template name that represents a qualified
|
|
|
|
/// template name such as \c std::vector.
|
2011-01-12 17:06:06 +08:00
|
|
|
TemplateName
|
|
|
|
ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS,
|
|
|
|
bool TemplateKeyword,
|
|
|
|
TemplateDecl *Template) const {
|
2011-03-04 01:04:51 +08:00
|
|
|
assert(NNS && "Missing nested-name-specifier in qualified template name");
|
|
|
|
|
Fix an obscure crash found in the Boost.MPL test suite, along with a
ton of potential crashes of the same kind. The fundamental problem is
that type creation was following a dangerous pattern when using its
FoldingSets:
1) Use FindNodeOrInsertPos to see if the type is available
2) If not, and we aren't looking at a canonical type, build the
canonical type
3) Build and insert the new node into the FoldingSet
The problem here is that building the canonical type can, in very rare
circumstances, force the hash table inside the FoldingSet to
reallocate. That invalidates the insertion position we computed in
step 1, and in step 3 we end up inserting the new node into the wrong
place. BOOM!
I've audited all of ASTContext, fixing this problem everywhere I found
it. The vast majority of wrong code was C++-specific (and *ahem*
written by me), so I also audited other major folding sets in the C++
code (e.g., template specializations), but found no other instances of
this problem.
llvm-svn: 95315
2010-02-05 02:10:26 +08:00
|
|
|
// FIXME: Canonicalization?
|
2009-07-30 02:26:50 +08:00
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
QualifiedTemplateName::Profile(ID, NNS, TemplateKeyword, Template);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-30 02:26:50 +08:00
|
|
|
void *InsertPos = 0;
|
|
|
|
QualifiedTemplateName *QTN =
|
2009-12-02 16:04:21 +08:00
|
|
|
QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
|
2009-07-30 02:26:50 +08:00
|
|
|
if (!QTN) {
|
2012-08-16 09:19:31 +08:00
|
|
|
QTN = new (*this, llvm::alignOf<QualifiedTemplateName>())
|
|
|
|
QualifiedTemplateName(NNS, TemplateKeyword, Template);
|
2009-07-30 02:26:50 +08:00
|
|
|
QualifiedTemplateNames.InsertNode(QTN, InsertPos);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-30 02:26:50 +08:00
|
|
|
return TemplateName(QTN);
|
|
|
|
}
|
|
|
|
|
2009-03-31 06:58:21 +08:00
|
|
|
/// \brief Retrieve the template name that represents a dependent
|
|
|
|
/// template name such as \c MetaFun::template apply.
|
2011-01-12 17:06:06 +08:00
|
|
|
TemplateName
|
|
|
|
ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
|
|
|
|
const IdentifierInfo *Name) const {
|
2009-09-09 23:08:12 +08:00
|
|
|
assert((!NNS || NNS->isDependent()) &&
|
2009-09-09 08:23:06 +08:00
|
|
|
"Nested name specifier must be dependent");
|
2009-03-31 06:58:21 +08:00
|
|
|
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
DependentTemplateName::Profile(ID, NNS, Name);
|
|
|
|
|
|
|
|
void *InsertPos = 0;
|
|
|
|
DependentTemplateName *QTN =
|
|
|
|
DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
|
|
|
|
if (QTN)
|
|
|
|
return TemplateName(QTN);
|
|
|
|
|
|
|
|
NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
|
|
|
|
if (CanonNNS == NNS) {
|
2012-08-16 09:19:31 +08:00
|
|
|
QTN = new (*this, llvm::alignOf<DependentTemplateName>())
|
|
|
|
DependentTemplateName(NNS, Name);
|
2009-03-31 06:58:21 +08:00
|
|
|
} else {
|
|
|
|
TemplateName Canon = getDependentTemplateName(CanonNNS, Name);
|
2012-08-16 09:19:31 +08:00
|
|
|
QTN = new (*this, llvm::alignOf<DependentTemplateName>())
|
|
|
|
DependentTemplateName(NNS, Name, Canon);
|
Fix an obscure crash found in the Boost.MPL test suite, along with a
ton of potential crashes of the same kind. The fundamental problem is
that type creation was following a dangerous pattern when using its
FoldingSets:
1) Use FindNodeOrInsertPos to see if the type is available
2) If not, and we aren't looking at a canonical type, build the
canonical type
3) Build and insert the new node into the FoldingSet
The problem here is that building the canonical type can, in very rare
circumstances, force the hash table inside the FoldingSet to
reallocate. That invalidates the insertion position we computed in
step 1, and in step 3 we end up inserting the new node into the wrong
place. BOOM!
I've audited all of ASTContext, fixing this problem everywhere I found
it. The vast majority of wrong code was C++-specific (and *ahem*
written by me), so I also audited other major folding sets in the C++
code (e.g., template specializations), but found no other instances of
this problem.
llvm-svn: 95315
2010-02-05 02:10:26 +08:00
|
|
|
DependentTemplateName *CheckQTN =
|
|
|
|
DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
assert(!CheckQTN && "Dependent type name canonicalization broken");
|
|
|
|
(void)CheckQTN;
|
2009-03-31 06:58:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
DependentTemplateNames.InsertNode(QTN, InsertPos);
|
|
|
|
return TemplateName(QTN);
|
|
|
|
}
|
|
|
|
|
2009-11-04 08:56:37 +08:00
|
|
|
/// \brief Retrieve the template name that represents a dependent
|
|
|
|
/// template name such as \c MetaFun::template operator+.
|
|
|
|
TemplateName
|
|
|
|
ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
|
2011-01-12 17:06:06 +08:00
|
|
|
OverloadedOperatorKind Operator) const {
|
2009-11-04 08:56:37 +08:00
|
|
|
assert((!NNS || NNS->isDependent()) &&
|
|
|
|
"Nested name specifier must be dependent");
|
|
|
|
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
DependentTemplateName::Profile(ID, NNS, Operator);
|
|
|
|
|
|
|
|
void *InsertPos = 0;
|
Fix an obscure crash found in the Boost.MPL test suite, along with a
ton of potential crashes of the same kind. The fundamental problem is
that type creation was following a dangerous pattern when using its
FoldingSets:
1) Use FindNodeOrInsertPos to see if the type is available
2) If not, and we aren't looking at a canonical type, build the
canonical type
3) Build and insert the new node into the FoldingSet
The problem here is that building the canonical type can, in very rare
circumstances, force the hash table inside the FoldingSet to
reallocate. That invalidates the insertion position we computed in
step 1, and in step 3 we end up inserting the new node into the wrong
place. BOOM!
I've audited all of ASTContext, fixing this problem everywhere I found
it. The vast majority of wrong code was C++-specific (and *ahem*
written by me), so I also audited other major folding sets in the C++
code (e.g., template specializations), but found no other instances of
this problem.
llvm-svn: 95315
2010-02-05 02:10:26 +08:00
|
|
|
DependentTemplateName *QTN
|
|
|
|
= DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
|
2009-11-04 08:56:37 +08:00
|
|
|
|
|
|
|
if (QTN)
|
|
|
|
return TemplateName(QTN);
|
|
|
|
|
|
|
|
NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
|
|
|
|
if (CanonNNS == NNS) {
|
2012-08-16 09:19:31 +08:00
|
|
|
QTN = new (*this, llvm::alignOf<DependentTemplateName>())
|
|
|
|
DependentTemplateName(NNS, Operator);
|
2009-11-04 08:56:37 +08:00
|
|
|
} else {
|
|
|
|
TemplateName Canon = getDependentTemplateName(CanonNNS, Operator);
|
2012-08-16 09:19:31 +08:00
|
|
|
QTN = new (*this, llvm::alignOf<DependentTemplateName>())
|
|
|
|
DependentTemplateName(NNS, Operator, Canon);
|
Fix an obscure crash found in the Boost.MPL test suite, along with a
ton of potential crashes of the same kind. The fundamental problem is
that type creation was following a dangerous pattern when using its
FoldingSets:
1) Use FindNodeOrInsertPos to see if the type is available
2) If not, and we aren't looking at a canonical type, build the
canonical type
3) Build and insert the new node into the FoldingSet
The problem here is that building the canonical type can, in very rare
circumstances, force the hash table inside the FoldingSet to
reallocate. That invalidates the insertion position we computed in
step 1, and in step 3 we end up inserting the new node into the wrong
place. BOOM!
I've audited all of ASTContext, fixing this problem everywhere I found
it. The vast majority of wrong code was C++-specific (and *ahem*
written by me), so I also audited other major folding sets in the C++
code (e.g., template specializations), but found no other instances of
this problem.
llvm-svn: 95315
2010-02-05 02:10:26 +08:00
|
|
|
|
|
|
|
DependentTemplateName *CheckQTN
|
|
|
|
= DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
assert(!CheckQTN && "Dependent template name canonicalization broken");
|
|
|
|
(void)CheckQTN;
|
2009-11-04 08:56:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
DependentTemplateNames.InsertNode(QTN, InsertPos);
|
|
|
|
return TemplateName(QTN);
|
|
|
|
}
|
|
|
|
|
2011-06-30 16:33:18 +08:00
|
|
|
TemplateName
|
|
|
|
ASTContext::getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param,
|
|
|
|
TemplateName replacement) const {
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
SubstTemplateTemplateParmStorage::Profile(ID, param, replacement);
|
|
|
|
|
|
|
|
void *insertPos = 0;
|
|
|
|
SubstTemplateTemplateParmStorage *subst
|
|
|
|
= SubstTemplateTemplateParms.FindNodeOrInsertPos(ID, insertPos);
|
|
|
|
|
|
|
|
if (!subst) {
|
|
|
|
subst = new (*this) SubstTemplateTemplateParmStorage(param, replacement);
|
|
|
|
SubstTemplateTemplateParms.InsertNode(subst, insertPos);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TemplateName(subst);
|
|
|
|
}
|
|
|
|
|
2011-01-15 14:45:20 +08:00
|
|
|
TemplateName
|
|
|
|
ASTContext::getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param,
|
|
|
|
const TemplateArgument &ArgPack) const {
|
|
|
|
ASTContext &Self = const_cast<ASTContext &>(*this);
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
SubstTemplateTemplateParmPackStorage::Profile(ID, Self, Param, ArgPack);
|
|
|
|
|
|
|
|
void *InsertPos = 0;
|
|
|
|
SubstTemplateTemplateParmPackStorage *Subst
|
|
|
|
= SubstTemplateTemplateParmPacks.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
|
|
|
|
if (!Subst) {
|
2011-06-30 16:33:18 +08:00
|
|
|
Subst = new (*this) SubstTemplateTemplateParmPackStorage(Param,
|
2011-01-15 14:45:20 +08:00
|
|
|
ArgPack.pack_size(),
|
|
|
|
ArgPack.pack_begin());
|
|
|
|
SubstTemplateTemplateParmPacks.InsertNode(Subst, InsertPos);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TemplateName(Subst);
|
|
|
|
}
|
|
|
|
|
2008-11-03 22:12:49 +08:00
|
|
|
/// getFromTargetType - Given one of the integer types provided by
|
2008-11-03 23:57:00 +08:00
|
|
|
/// TargetInfo, produce the corresponding type. The unsigned @p Type
|
|
|
|
/// is actually a value of type @c TargetInfo::IntType.
|
2009-10-24 07:03:21 +08:00
|
|
|
CanQualType ASTContext::getFromTargetType(unsigned Type) const {
|
2008-11-03 22:12:49 +08:00
|
|
|
switch (Type) {
|
2009-10-24 07:03:21 +08:00
|
|
|
case TargetInfo::NoInt: return CanQualType();
|
2008-11-03 22:12:49 +08:00
|
|
|
case TargetInfo::SignedShort: return ShortTy;
|
|
|
|
case TargetInfo::UnsignedShort: return UnsignedShortTy;
|
|
|
|
case TargetInfo::SignedInt: return IntTy;
|
|
|
|
case TargetInfo::UnsignedInt: return UnsignedIntTy;
|
|
|
|
case TargetInfo::SignedLong: return LongTy;
|
|
|
|
case TargetInfo::UnsignedLong: return UnsignedLongTy;
|
|
|
|
case TargetInfo::SignedLongLong: return LongLongTy;
|
|
|
|
case TargetInfo::UnsignedLongLong: return UnsignedLongLongTy;
|
|
|
|
}
|
|
|
|
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("Unhandled TargetInfo::IntType value");
|
2008-11-03 22:12:49 +08:00
|
|
|
}
|
2008-07-25 07:58:27 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Type Predicates.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-02-19 05:49:28 +08:00
|
|
|
/// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's
|
|
|
|
/// garbage collection attribute.
|
|
|
|
///
|
2011-01-12 08:34:59 +08:00
|
|
|
Qualifiers::GC ASTContext::getObjCGCAttrKind(QualType Ty) const {
|
2012-03-11 15:00:24 +08:00
|
|
|
if (getLangOpts().getGC() == LangOptions::NonGC)
|
2011-01-12 08:34:59 +08:00
|
|
|
return Qualifiers::GCNone;
|
|
|
|
|
2012-03-11 15:00:24 +08:00
|
|
|
assert(getLangOpts().ObjC1);
|
2011-01-12 08:34:59 +08:00
|
|
|
Qualifiers::GC GCAttrs = Ty.getObjCGCAttr();
|
|
|
|
|
|
|
|
// Default behaviour under objective-C's gc is for ObjC pointers
|
|
|
|
// (or pointers to them) be treated as though they were declared
|
|
|
|
// as __strong.
|
|
|
|
if (GCAttrs == Qualifiers::GCNone) {
|
|
|
|
if (Ty->isObjCObjectPointerType() || Ty->isBlockPointerType())
|
|
|
|
return Qualifiers::Strong;
|
|
|
|
else if (Ty->isPointerType())
|
|
|
|
return getObjCGCAttrKind(Ty->getAs<PointerType>()->getPointeeType());
|
|
|
|
} else {
|
|
|
|
// It's not valid to set GC attributes on anything that isn't a
|
|
|
|
// pointer.
|
|
|
|
#ifndef NDEBUG
|
|
|
|
QualType CT = Ty->getCanonicalTypeInternal();
|
|
|
|
while (const ArrayType *AT = dyn_cast<ArrayType>(CT))
|
|
|
|
CT = AT->getElementType();
|
|
|
|
assert(CT->isAnyPointerType() || CT->isBlockPointerType());
|
|
|
|
#endif
|
2009-02-19 05:49:28 +08:00
|
|
|
}
|
2009-02-19 06:53:11 +08:00
|
|
|
return GCAttrs;
|
2009-02-19 05:49:28 +08:00
|
|
|
}
|
|
|
|
|
2008-04-07 14:51:04 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Type Compatibility Testing
|
|
|
|
//===----------------------------------------------------------------------===//
|
2007-11-01 13:03:41 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
/// areCompatVectorTypes - Return true if the two specified vector types are
|
2008-04-07 14:51:04 +08:00
|
|
|
/// compatible.
|
|
|
|
static bool areCompatVectorTypes(const VectorType *LHS,
|
|
|
|
const VectorType *RHS) {
|
2009-10-23 04:10:53 +08:00
|
|
|
assert(LHS->isCanonicalUnqualified() && RHS->isCanonicalUnqualified());
|
2008-04-07 14:51:04 +08:00
|
|
|
return LHS->getElementType() == RHS->getElementType() &&
|
2008-10-06 01:34:18 +08:00
|
|
|
LHS->getNumElements() == RHS->getNumElements();
|
2008-04-07 14:51:04 +08:00
|
|
|
}
|
|
|
|
|
2010-08-06 18:14:59 +08:00
|
|
|
bool ASTContext::areCompatibleVectorTypes(QualType FirstVec,
|
|
|
|
QualType SecondVec) {
|
|
|
|
assert(FirstVec->isVectorType() && "FirstVec should be a vector type");
|
|
|
|
assert(SecondVec->isVectorType() && "SecondVec should be a vector type");
|
|
|
|
|
|
|
|
if (hasSameUnqualifiedType(FirstVec, SecondVec))
|
|
|
|
return true;
|
|
|
|
|
2010-11-13 01:24:54 +08:00
|
|
|
// Treat Neon vector types and most AltiVec vector types as if they are the
|
|
|
|
// equivalent GCC vector types.
|
2010-08-06 18:14:59 +08:00
|
|
|
const VectorType *First = FirstVec->getAs<VectorType>();
|
|
|
|
const VectorType *Second = SecondVec->getAs<VectorType>();
|
2010-11-13 01:24:54 +08:00
|
|
|
if (First->getNumElements() == Second->getNumElements() &&
|
2010-08-06 18:14:59 +08:00
|
|
|
hasSameType(First->getElementType(), Second->getElementType()) &&
|
2010-11-13 01:24:54 +08:00
|
|
|
First->getVectorKind() != VectorType::AltiVecPixel &&
|
|
|
|
First->getVectorKind() != VectorType::AltiVecBool &&
|
|
|
|
Second->getVectorKind() != VectorType::AltiVecPixel &&
|
|
|
|
Second->getVectorKind() != VectorType::AltiVecBool)
|
2010-08-06 18:14:59 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-07-23 09:01:38 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// ProtocolCompatibleWithProtocol - return 'true' if 'lProto' is in the
|
|
|
|
/// inheritance hierarchy of 'rProto'.
|
2011-01-12 17:06:06 +08:00
|
|
|
bool
|
|
|
|
ASTContext::ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto,
|
|
|
|
ObjCProtocolDecl *rProto) const {
|
2012-01-02 02:09:12 +08:00
|
|
|
if (declaresSameEntity(lProto, rProto))
|
2009-07-11 07:34:53 +08:00
|
|
|
return true;
|
2009-07-23 09:01:38 +08:00
|
|
|
for (ObjCProtocolDecl::protocol_iterator PI = rProto->protocol_begin(),
|
|
|
|
E = rProto->protocol_end(); PI != E; ++PI)
|
|
|
|
if (ProtocolCompatibleWithProtocol(lProto, *PI))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
2009-07-11 07:34:53 +08:00
|
|
|
|
2012-08-28 10:49:14 +08:00
|
|
|
/// QualifiedIdConformsQualifiedId - compare id<pr,...> with id<pr1,...>
|
2009-07-23 09:01:38 +08:00
|
|
|
/// return true if lhs's protocols conform to rhs's protocol; false
|
|
|
|
/// otherwise.
|
|
|
|
bool ASTContext::QualifiedIdConformsQualifiedId(QualType lhs, QualType rhs) {
|
|
|
|
if (lhs->isObjCQualifiedIdType() && rhs->isObjCQualifiedIdType())
|
|
|
|
return ObjCQualifiedIdTypesAreCompatible(lhs, rhs, false);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-08-28 10:49:14 +08:00
|
|
|
/// ObjCQualifiedClassTypesAreCompatible - compare Class<pr,...> and
|
|
|
|
/// Class<pr1, ...>.
|
2010-07-20 06:02:22 +08:00
|
|
|
bool ASTContext::ObjCQualifiedClassTypesAreCompatible(QualType lhs,
|
|
|
|
QualType rhs) {
|
|
|
|
const ObjCObjectPointerType *lhsQID = lhs->getAs<ObjCObjectPointerType>();
|
|
|
|
const ObjCObjectPointerType *rhsOPT = rhs->getAs<ObjCObjectPointerType>();
|
|
|
|
assert ((lhsQID && rhsOPT) && "ObjCQualifiedClassTypesAreCompatible");
|
|
|
|
|
|
|
|
for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
|
|
|
|
E = lhsQID->qual_end(); I != E; ++I) {
|
|
|
|
bool match = false;
|
|
|
|
ObjCProtocolDecl *lhsProto = *I;
|
|
|
|
for (ObjCObjectPointerType::qual_iterator J = rhsOPT->qual_begin(),
|
|
|
|
E = rhsOPT->qual_end(); J != E; ++J) {
|
|
|
|
ObjCProtocolDecl *rhsProto = *J;
|
|
|
|
if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto)) {
|
|
|
|
match = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!match)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-07-23 09:01:38 +08:00
|
|
|
/// ObjCQualifiedIdTypesAreCompatible - We know that one of lhs/rhs is an
|
|
|
|
/// ObjCQualifiedIDType.
|
|
|
|
bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
|
|
|
|
bool compare) {
|
|
|
|
// Allow id<P..> and an 'id' or void* type in all cases.
|
2009-09-09 23:08:12 +08:00
|
|
|
if (lhs->isVoidPointerType() ||
|
2009-07-23 09:01:38 +08:00
|
|
|
lhs->isObjCIdType() || lhs->isObjCClassType())
|
|
|
|
return true;
|
2009-09-09 23:08:12 +08:00
|
|
|
else if (rhs->isVoidPointerType() ||
|
2009-07-23 09:01:38 +08:00
|
|
|
rhs->isObjCIdType() || rhs->isObjCClassType())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (const ObjCObjectPointerType *lhsQID = lhs->getAsObjCQualifiedIdType()) {
|
2009-09-22 07:43:11 +08:00
|
|
|
const ObjCObjectPointerType *rhsOPT = rhs->getAs<ObjCObjectPointerType>();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-23 09:01:38 +08:00
|
|
|
if (!rhsOPT) return false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-23 09:01:38 +08:00
|
|
|
if (rhsOPT->qual_empty()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
// If the RHS is a unqualified interface pointer "NSString*",
|
2009-07-23 09:01:38 +08:00
|
|
|
// make sure we check the class hierarchy.
|
|
|
|
if (ObjCInterfaceDecl *rhsID = rhsOPT->getInterfaceDecl()) {
|
|
|
|
for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
|
|
|
|
E = lhsQID->qual_end(); I != E; ++I) {
|
|
|
|
// when comparing an id<P> on lhs with a static type on rhs,
|
|
|
|
// see if static class implements all of id's protocols, directly or
|
|
|
|
// through its super class and categories.
|
2009-08-12 06:02:25 +08:00
|
|
|
if (!rhsID->ClassImplementsProtocol(*I, true))
|
2009-07-23 09:01:38 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If there are no qualifiers and no interface, we have an 'id'.
|
|
|
|
return true;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
// Both the right and left sides have qualifiers.
|
2009-07-23 09:01:38 +08:00
|
|
|
for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
|
|
|
|
E = lhsQID->qual_end(); I != E; ++I) {
|
|
|
|
ObjCProtocolDecl *lhsProto = *I;
|
|
|
|
bool match = false;
|
2009-07-16 02:40:39 +08:00
|
|
|
|
|
|
|
// when comparing an id<P> on lhs with a static type on rhs,
|
|
|
|
// see if static class implements all of id's protocols, directly or
|
|
|
|
// through its super class and categories.
|
2009-07-23 09:01:38 +08:00
|
|
|
for (ObjCObjectPointerType::qual_iterator J = rhsOPT->qual_begin(),
|
|
|
|
E = rhsOPT->qual_end(); J != E; ++J) {
|
|
|
|
ObjCProtocolDecl *rhsProto = *J;
|
|
|
|
if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
|
|
|
|
(compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) {
|
|
|
|
match = true;
|
2009-07-17 00:21:02 +08:00
|
|
|
break;
|
|
|
|
}
|
2009-07-16 02:40:39 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
// If the RHS is a qualified interface pointer "NSString<P>*",
|
2009-07-23 09:01:38 +08:00
|
|
|
// make sure we check the class hierarchy.
|
|
|
|
if (ObjCInterfaceDecl *rhsID = rhsOPT->getInterfaceDecl()) {
|
|
|
|
for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
|
|
|
|
E = lhsQID->qual_end(); I != E; ++I) {
|
|
|
|
// when comparing an id<P> on lhs with a static type on rhs,
|
|
|
|
// see if static class implements all of id's protocols, directly or
|
|
|
|
// through its super class and categories.
|
2009-08-12 06:02:25 +08:00
|
|
|
if (rhsID->ClassImplementsProtocol(*I, true)) {
|
2009-07-23 09:01:38 +08:00
|
|
|
match = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!match)
|
2009-07-16 02:40:39 +08:00
|
|
|
return false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-16 02:40:39 +08:00
|
|
|
return true;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-23 09:01:38 +08:00
|
|
|
const ObjCObjectPointerType *rhsQID = rhs->getAsObjCQualifiedIdType();
|
|
|
|
assert(rhsQID && "One of the LHS/RHS should be id<x>");
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
if (const ObjCObjectPointerType *lhsOPT =
|
2009-07-23 09:01:38 +08:00
|
|
|
lhs->getAsObjCInterfacePointerType()) {
|
2010-11-02 04:47:16 +08:00
|
|
|
// If both the right and left sides have qualifiers.
|
2009-07-23 09:01:38 +08:00
|
|
|
for (ObjCObjectPointerType::qual_iterator I = lhsOPT->qual_begin(),
|
|
|
|
E = lhsOPT->qual_end(); I != E; ++I) {
|
|
|
|
ObjCProtocolDecl *lhsProto = *I;
|
|
|
|
bool match = false;
|
|
|
|
|
2010-11-02 04:47:16 +08:00
|
|
|
// when comparing an id<P> on rhs with a static type on lhs,
|
2009-07-23 09:01:38 +08:00
|
|
|
// see if static class implements all of id's protocols, directly or
|
|
|
|
// through its super class and categories.
|
2010-11-02 04:47:16 +08:00
|
|
|
// First, lhs protocols in the qualifier list must be found, direct
|
|
|
|
// or indirect in rhs's qualifier list or it is a mismatch.
|
2009-07-23 09:01:38 +08:00
|
|
|
for (ObjCObjectPointerType::qual_iterator J = rhsQID->qual_begin(),
|
|
|
|
E = rhsQID->qual_end(); J != E; ++J) {
|
|
|
|
ObjCProtocolDecl *rhsProto = *J;
|
|
|
|
if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
|
|
|
|
(compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) {
|
|
|
|
match = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!match)
|
|
|
|
return false;
|
|
|
|
}
|
2010-11-02 04:47:16 +08:00
|
|
|
|
|
|
|
// Static class's protocols, or its super class or category protocols
|
|
|
|
// must be found, direct or indirect in rhs's qualifier list or it is a mismatch.
|
|
|
|
if (ObjCInterfaceDecl *lhsID = lhsOPT->getInterfaceDecl()) {
|
|
|
|
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> LHSInheritedProtocols;
|
|
|
|
CollectInheritedProtocols(lhsID, LHSInheritedProtocols);
|
|
|
|
// This is rather dubious but matches gcc's behavior. If lhs has
|
|
|
|
// no type qualifier and its class has no static protocol(s)
|
|
|
|
// assume that it is mismatch.
|
|
|
|
if (LHSInheritedProtocols.empty() && lhsOPT->qual_empty())
|
|
|
|
return false;
|
|
|
|
for (llvm::SmallPtrSet<ObjCProtocolDecl*,8>::iterator I =
|
|
|
|
LHSInheritedProtocols.begin(),
|
|
|
|
E = LHSInheritedProtocols.end(); I != E; ++I) {
|
|
|
|
bool match = false;
|
|
|
|
ObjCProtocolDecl *lhsProto = (*I);
|
|
|
|
for (ObjCObjectPointerType::qual_iterator J = rhsQID->qual_begin(),
|
|
|
|
E = rhsQID->qual_end(); J != E; ++J) {
|
|
|
|
ObjCProtocolDecl *rhsProto = *J;
|
|
|
|
if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
|
|
|
|
(compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) {
|
|
|
|
match = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!match)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2009-07-23 09:01:38 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// canAssignObjCInterfaces - Return true if the two interface types are
|
|
|
|
/// compatible for assignment from RHS to LHS. This handles validation of any
|
|
|
|
/// protocol qualifiers on the LHS or RHS.
|
|
|
|
///
|
|
|
|
bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
|
|
|
|
const ObjCObjectPointerType *RHSOPT) {
|
2010-05-15 19:32:37 +08:00
|
|
|
const ObjCObjectType* LHS = LHSOPT->getObjectType();
|
|
|
|
const ObjCObjectType* RHS = RHSOPT->getObjectType();
|
|
|
|
|
2009-07-23 09:01:38 +08:00
|
|
|
// If either type represents the built-in 'id' or 'Class' types, return true.
|
2010-05-15 19:32:37 +08:00
|
|
|
if (LHS->isObjCUnqualifiedIdOrClass() ||
|
|
|
|
RHS->isObjCUnqualifiedIdOrClass())
|
2009-07-23 09:01:38 +08:00
|
|
|
return true;
|
|
|
|
|
2010-05-15 19:32:37 +08:00
|
|
|
if (LHS->isObjCQualifiedId() || RHS->isObjCQualifiedId())
|
2009-09-09 23:08:12 +08:00
|
|
|
return ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0),
|
|
|
|
QualType(RHSOPT,0),
|
2009-07-23 09:01:38 +08:00
|
|
|
false);
|
2010-07-20 06:02:22 +08:00
|
|
|
|
|
|
|
if (LHS->isObjCQualifiedClass() && RHS->isObjCQualifiedClass())
|
|
|
|
return ObjCQualifiedClassTypesAreCompatible(QualType(LHSOPT,0),
|
|
|
|
QualType(RHSOPT,0));
|
|
|
|
|
2010-05-15 19:32:37 +08:00
|
|
|
// If we have 2 user-defined types, fall into that path.
|
|
|
|
if (LHS->getInterface() && RHS->getInterface())
|
2009-07-23 09:01:38 +08:00
|
|
|
return canAssignObjCInterfaces(LHS, RHS);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-23 09:01:38 +08:00
|
|
|
return false;
|
2009-07-11 07:34:53 +08:00
|
|
|
}
|
|
|
|
|
2010-03-17 08:20:01 +08:00
|
|
|
/// canAssignObjCInterfacesInBlockPointer - This routine is specifically written
|
2011-04-15 13:22:18 +08:00
|
|
|
/// for providing type-safety for objective-c pointers used to pass/return
|
2010-03-17 08:20:01 +08:00
|
|
|
/// arguments in block literals. When passed as arguments, passing 'A*' where
|
|
|
|
/// 'id' is expected is not OK. Passing 'Sub *" where 'Super *" is expected is
|
|
|
|
/// not OK. For the return type, the opposite is not OK.
|
|
|
|
bool ASTContext::canAssignObjCInterfacesInBlockPointer(
|
|
|
|
const ObjCObjectPointerType *LHSOPT,
|
2011-03-15 00:07:00 +08:00
|
|
|
const ObjCObjectPointerType *RHSOPT,
|
|
|
|
bool BlockReturnType) {
|
2010-04-07 01:23:39 +08:00
|
|
|
if (RHSOPT->isObjCBuiltinType() || LHSOPT->isObjCIdType())
|
2010-03-17 08:20:01 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
if (LHSOPT->isObjCBuiltinType()) {
|
|
|
|
return RHSOPT->isObjCBuiltinType() || RHSOPT->isObjCQualifiedIdType();
|
|
|
|
}
|
|
|
|
|
2010-04-07 01:23:39 +08:00
|
|
|
if (LHSOPT->isObjCQualifiedIdType() || RHSOPT->isObjCQualifiedIdType())
|
2010-03-17 08:20:01 +08:00
|
|
|
return ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0),
|
|
|
|
QualType(RHSOPT,0),
|
|
|
|
false);
|
|
|
|
|
|
|
|
const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
|
|
|
|
const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
|
|
|
|
if (LHS && RHS) { // We have 2 user-defined types.
|
|
|
|
if (LHS != RHS) {
|
|
|
|
if (LHS->getDecl()->isSuperClassOf(RHS->getDecl()))
|
2011-03-15 00:07:00 +08:00
|
|
|
return BlockReturnType;
|
2010-03-17 08:20:01 +08:00
|
|
|
if (RHS->getDecl()->isSuperClassOf(LHS->getDecl()))
|
2011-03-15 00:07:00 +08:00
|
|
|
return !BlockReturnType;
|
2010-03-17 08:20:01 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-10-30 09:13:23 +08:00
|
|
|
/// getIntersectionOfProtocols - This routine finds the intersection of set
|
|
|
|
/// of protocols inherited from two distinct objective-c pointer objects.
|
|
|
|
/// It is used to build composite qualifier list of the composite type of
|
|
|
|
/// the conditional expression involving two objective-c pointer objects.
|
|
|
|
static
|
|
|
|
void getIntersectionOfProtocols(ASTContext &Context,
|
|
|
|
const ObjCObjectPointerType *LHSOPT,
|
|
|
|
const ObjCObjectPointerType *RHSOPT,
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVectorImpl<ObjCProtocolDecl *> &IntersectionOfProtocols) {
|
2009-10-30 09:13:23 +08:00
|
|
|
|
2010-05-15 19:32:37 +08:00
|
|
|
const ObjCObjectType* LHS = LHSOPT->getObjectType();
|
|
|
|
const ObjCObjectType* RHS = RHSOPT->getObjectType();
|
|
|
|
assert(LHS->getInterface() && "LHS must have an interface base");
|
|
|
|
assert(RHS->getInterface() && "RHS must have an interface base");
|
2009-10-30 09:13:23 +08:00
|
|
|
|
|
|
|
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> InheritedProtocolSet;
|
|
|
|
unsigned LHSNumProtocols = LHS->getNumProtocols();
|
|
|
|
if (LHSNumProtocols > 0)
|
|
|
|
InheritedProtocolSet.insert(LHS->qual_begin(), LHS->qual_end());
|
|
|
|
else {
|
2010-02-13 03:27:33 +08:00
|
|
|
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> LHSInheritedProtocols;
|
2010-05-15 19:32:37 +08:00
|
|
|
Context.CollectInheritedProtocols(LHS->getInterface(),
|
|
|
|
LHSInheritedProtocols);
|
2009-10-30 09:13:23 +08:00
|
|
|
InheritedProtocolSet.insert(LHSInheritedProtocols.begin(),
|
|
|
|
LHSInheritedProtocols.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned RHSNumProtocols = RHS->getNumProtocols();
|
|
|
|
if (RHSNumProtocols > 0) {
|
2010-04-20 00:39:44 +08:00
|
|
|
ObjCProtocolDecl **RHSProtocols =
|
|
|
|
const_cast<ObjCProtocolDecl **>(RHS->qual_begin());
|
2009-10-30 09:13:23 +08:00
|
|
|
for (unsigned i = 0; i < RHSNumProtocols; ++i)
|
|
|
|
if (InheritedProtocolSet.count(RHSProtocols[i]))
|
|
|
|
IntersectionOfProtocols.push_back(RHSProtocols[i]);
|
2011-08-18 07:08:45 +08:00
|
|
|
} else {
|
2010-02-13 03:27:33 +08:00
|
|
|
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> RHSInheritedProtocols;
|
2010-05-15 19:32:37 +08:00
|
|
|
Context.CollectInheritedProtocols(RHS->getInterface(),
|
|
|
|
RHSInheritedProtocols);
|
2010-02-13 03:27:33 +08:00
|
|
|
for (llvm::SmallPtrSet<ObjCProtocolDecl*,8>::iterator I =
|
|
|
|
RHSInheritedProtocols.begin(),
|
|
|
|
E = RHSInheritedProtocols.end(); I != E; ++I)
|
|
|
|
if (InheritedProtocolSet.count((*I)))
|
|
|
|
IntersectionOfProtocols.push_back((*I));
|
2009-10-30 09:13:23 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-28 07:02:38 +08:00
|
|
|
/// areCommonBaseCompatible - Returns common base class of the two classes if
|
|
|
|
/// one found. Note that this is O'2 algorithm. But it will be called as the
|
|
|
|
/// last type comparison in a ?-exp of ObjC pointer types before a
|
|
|
|
/// warning is issued. So, its invokation is extremely rare.
|
|
|
|
QualType ASTContext::areCommonBaseCompatible(
|
2010-05-15 19:32:37 +08:00
|
|
|
const ObjCObjectPointerType *Lptr,
|
|
|
|
const ObjCObjectPointerType *Rptr) {
|
|
|
|
const ObjCObjectType *LHS = Lptr->getObjectType();
|
|
|
|
const ObjCObjectType *RHS = Rptr->getObjectType();
|
|
|
|
const ObjCInterfaceDecl* LDecl = LHS->getInterface();
|
|
|
|
const ObjCInterfaceDecl* RDecl = RHS->getInterface();
|
2011-12-15 08:29:59 +08:00
|
|
|
if (!LDecl || !RDecl || (declaresSameEntity(LDecl, RDecl)))
|
2009-10-28 07:02:38 +08:00
|
|
|
return QualType();
|
|
|
|
|
2011-04-19 05:16:59 +08:00
|
|
|
do {
|
2010-05-15 19:32:37 +08:00
|
|
|
LHS = cast<ObjCInterfaceType>(getObjCInterfaceType(LDecl));
|
2009-10-30 09:13:23 +08:00
|
|
|
if (canAssignObjCInterfaces(LHS, RHS)) {
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<ObjCProtocolDecl *, 8> Protocols;
|
2010-05-15 19:32:37 +08:00
|
|
|
getIntersectionOfProtocols(*this, Lptr, Rptr, Protocols);
|
|
|
|
|
|
|
|
QualType Result = QualType(LHS, 0);
|
|
|
|
if (!Protocols.empty())
|
|
|
|
Result = getObjCObjectType(Result, Protocols.data(), Protocols.size());
|
|
|
|
Result = getObjCObjectPointerType(Result);
|
|
|
|
return Result;
|
2009-10-30 09:13:23 +08:00
|
|
|
}
|
2011-04-19 05:16:59 +08:00
|
|
|
} while ((LDecl = LDecl->getSuperClass()));
|
2009-10-28 07:02:38 +08:00
|
|
|
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2010-05-15 19:32:37 +08:00
|
|
|
bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS,
|
|
|
|
const ObjCObjectType *RHS) {
|
|
|
|
assert(LHS->getInterface() && "LHS is not an interface type");
|
|
|
|
assert(RHS->getInterface() && "RHS is not an interface type");
|
|
|
|
|
2008-04-07 14:51:04 +08:00
|
|
|
// Verify that the base decls are compatible: the RHS must be a subclass of
|
|
|
|
// the LHS.
|
2010-05-15 19:32:37 +08:00
|
|
|
if (!LHS->getInterface()->isSuperClassOf(RHS->getInterface()))
|
2008-04-07 14:51:04 +08:00
|
|
|
return false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-04-07 14:51:04 +08:00
|
|
|
// RHS must have a superset of the protocols in the LHS. If the LHS is not
|
|
|
|
// protocol qualified at all, then we are good.
|
2009-07-18 23:33:26 +08:00
|
|
|
if (LHS->getNumProtocols() == 0)
|
2008-04-07 14:51:04 +08:00
|
|
|
return true;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-04-09 02:25:29 +08:00
|
|
|
// Okay, we know the LHS has protocol qualifiers. If the RHS doesn't,
|
|
|
|
// more detailed analysis is required.
|
|
|
|
if (RHS->getNumProtocols() == 0) {
|
|
|
|
// OK, if LHS is a superclass of RHS *and*
|
|
|
|
// this superclass is assignment compatible with LHS.
|
|
|
|
// false otherwise.
|
2011-04-13 00:34:14 +08:00
|
|
|
bool IsSuperClass =
|
|
|
|
LHS->getInterface()->isSuperClassOf(RHS->getInterface());
|
|
|
|
if (IsSuperClass) {
|
2011-04-09 02:25:29 +08:00
|
|
|
// OK if conversion of LHS to SuperClass results in narrowing of types
|
|
|
|
// ; i.e., SuperClass may implement at least one of the protocols
|
|
|
|
// in LHS's protocol list. Example, SuperObj<P1> = lhs<P1,P2> is ok.
|
|
|
|
// But not SuperObj<P1,P2,P3> = lhs<P1,P2>.
|
|
|
|
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> SuperClassInheritedProtocols;
|
2011-04-13 00:34:14 +08:00
|
|
|
CollectInheritedProtocols(RHS->getInterface(), SuperClassInheritedProtocols);
|
2011-04-09 02:25:29 +08:00
|
|
|
// If super class has no protocols, it is not a match.
|
|
|
|
if (SuperClassInheritedProtocols.empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (ObjCObjectType::qual_iterator LHSPI = LHS->qual_begin(),
|
|
|
|
LHSPE = LHS->qual_end();
|
|
|
|
LHSPI != LHSPE; LHSPI++) {
|
|
|
|
bool SuperImplementsProtocol = false;
|
|
|
|
ObjCProtocolDecl *LHSProto = (*LHSPI);
|
|
|
|
|
|
|
|
for (llvm::SmallPtrSet<ObjCProtocolDecl*,8>::iterator I =
|
|
|
|
SuperClassInheritedProtocols.begin(),
|
|
|
|
E = SuperClassInheritedProtocols.end(); I != E; ++I) {
|
|
|
|
ObjCProtocolDecl *SuperClassProto = (*I);
|
|
|
|
if (SuperClassProto->lookupProtocolNamed(LHSProto->getIdentifier())) {
|
|
|
|
SuperImplementsProtocol = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!SuperImplementsProtocol)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-05-15 19:32:37 +08:00
|
|
|
for (ObjCObjectType::qual_iterator LHSPI = LHS->qual_begin(),
|
|
|
|
LHSPE = LHS->qual_end();
|
2009-03-02 00:12:44 +08:00
|
|
|
LHSPI != LHSPE; LHSPI++) {
|
|
|
|
bool RHSImplementsProtocol = false;
|
|
|
|
|
|
|
|
// If the RHS doesn't implement the protocol on the left, the types
|
|
|
|
// are incompatible.
|
2010-05-15 19:32:37 +08:00
|
|
|
for (ObjCObjectType::qual_iterator RHSPI = RHS->qual_begin(),
|
|
|
|
RHSPE = RHS->qual_end();
|
2009-07-17 00:21:02 +08:00
|
|
|
RHSPI != RHSPE; RHSPI++) {
|
|
|
|
if ((*RHSPI)->lookupProtocolNamed((*LHSPI)->getIdentifier())) {
|
2009-03-02 00:12:44 +08:00
|
|
|
RHSImplementsProtocol = true;
|
2009-07-17 00:21:02 +08:00
|
|
|
break;
|
|
|
|
}
|
2009-03-02 00:12:44 +08:00
|
|
|
}
|
|
|
|
// FIXME: For better diagnostics, consider passing back the protocol name.
|
|
|
|
if (!RHSImplementsProtocol)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// The RHS implements all protocols listed on the LHS.
|
|
|
|
return true;
|
2008-04-07 14:51:04 +08:00
|
|
|
}
|
|
|
|
|
2009-02-13 01:52:19 +08:00
|
|
|
bool ASTContext::areComparableObjCPointerTypes(QualType LHS, QualType RHS) {
|
|
|
|
// get the "pointed to" types
|
2009-09-22 07:43:11 +08:00
|
|
|
const ObjCObjectPointerType *LHSOPT = LHS->getAs<ObjCObjectPointerType>();
|
|
|
|
const ObjCObjectPointerType *RHSOPT = RHS->getAs<ObjCObjectPointerType>();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-11 07:34:53 +08:00
|
|
|
if (!LHSOPT || !RHSOPT)
|
2009-02-13 01:52:19 +08:00
|
|
|
return false;
|
2009-07-11 07:34:53 +08:00
|
|
|
|
|
|
|
return canAssignObjCInterfaces(LHSOPT, RHSOPT) ||
|
|
|
|
canAssignObjCInterfaces(RHSOPT, LHSOPT);
|
2009-02-13 01:52:19 +08:00
|
|
|
}
|
|
|
|
|
2010-08-07 19:51:51 +08:00
|
|
|
bool ASTContext::canBindObjCObjectType(QualType To, QualType From) {
|
|
|
|
return canAssignObjCInterfaces(
|
|
|
|
getObjCObjectPointerType(To)->getAs<ObjCObjectPointerType>(),
|
|
|
|
getObjCObjectPointerType(From)->getAs<ObjCObjectPointerType>());
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
/// typesAreCompatible - C99 6.7.3p9: For two qualified types to be compatible,
|
2007-10-16 04:41:53 +08:00
|
|
|
/// both shall have the identically qualified version of a compatible type.
|
2009-09-09 23:08:12 +08:00
|
|
|
/// C99 6.2.7p1: Two types have compatible types if their types are the
|
2007-10-16 04:41:53 +08:00
|
|
|
/// same. See 6.7.[2,3,5] for additional rules.
|
2010-07-29 23:18:02 +08:00
|
|
|
bool ASTContext::typesAreCompatible(QualType LHS, QualType RHS,
|
|
|
|
bool CompareUnqualified) {
|
2012-03-11 15:00:24 +08:00
|
|
|
if (getLangOpts().CPlusPlus)
|
2010-02-04 05:02:30 +08:00
|
|
|
return hasSameType(LHS, RHS);
|
|
|
|
|
2010-07-29 23:18:02 +08:00
|
|
|
return !mergeTypes(LHS, RHS, false, CompareUnqualified).isNull();
|
2008-08-22 08:56:42 +08:00
|
|
|
}
|
|
|
|
|
2011-07-13 06:05:16 +08:00
|
|
|
bool ASTContext::propertyTypesAreCompatible(QualType LHS, QualType RHS) {
|
2011-07-13 07:20:13 +08:00
|
|
|
return typesAreCompatible(LHS, RHS);
|
2011-07-13 06:05:16 +08:00
|
|
|
}
|
|
|
|
|
2010-03-17 08:20:01 +08:00
|
|
|
bool ASTContext::typesAreBlockPointerCompatible(QualType LHS, QualType RHS) {
|
|
|
|
return !mergeTypes(LHS, RHS, true).isNull();
|
|
|
|
}
|
|
|
|
|
2010-10-25 02:30:18 +08:00
|
|
|
/// mergeTransparentUnionType - if T is a transparent union type and a member
|
|
|
|
/// of T is compatible with SubType, return the merged type, else return
|
|
|
|
/// QualType()
|
|
|
|
QualType ASTContext::mergeTransparentUnionType(QualType T, QualType SubType,
|
|
|
|
bool OfBlockPointer,
|
|
|
|
bool Unqualified) {
|
|
|
|
if (const RecordType *UT = T->getAsUnionType()) {
|
|
|
|
RecordDecl *UD = UT->getDecl();
|
|
|
|
if (UD->hasAttr<TransparentUnionAttr>()) {
|
|
|
|
for (RecordDecl::field_iterator it = UD->field_begin(),
|
|
|
|
itend = UD->field_end(); it != itend; ++it) {
|
2010-12-03 05:00:06 +08:00
|
|
|
QualType ET = it->getType().getUnqualifiedType();
|
2010-10-25 02:30:18 +08:00
|
|
|
QualType MT = mergeTypes(ET, SubType, OfBlockPointer, Unqualified);
|
|
|
|
if (!MT.isNull())
|
|
|
|
return MT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// mergeFunctionArgumentTypes - merge two types which appear as function
|
|
|
|
/// argument types
|
|
|
|
QualType ASTContext::mergeFunctionArgumentTypes(QualType lhs, QualType rhs,
|
|
|
|
bool OfBlockPointer,
|
|
|
|
bool Unqualified) {
|
|
|
|
// 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);
|
|
|
|
if (!lmerge.isNull())
|
|
|
|
return lmerge;
|
|
|
|
|
|
|
|
QualType rmerge = mergeTransparentUnionType(rhs, lhs, OfBlockPointer,
|
|
|
|
Unqualified);
|
|
|
|
if (!rmerge.isNull())
|
|
|
|
return rmerge;
|
|
|
|
|
|
|
|
return mergeTypes(lhs, rhs, OfBlockPointer, Unqualified);
|
|
|
|
}
|
|
|
|
|
2010-03-17 08:20:01 +08:00
|
|
|
QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
|
2010-07-29 23:18:02 +08:00
|
|
|
bool OfBlockPointer,
|
|
|
|
bool Unqualified) {
|
2009-09-22 07:43:11 +08:00
|
|
|
const FunctionType *lbase = lhs->getAs<FunctionType>();
|
|
|
|
const FunctionType *rbase = rhs->getAs<FunctionType>();
|
2009-02-27 07:50:07 +08:00
|
|
|
const FunctionProtoType *lproto = dyn_cast<FunctionProtoType>(lbase);
|
|
|
|
const FunctionProtoType *rproto = dyn_cast<FunctionProtoType>(rbase);
|
2008-08-22 08:56:42 +08:00
|
|
|
bool allLTypes = true;
|
|
|
|
bool allRTypes = true;
|
|
|
|
|
|
|
|
// Check return type
|
2010-03-17 08:20:01 +08:00
|
|
|
QualType retType;
|
2011-02-12 02:46:17 +08:00
|
|
|
if (OfBlockPointer) {
|
|
|
|
QualType RHS = rbase->getResultType();
|
|
|
|
QualType LHS = lbase->getResultType();
|
|
|
|
bool UnqualifiedResult = Unqualified;
|
|
|
|
if (!UnqualifiedResult)
|
|
|
|
UnqualifiedResult = (!RHS.hasQualifiers() && LHS.hasQualifiers());
|
2011-03-15 00:07:00 +08:00
|
|
|
retType = mergeTypes(LHS, RHS, true, UnqualifiedResult, true);
|
2011-02-12 02:46:17 +08:00
|
|
|
}
|
2010-03-17 08:20:01 +08:00
|
|
|
else
|
2010-12-15 09:06:38 +08:00
|
|
|
retType = mergeTypes(lbase->getResultType(), rbase->getResultType(), false,
|
|
|
|
Unqualified);
|
2008-08-22 08:56:42 +08:00
|
|
|
if (retType.isNull()) return QualType();
|
2010-07-29 23:18:02 +08:00
|
|
|
|
|
|
|
if (Unqualified)
|
|
|
|
retType = retType.getUnqualifiedType();
|
|
|
|
|
|
|
|
CanQualType LRetType = getCanonicalType(lbase->getResultType());
|
|
|
|
CanQualType RRetType = getCanonicalType(rbase->getResultType());
|
|
|
|
if (Unqualified) {
|
|
|
|
LRetType = LRetType.getUnqualifiedType();
|
|
|
|
RRetType = RRetType.getUnqualifiedType();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getCanonicalType(retType) != LRetType)
|
2008-10-06 01:34:18 +08:00
|
|
|
allLTypes = false;
|
2010-07-29 23:18:02 +08:00
|
|
|
if (getCanonicalType(retType) != RRetType)
|
2008-10-06 01:34:18 +08:00
|
|
|
allRTypes = false;
|
2010-12-15 09:06:38 +08:00
|
|
|
|
2010-04-29 00:20:58 +08:00
|
|
|
// FIXME: double check this
|
|
|
|
// FIXME: should we error if lbase->getRegParmAttr() != 0 &&
|
|
|
|
// rbase->getRegParmAttr() != 0 &&
|
|
|
|
// lbase->getRegParmAttr() != rbase->getRegParmAttr()?
|
2010-03-31 04:24:48 +08:00
|
|
|
FunctionType::ExtInfo lbaseInfo = lbase->getExtInfo();
|
|
|
|
FunctionType::ExtInfo rbaseInfo = rbase->getExtInfo();
|
2010-12-15 09:06:38 +08:00
|
|
|
|
|
|
|
// Compatible functions must have compatible calling conventions
|
|
|
|
if (!isSameCallConv(lbaseInfo.getCC(), rbaseInfo.getCC()))
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
// Regparm is part of the calling convention.
|
2011-04-09 16:18:08 +08:00
|
|
|
if (lbaseInfo.getHasRegParm() != rbaseInfo.getHasRegParm())
|
|
|
|
return QualType();
|
2010-12-15 09:06:38 +08:00
|
|
|
if (lbaseInfo.getRegParm() != rbaseInfo.getRegParm())
|
|
|
|
return QualType();
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
if (lbaseInfo.getProducesResult() != rbaseInfo.getProducesResult())
|
|
|
|
return QualType();
|
|
|
|
|
2011-10-05 08:05:34 +08:00
|
|
|
// FIXME: some uses, e.g. conditional exprs, really want this to be 'both'.
|
|
|
|
bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-11-30 00:09:03 +08:00
|
|
|
if (lbaseInfo.getNoReturn() != NoReturn)
|
|
|
|
allLTypes = false;
|
|
|
|
if (rbaseInfo.getNoReturn() != NoReturn)
|
|
|
|
allRTypes = false;
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
FunctionType::ExtInfo einfo = lbaseInfo.withNoReturn(NoReturn);
|
2010-12-14 16:05:40 +08:00
|
|
|
|
2008-08-22 08:56:42 +08:00
|
|
|
if (lproto && rproto) { // two C99 style function prototypes
|
2009-05-28 06:11:52 +08:00
|
|
|
assert(!lproto->hasExceptionSpec() && !rproto->hasExceptionSpec() &&
|
|
|
|
"C++ shouldn't be here");
|
2008-08-22 08:56:42 +08:00
|
|
|
unsigned lproto_nargs = lproto->getNumArgs();
|
|
|
|
unsigned rproto_nargs = rproto->getNumArgs();
|
|
|
|
|
|
|
|
// Compatible functions must have the same number of arguments
|
|
|
|
if (lproto_nargs != rproto_nargs)
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
// Variadic and non-variadic functions aren't compatible
|
|
|
|
if (lproto->isVariadic() != rproto->isVariadic())
|
|
|
|
return QualType();
|
|
|
|
|
2008-10-27 00:43:14 +08:00
|
|
|
if (lproto->getTypeQuals() != rproto->getTypeQuals())
|
|
|
|
return QualType();
|
|
|
|
|
2011-09-29 05:52:05 +08:00
|
|
|
if (LangOpts.ObjCAutoRefCount &&
|
|
|
|
!FunctionTypesMatchOnNSConsumedAttrs(rproto, lproto))
|
|
|
|
return QualType();
|
|
|
|
|
2008-08-22 08:56:42 +08:00
|
|
|
// Check argument compatibility
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<QualType, 10> types;
|
2008-08-22 08:56:42 +08:00
|
|
|
for (unsigned i = 0; i < lproto_nargs; i++) {
|
|
|
|
QualType largtype = lproto->getArgType(i).getUnqualifiedType();
|
|
|
|
QualType rargtype = rproto->getArgType(i).getUnqualifiedType();
|
2010-10-25 02:30:18 +08:00
|
|
|
QualType argtype = mergeFunctionArgumentTypes(largtype, rargtype,
|
|
|
|
OfBlockPointer,
|
|
|
|
Unqualified);
|
2008-08-22 08:56:42 +08:00
|
|
|
if (argtype.isNull()) return QualType();
|
2010-07-29 23:18:02 +08:00
|
|
|
|
|
|
|
if (Unqualified)
|
|
|
|
argtype = argtype.getUnqualifiedType();
|
|
|
|
|
2008-08-22 08:56:42 +08:00
|
|
|
types.push_back(argtype);
|
2010-07-29 23:18:02 +08:00
|
|
|
if (Unqualified) {
|
|
|
|
largtype = largtype.getUnqualifiedType();
|
|
|
|
rargtype = rargtype.getUnqualifiedType();
|
|
|
|
}
|
|
|
|
|
2008-10-06 01:34:18 +08:00
|
|
|
if (getCanonicalType(argtype) != getCanonicalType(largtype))
|
|
|
|
allLTypes = false;
|
|
|
|
if (getCanonicalType(argtype) != getCanonicalType(rargtype))
|
|
|
|
allRTypes = false;
|
2008-08-22 08:56:42 +08:00
|
|
|
}
|
2011-09-29 05:52:05 +08:00
|
|
|
|
2008-08-22 08:56:42 +08:00
|
|
|
if (allLTypes) return lhs;
|
|
|
|
if (allRTypes) return rhs;
|
2010-12-14 16:05:40 +08:00
|
|
|
|
|
|
|
FunctionProtoType::ExtProtoInfo EPI = lproto->getExtProtoInfo();
|
|
|
|
EPI.ExtInfo = einfo;
|
|
|
|
return getFunctionType(retType, types.begin(), types.size(), EPI);
|
2008-08-22 08:56:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (lproto) allRTypes = false;
|
|
|
|
if (rproto) allLTypes = false;
|
|
|
|
|
2009-02-27 07:50:07 +08:00
|
|
|
const FunctionProtoType *proto = lproto ? lproto : rproto;
|
2008-08-22 08:56:42 +08:00
|
|
|
if (proto) {
|
2009-05-28 06:11:52 +08:00
|
|
|
assert(!proto->hasExceptionSpec() && "C++ shouldn't be here");
|
2008-08-22 08:56:42 +08:00
|
|
|
if (proto->isVariadic()) return QualType();
|
|
|
|
// Check that the types are compatible with the types that
|
|
|
|
// would result from default argument promotions (C99 6.7.5.3p15).
|
|
|
|
// The only types actually affected are promotable integer
|
|
|
|
// types and floats, which would be passed as a different
|
|
|
|
// type depending on whether the prototype is visible.
|
|
|
|
unsigned proto_nargs = proto->getNumArgs();
|
|
|
|
for (unsigned i = 0; i < proto_nargs; ++i) {
|
|
|
|
QualType argTy = proto->getArgType(i);
|
2010-02-04 03:27:29 +08:00
|
|
|
|
2012-08-30 08:44:15 +08:00
|
|
|
// Look at the converted type of enum types, since that is the type used
|
2010-02-04 03:27:29 +08:00
|
|
|
// to pass enum values.
|
2012-08-30 08:44:15 +08:00
|
|
|
if (const EnumType *Enum = argTy->getAs<EnumType>()) {
|
|
|
|
argTy = Enum->getDecl()->getIntegerType();
|
|
|
|
if (argTy.isNull())
|
|
|
|
return QualType();
|
|
|
|
}
|
2010-02-04 03:27:29 +08:00
|
|
|
|
2008-08-22 08:56:42 +08:00
|
|
|
if (argTy->isPromotableIntegerType() ||
|
|
|
|
getCanonicalType(argTy).getUnqualifiedType() == FloatTy)
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (allLTypes) return lhs;
|
|
|
|
if (allRTypes) return rhs;
|
2010-12-14 16:05:40 +08:00
|
|
|
|
|
|
|
FunctionProtoType::ExtProtoInfo EPI = proto->getExtProtoInfo();
|
|
|
|
EPI.ExtInfo = einfo;
|
2008-08-22 08:56:42 +08:00
|
|
|
return getFunctionType(retType, proto->arg_type_begin(),
|
2010-12-14 16:05:40 +08:00
|
|
|
proto->getNumArgs(), EPI);
|
2008-08-22 08:56:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (allLTypes) return lhs;
|
|
|
|
if (allRTypes) return rhs;
|
2010-12-15 09:06:38 +08:00
|
|
|
return getFunctionNoProtoType(retType, einfo);
|
2008-08-22 08:56:42 +08:00
|
|
|
}
|
|
|
|
|
2010-03-17 08:20:01 +08:00
|
|
|
QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
|
2010-07-29 23:18:02 +08:00
|
|
|
bool OfBlockPointer,
|
2011-03-15 00:07:00 +08:00
|
|
|
bool Unqualified, bool BlockReturnType) {
|
2007-12-03 15:33:35 +08:00
|
|
|
// 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
|
2009-03-17 07:22:08 +08:00
|
|
|
// expression is an lvalue unless the reference is an rvalue reference and
|
|
|
|
// the expression is a function call (possibly inside parentheses).
|
2010-02-04 05:02:30 +08:00
|
|
|
assert(!LHS->getAs<ReferenceType>() && "LHS is a reference type?");
|
|
|
|
assert(!RHS->getAs<ReferenceType>() && "RHS is a reference type?");
|
2010-07-29 23:18:02 +08:00
|
|
|
|
|
|
|
if (Unqualified) {
|
|
|
|
LHS = LHS.getUnqualifiedType();
|
|
|
|
RHS = RHS.getUnqualifiedType();
|
|
|
|
}
|
2010-02-04 05:02:30 +08:00
|
|
|
|
2008-08-22 08:56:42 +08:00
|
|
|
QualType LHSCan = getCanonicalType(LHS),
|
|
|
|
RHSCan = getCanonicalType(RHS);
|
|
|
|
|
2008-04-07 13:37:56 +08:00
|
|
|
// If two types are identical, they are compatible.
|
2008-08-22 08:56:42 +08:00
|
|
|
if (LHSCan == RHSCan)
|
|
|
|
return LHS;
|
|
|
|
|
2009-09-25 03:53:00 +08:00
|
|
|
// If the qualifiers are different, the types aren't compatible... mostly.
|
First part of changes to eliminate problems with cv-qualifiers and
sugared types. The basic problem is that our qualifier accessors
(getQualifiers, getCVRQualifiers, isConstQualified, etc.) only look at
the current QualType and not at any qualifiers that come from sugared
types, meaning that we won't see these qualifiers through, e.g.,
typedefs:
typedef const int CInt;
typedef CInt Self;
Self.isConstQualified() currently returns false!
Various bugs (e.g., PR5383) have cropped up all over the front end due
to such problems. I'm addressing this problem by splitting each
qualifier accessor into two versions:
- the "local" version only returns qualifiers on this particular
QualType instance
- the "normal" version that will eventually combine qualifiers from this
QualType instance with the qualifiers on the canonical type to
produce the full set of qualifiers.
This commit adds the local versions and switches a few callers from
the "normal" version (e.g., isConstQualified) over to the "local"
version (e.g., isLocalConstQualified) when that is the right thing to
do, e.g., because we're printing or serializing the qualifiers. Also,
switch a bunch of
Context.getCanonicalType(T1).getUnqualifiedType() == Context.getCanonicalType(T2).getQualifiedType()
expressions over to
Context.hasSameUnqualifiedType(T1, T2)
llvm-svn: 88969
2009-11-17 05:35:15 +08:00
|
|
|
Qualifiers LQuals = LHSCan.getLocalQualifiers();
|
|
|
|
Qualifiers RQuals = RHSCan.getLocalQualifiers();
|
2009-09-25 03:53:00 +08:00
|
|
|
if (LQuals != RQuals) {
|
|
|
|
// If any of these qualifiers are different, we have a type
|
|
|
|
// mismatch.
|
|
|
|
if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() ||
|
2011-06-16 07:02:42 +08:00
|
|
|
LQuals.getAddressSpace() != RQuals.getAddressSpace() ||
|
|
|
|
LQuals.getObjCLifetime() != RQuals.getObjCLifetime())
|
2009-09-25 03:53:00 +08:00
|
|
|
return QualType();
|
|
|
|
|
|
|
|
// Exactly one GC qualifier difference is allowed: __strong is
|
|
|
|
// okay if the other type has no GC qualifier but is an Objective
|
|
|
|
// C object pointer (i.e. implicitly strong by default). We fix
|
|
|
|
// this by pretending that the unqualified type was actually
|
|
|
|
// qualified __strong.
|
|
|
|
Qualifiers::GC GC_L = LQuals.getObjCGCAttr();
|
|
|
|
Qualifiers::GC GC_R = RQuals.getObjCGCAttr();
|
|
|
|
assert((GC_L != GC_R) && "unequal qualifier sets had only equal elements");
|
|
|
|
|
|
|
|
if (GC_L == Qualifiers::Weak || GC_R == Qualifiers::Weak)
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
if (GC_L == Qualifiers::Strong && RHSCan->isObjCObjectPointerType()) {
|
|
|
|
return mergeTypes(LHS, getObjCGCQualType(RHS, Qualifiers::Strong));
|
|
|
|
}
|
|
|
|
if (GC_R == Qualifiers::Strong && LHSCan->isObjCObjectPointerType()) {
|
|
|
|
return mergeTypes(getObjCGCQualType(LHS, Qualifiers::Strong), RHS);
|
|
|
|
}
|
2008-08-22 08:56:42 +08:00
|
|
|
return QualType();
|
2009-09-25 03:53:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Okay, qualifiers are equal.
|
2008-08-22 08:56:42 +08:00
|
|
|
|
2009-06-01 09:22:52 +08:00
|
|
|
Type::TypeClass LHSClass = LHSCan->getTypeClass();
|
|
|
|
Type::TypeClass RHSClass = RHSCan->getTypeClass();
|
2008-04-07 13:37:56 +08:00
|
|
|
|
2008-01-14 13:45:46 +08:00
|
|
|
// We want to consider the two function types to be the same for these
|
|
|
|
// comparisons, just force one to the other.
|
|
|
|
if (LHSClass == Type::FunctionProto) LHSClass = Type::FunctionNoProto;
|
|
|
|
if (RHSClass == Type::FunctionProto) RHSClass = Type::FunctionNoProto;
|
2008-02-12 16:23:06 +08:00
|
|
|
|
|
|
|
// Same as above for arrays
|
2008-04-07 13:43:21 +08:00
|
|
|
if (LHSClass == Type::VariableArray || LHSClass == Type::IncompleteArray)
|
|
|
|
LHSClass = Type::ConstantArray;
|
|
|
|
if (RHSClass == Type::VariableArray || RHSClass == Type::IncompleteArray)
|
|
|
|
RHSClass = Type::ConstantArray;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-05-15 19:32:37 +08:00
|
|
|
// ObjCInterfaces are just specialized ObjCObjects.
|
|
|
|
if (LHSClass == Type::ObjCInterface) LHSClass = Type::ObjCObject;
|
|
|
|
if (RHSClass == Type::ObjCInterface) RHSClass = Type::ObjCObject;
|
|
|
|
|
2008-04-19 07:10:10 +08:00
|
|
|
// Canonicalize ExtVector -> Vector.
|
|
|
|
if (LHSClass == Type::ExtVector) LHSClass = Type::Vector;
|
|
|
|
if (RHSClass == Type::ExtVector) RHSClass = Type::Vector;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-12-11 04:07:25 +08:00
|
|
|
// If the canonical type classes don't match.
|
|
|
|
if (LHSClass != RHSClass) {
|
2008-01-14 13:45:46 +08:00
|
|
|
// C99 6.7.2.2p4: Each enumerated type shall be compatible with char,
|
2009-09-09 23:08:12 +08:00
|
|
|
// a signed integer type, or an unsigned integer type.
|
2009-12-09 17:09:27 +08:00
|
|
|
// Compatibility is based on the underlying type, not the promotion
|
|
|
|
// type.
|
2009-09-22 07:43:11 +08:00
|
|
|
if (const EnumType* ETy = LHS->getAs<EnumType>()) {
|
2012-02-07 03:06:20 +08:00
|
|
|
QualType TINT = ETy->getDecl()->getIntegerType();
|
|
|
|
if (!TINT.isNull() && hasSameType(TINT, RHSCan.getUnqualifiedType()))
|
2008-08-22 08:56:42 +08:00
|
|
|
return RHS;
|
2008-02-12 16:46:17 +08:00
|
|
|
}
|
2009-09-22 07:43:11 +08:00
|
|
|
if (const EnumType* ETy = RHS->getAs<EnumType>()) {
|
2012-02-07 03:06:20 +08:00
|
|
|
QualType TINT = ETy->getDecl()->getIntegerType();
|
|
|
|
if (!TINT.isNull() && hasSameType(TINT, LHSCan.getUnqualifiedType()))
|
2008-08-22 08:56:42 +08:00
|
|
|
return LHS;
|
2008-02-12 16:46:17 +08:00
|
|
|
}
|
2012-01-26 08:45:38 +08:00
|
|
|
// allow block pointer type to match an 'id' type.
|
2012-01-27 01:08:50 +08:00
|
|
|
if (OfBlockPointer && !BlockReturnType) {
|
|
|
|
if (LHS->isObjCIdType() && RHS->isBlockPointerType())
|
|
|
|
return LHS;
|
|
|
|
if (RHS->isObjCIdType() && LHS->isBlockPointerType())
|
|
|
|
return RHS;
|
|
|
|
}
|
2012-01-26 08:45:38 +08:00
|
|
|
|
2008-08-22 08:56:42 +08:00
|
|
|
return QualType();
|
2007-10-16 04:41:53 +08:00
|
|
|
}
|
2008-08-22 08:56:42 +08:00
|
|
|
|
2008-01-10 06:43:08 +08:00
|
|
|
// The canonical type classes match.
|
2008-01-14 13:45:46 +08:00
|
|
|
switch (LHSClass) {
|
2009-02-27 07:50:07 +08:00
|
|
|
#define TYPE(Class, Base)
|
|
|
|
#define ABSTRACT_TYPE(Class, Base)
|
2010-03-02 07:49:17 +08:00
|
|
|
#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
|
2009-02-27 07:50:07 +08:00
|
|
|
#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
|
|
|
|
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
|
|
|
|
#include "clang/AST/TypeNodes.def"
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("Non-canonical and dependent types shouldn't get here");
|
2009-02-27 07:50:07 +08:00
|
|
|
|
2009-03-17 07:22:08 +08:00
|
|
|
case Type::LValueReference:
|
|
|
|
case Type::RValueReference:
|
2009-02-27 07:50:07 +08:00
|
|
|
case Type::MemberPointer:
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("C++ should never be in mergeTypes");
|
2009-02-27 07:50:07 +08:00
|
|
|
|
2010-05-15 19:32:37 +08:00
|
|
|
case Type::ObjCInterface:
|
2009-02-27 07:50:07 +08:00
|
|
|
case Type::IncompleteArray:
|
|
|
|
case Type::VariableArray:
|
|
|
|
case Type::FunctionProto:
|
|
|
|
case Type::ExtVector:
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("Types are eliminated above");
|
2009-02-27 07:50:07 +08:00
|
|
|
|
2008-01-14 13:45:46 +08:00
|
|
|
case Type::Pointer:
|
2008-08-22 08:56:42 +08:00
|
|
|
{
|
|
|
|
// Merge two pointer types, while trying to preserve typedef info
|
2009-07-30 05:53:49 +08:00
|
|
|
QualType LHSPointee = LHS->getAs<PointerType>()->getPointeeType();
|
|
|
|
QualType RHSPointee = RHS->getAs<PointerType>()->getPointeeType();
|
2010-07-29 23:18:02 +08:00
|
|
|
if (Unqualified) {
|
|
|
|
LHSPointee = LHSPointee.getUnqualifiedType();
|
|
|
|
RHSPointee = RHSPointee.getUnqualifiedType();
|
|
|
|
}
|
|
|
|
QualType ResultType = mergeTypes(LHSPointee, RHSPointee, false,
|
|
|
|
Unqualified);
|
2008-08-22 08:56:42 +08:00
|
|
|
if (ResultType.isNull()) return QualType();
|
2009-06-02 13:28:56 +08:00
|
|
|
if (getCanonicalType(LHSPointee) == getCanonicalType(ResultType))
|
2008-10-06 01:34:18 +08:00
|
|
|
return LHS;
|
2009-06-02 13:28:56 +08:00
|
|
|
if (getCanonicalType(RHSPointee) == getCanonicalType(ResultType))
|
2008-10-06 01:34:18 +08:00
|
|
|
return RHS;
|
2008-08-22 08:56:42 +08:00
|
|
|
return getPointerType(ResultType);
|
|
|
|
}
|
2008-12-11 01:49:55 +08:00
|
|
|
case Type::BlockPointer:
|
|
|
|
{
|
|
|
|
// Merge two block pointer types, while trying to preserve typedef info
|
2009-07-30 05:53:49 +08:00
|
|
|
QualType LHSPointee = LHS->getAs<BlockPointerType>()->getPointeeType();
|
|
|
|
QualType RHSPointee = RHS->getAs<BlockPointerType>()->getPointeeType();
|
2010-07-29 23:18:02 +08:00
|
|
|
if (Unqualified) {
|
|
|
|
LHSPointee = LHSPointee.getUnqualifiedType();
|
|
|
|
RHSPointee = RHSPointee.getUnqualifiedType();
|
|
|
|
}
|
|
|
|
QualType ResultType = mergeTypes(LHSPointee, RHSPointee, OfBlockPointer,
|
|
|
|
Unqualified);
|
2008-12-11 01:49:55 +08:00
|
|
|
if (ResultType.isNull()) return QualType();
|
|
|
|
if (getCanonicalType(LHSPointee) == getCanonicalType(ResultType))
|
|
|
|
return LHS;
|
|
|
|
if (getCanonicalType(RHSPointee) == getCanonicalType(ResultType))
|
|
|
|
return RHS;
|
|
|
|
return getBlockPointerType(ResultType);
|
|
|
|
}
|
2011-10-07 07:00:33 +08:00
|
|
|
case Type::Atomic:
|
|
|
|
{
|
|
|
|
// Merge two pointer types, while trying to preserve typedef info
|
|
|
|
QualType LHSValue = LHS->getAs<AtomicType>()->getValueType();
|
|
|
|
QualType RHSValue = RHS->getAs<AtomicType>()->getValueType();
|
|
|
|
if (Unqualified) {
|
|
|
|
LHSValue = LHSValue.getUnqualifiedType();
|
|
|
|
RHSValue = RHSValue.getUnqualifiedType();
|
|
|
|
}
|
|
|
|
QualType ResultType = mergeTypes(LHSValue, RHSValue, false,
|
|
|
|
Unqualified);
|
|
|
|
if (ResultType.isNull()) return QualType();
|
|
|
|
if (getCanonicalType(LHSValue) == getCanonicalType(ResultType))
|
|
|
|
return LHS;
|
|
|
|
if (getCanonicalType(RHSValue) == getCanonicalType(ResultType))
|
|
|
|
return RHS;
|
|
|
|
return getAtomicType(ResultType);
|
|
|
|
}
|
2008-01-14 13:45:46 +08:00
|
|
|
case Type::ConstantArray:
|
2008-08-22 08:56:42 +08:00
|
|
|
{
|
|
|
|
const ConstantArrayType* LCAT = getAsConstantArrayType(LHS);
|
|
|
|
const ConstantArrayType* RCAT = getAsConstantArrayType(RHS);
|
|
|
|
if (LCAT && RCAT && RCAT->getSize() != LCAT->getSize())
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
QualType LHSElem = getAsArrayType(LHS)->getElementType();
|
|
|
|
QualType RHSElem = getAsArrayType(RHS)->getElementType();
|
2010-07-29 23:18:02 +08:00
|
|
|
if (Unqualified) {
|
|
|
|
LHSElem = LHSElem.getUnqualifiedType();
|
|
|
|
RHSElem = RHSElem.getUnqualifiedType();
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType ResultType = mergeTypes(LHSElem, RHSElem, false, Unqualified);
|
2008-08-22 08:56:42 +08:00
|
|
|
if (ResultType.isNull()) return QualType();
|
2008-10-06 01:34:18 +08:00
|
|
|
if (LCAT && getCanonicalType(LHSElem) == getCanonicalType(ResultType))
|
|
|
|
return LHS;
|
|
|
|
if (RCAT && getCanonicalType(RHSElem) == getCanonicalType(ResultType))
|
|
|
|
return RHS;
|
2008-08-22 09:48:21 +08:00
|
|
|
if (LCAT) return getConstantArrayType(ResultType, LCAT->getSize(),
|
|
|
|
ArrayType::ArraySizeModifier(), 0);
|
|
|
|
if (RCAT) return getConstantArrayType(ResultType, RCAT->getSize(),
|
|
|
|
ArrayType::ArraySizeModifier(), 0);
|
2008-08-22 08:56:42 +08:00
|
|
|
const VariableArrayType* LVAT = getAsVariableArrayType(LHS);
|
|
|
|
const VariableArrayType* RVAT = getAsVariableArrayType(RHS);
|
2008-10-06 01:34:18 +08:00
|
|
|
if (LVAT && getCanonicalType(LHSElem) == getCanonicalType(ResultType))
|
|
|
|
return LHS;
|
|
|
|
if (RVAT && getCanonicalType(RHSElem) == getCanonicalType(ResultType))
|
|
|
|
return RHS;
|
2008-08-22 08:56:42 +08:00
|
|
|
if (LVAT) {
|
|
|
|
// FIXME: This isn't correct! But tricky to implement because
|
|
|
|
// the array's size has to be the size of LHS, but the type
|
|
|
|
// has to be different.
|
|
|
|
return LHS;
|
|
|
|
}
|
|
|
|
if (RVAT) {
|
|
|
|
// FIXME: This isn't correct! But tricky to implement because
|
|
|
|
// the array's size has to be the size of RHS, but the type
|
|
|
|
// has to be different.
|
|
|
|
return RHS;
|
|
|
|
}
|
2008-08-22 09:48:21 +08:00
|
|
|
if (getCanonicalType(LHSElem) == getCanonicalType(ResultType)) return LHS;
|
|
|
|
if (getCanonicalType(RHSElem) == getCanonicalType(ResultType)) return RHS;
|
2009-07-06 23:59:29 +08:00
|
|
|
return getIncompleteArrayType(ResultType,
|
|
|
|
ArrayType::ArraySizeModifier(), 0);
|
2008-08-22 08:56:42 +08:00
|
|
|
}
|
2008-01-14 13:45:46 +08:00
|
|
|
case Type::FunctionNoProto:
|
2010-07-29 23:18:02 +08:00
|
|
|
return mergeFunctionTypes(LHS, RHS, OfBlockPointer, Unqualified);
|
2009-02-27 07:50:07 +08:00
|
|
|
case Type::Record:
|
|
|
|
case Type::Enum:
|
2008-08-22 08:56:42 +08:00
|
|
|
return QualType();
|
2008-01-14 13:45:46 +08:00
|
|
|
case Type::Builtin:
|
2008-04-07 13:55:38 +08:00
|
|
|
// Only exactly equal builtin types are compatible, which is tested above.
|
2008-08-22 08:56:42 +08:00
|
|
|
return QualType();
|
2009-01-29 05:22:12 +08:00
|
|
|
case Type::Complex:
|
|
|
|
// Distinct complex types are incompatible.
|
|
|
|
return QualType();
|
2008-04-07 13:55:38 +08:00
|
|
|
case Type::Vector:
|
2009-02-28 07:04:43 +08:00
|
|
|
// FIXME: The merged type should be an ExtVector!
|
2010-03-13 07:14:13 +08:00
|
|
|
if (areCompatVectorTypes(LHSCan->getAs<VectorType>(),
|
|
|
|
RHSCan->getAs<VectorType>()))
|
2008-08-22 08:56:42 +08:00
|
|
|
return LHS;
|
2008-10-06 01:34:18 +08:00
|
|
|
return QualType();
|
2010-05-15 19:32:37 +08:00
|
|
|
case Type::ObjCObject: {
|
|
|
|
// Check if the types are assignment compatible.
|
2009-02-28 07:04:43 +08:00
|
|
|
// FIXME: This should be type compatibility, e.g. whether
|
|
|
|
// "LHS x; RHS x;" at global scope is legal.
|
2010-05-15 19:32:37 +08:00
|
|
|
const ObjCObjectType* LHSIface = LHS->getAs<ObjCObjectType>();
|
|
|
|
const ObjCObjectType* RHSIface = RHS->getAs<ObjCObjectType>();
|
|
|
|
if (canAssignObjCInterfaces(LHSIface, RHSIface))
|
2009-02-22 00:18:07 +08:00
|
|
|
return LHS;
|
|
|
|
|
2008-08-22 08:56:42 +08:00
|
|
|
return QualType();
|
2009-02-22 01:14:49 +08:00
|
|
|
}
|
2009-07-11 07:34:53 +08:00
|
|
|
case Type::ObjCObjectPointer: {
|
2010-03-17 08:20:01 +08:00
|
|
|
if (OfBlockPointer) {
|
|
|
|
if (canAssignObjCInterfacesInBlockPointer(
|
|
|
|
LHS->getAs<ObjCObjectPointerType>(),
|
2011-03-15 00:07:00 +08:00
|
|
|
RHS->getAs<ObjCObjectPointerType>(),
|
|
|
|
BlockReturnType))
|
2012-01-17 14:56:22 +08:00
|
|
|
return LHS;
|
2010-03-17 08:20:01 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
2009-09-22 07:43:11 +08:00
|
|
|
if (canAssignObjCInterfaces(LHS->getAs<ObjCObjectPointerType>(),
|
|
|
|
RHS->getAs<ObjCObjectPointerType>()))
|
2009-07-11 07:34:53 +08:00
|
|
|
return LHS;
|
|
|
|
|
2008-12-11 06:14:21 +08:00
|
|
|
return QualType();
|
2012-01-17 14:56:22 +08:00
|
|
|
}
|
2007-10-16 04:41:53 +08:00
|
|
|
}
|
2009-02-27 07:50:07 +08:00
|
|
|
|
2012-01-17 14:56:22 +08:00
|
|
|
llvm_unreachable("Invalid Type::Class!");
|
2007-10-16 04:41:53 +08:00
|
|
|
}
|
2007-11-01 01:10:13 +08:00
|
|
|
|
2011-09-29 05:52:05 +08:00
|
|
|
bool ASTContext::FunctionTypesMatchOnNSConsumedAttrs(
|
|
|
|
const FunctionProtoType *FromFunctionType,
|
|
|
|
const FunctionProtoType *ToFunctionType) {
|
|
|
|
if (FromFunctionType->hasAnyConsumedArgs() !=
|
|
|
|
ToFunctionType->hasAnyConsumedArgs())
|
|
|
|
return false;
|
|
|
|
FunctionProtoType::ExtProtoInfo FromEPI =
|
|
|
|
FromFunctionType->getExtProtoInfo();
|
|
|
|
FunctionProtoType::ExtProtoInfo ToEPI =
|
|
|
|
ToFunctionType->getExtProtoInfo();
|
|
|
|
if (FromEPI.ConsumedArguments && ToEPI.ConsumedArguments)
|
|
|
|
for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs();
|
|
|
|
ArgIdx != NumArgs; ++ArgIdx) {
|
|
|
|
if (FromEPI.ConsumedArguments[ArgIdx] !=
|
|
|
|
ToEPI.ConsumedArguments[ArgIdx])
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-05-20 05:37:30 +08:00
|
|
|
/// mergeObjCGCQualifiers - This routine merges ObjC's GC attribute of 'LHS' and
|
|
|
|
/// 'RHS' attributes and returns the merged version; including for function
|
|
|
|
/// return types.
|
|
|
|
QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) {
|
|
|
|
QualType LHSCan = getCanonicalType(LHS),
|
|
|
|
RHSCan = getCanonicalType(RHS);
|
|
|
|
// If two types are identical, they are compatible.
|
|
|
|
if (LHSCan == RHSCan)
|
|
|
|
return LHS;
|
|
|
|
if (RHSCan->isFunctionType()) {
|
|
|
|
if (!LHSCan->isFunctionType())
|
|
|
|
return QualType();
|
|
|
|
QualType OldReturnType =
|
|
|
|
cast<FunctionType>(RHSCan.getTypePtr())->getResultType();
|
|
|
|
QualType NewReturnType =
|
|
|
|
cast<FunctionType>(LHSCan.getTypePtr())->getResultType();
|
|
|
|
QualType ResReturnType =
|
|
|
|
mergeObjCGCQualifiers(NewReturnType, OldReturnType);
|
|
|
|
if (ResReturnType.isNull())
|
|
|
|
return QualType();
|
|
|
|
if (ResReturnType == NewReturnType || ResReturnType == OldReturnType) {
|
|
|
|
// id foo(); ... __strong id foo(); or: __strong id foo(); ... id foo();
|
|
|
|
// In either case, use OldReturnType to build the new function type.
|
|
|
|
const FunctionType *F = LHS->getAs<FunctionType>();
|
|
|
|
if (const FunctionProtoType *FPT = cast<FunctionProtoType>(F)) {
|
2010-12-14 16:05:40 +08:00
|
|
|
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
|
|
|
|
EPI.ExtInfo = getFunctionExtInfo(LHS);
|
2010-05-20 05:37:30 +08:00
|
|
|
QualType ResultType
|
|
|
|
= getFunctionType(OldReturnType, FPT->arg_type_begin(),
|
2010-12-14 16:05:40 +08:00
|
|
|
FPT->getNumArgs(), EPI);
|
2010-05-20 05:37:30 +08:00
|
|
|
return ResultType;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the qualifiers are different, the types can still be merged.
|
|
|
|
Qualifiers LQuals = LHSCan.getLocalQualifiers();
|
|
|
|
Qualifiers RQuals = RHSCan.getLocalQualifiers();
|
|
|
|
if (LQuals != RQuals) {
|
|
|
|
// If any of these qualifiers are different, we have a type mismatch.
|
|
|
|
if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() ||
|
|
|
|
LQuals.getAddressSpace() != RQuals.getAddressSpace())
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
// Exactly one GC qualifier difference is allowed: __strong is
|
|
|
|
// okay if the other type has no GC qualifier but is an Objective
|
|
|
|
// C object pointer (i.e. implicitly strong by default). We fix
|
|
|
|
// this by pretending that the unqualified type was actually
|
|
|
|
// qualified __strong.
|
|
|
|
Qualifiers::GC GC_L = LQuals.getObjCGCAttr();
|
|
|
|
Qualifiers::GC GC_R = RQuals.getObjCGCAttr();
|
|
|
|
assert((GC_L != GC_R) && "unequal qualifier sets had only equal elements");
|
|
|
|
|
|
|
|
if (GC_L == Qualifiers::Weak || GC_R == Qualifiers::Weak)
|
|
|
|
return QualType();
|
|
|
|
|
|
|
|
if (GC_L == Qualifiers::Strong)
|
|
|
|
return LHS;
|
|
|
|
if (GC_R == Qualifiers::Strong)
|
|
|
|
return RHS;
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LHSCan->isObjCObjectPointerType() && RHSCan->isObjCObjectPointerType()) {
|
|
|
|
QualType LHSBaseQT = LHS->getAs<ObjCObjectPointerType>()->getPointeeType();
|
|
|
|
QualType RHSBaseQT = RHS->getAs<ObjCObjectPointerType>()->getPointeeType();
|
|
|
|
QualType ResQT = mergeObjCGCQualifiers(LHSBaseQT, RHSBaseQT);
|
|
|
|
if (ResQT == LHSBaseQT)
|
|
|
|
return LHS;
|
|
|
|
if (ResQT == RHSBaseQT)
|
|
|
|
return RHS;
|
|
|
|
}
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2008-06-28 14:23:08 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Integer Predicates
|
|
|
|
//===----------------------------------------------------------------------===//
|
2009-01-16 15:15:35 +08:00
|
|
|
|
2011-01-12 17:06:06 +08:00
|
|
|
unsigned ASTContext::getIntWidth(QualType T) const {
|
2011-01-19 14:33:43 +08:00
|
|
|
if (const EnumType *ET = dyn_cast<EnumType>(T))
|
2009-12-11 06:29:29 +08:00
|
|
|
T = ET->getDecl()->getIntegerType();
|
2010-10-09 07:50:27 +08:00
|
|
|
if (T->isBooleanType())
|
|
|
|
return 1;
|
2009-02-13 10:31:07 +08:00
|
|
|
// For builtin types, just use the standard type sizing method
|
2008-06-28 14:23:08 +08:00
|
|
|
return (unsigned)getTypeSize(T);
|
|
|
|
}
|
|
|
|
|
2012-09-09 18:21:24 +08:00
|
|
|
QualType ASTContext::getCorrespondingUnsignedType(QualType T) const {
|
2010-07-23 23:58:24 +08:00
|
|
|
assert(T->hasSignedIntegerRepresentation() && "Unexpected type");
|
2009-10-18 04:33:28 +08:00
|
|
|
|
|
|
|
// Turn <4 x signed int> -> <4 x unsigned int>
|
|
|
|
if (const VectorType *VTy = T->getAs<VectorType>())
|
|
|
|
return getVectorType(getCorrespondingUnsignedType(VTy->getElementType()),
|
2010-11-11 05:56:12 +08:00
|
|
|
VTy->getNumElements(), VTy->getVectorKind());
|
2009-10-18 04:33:28 +08:00
|
|
|
|
|
|
|
// For enums, we return the unsigned version of the base type.
|
|
|
|
if (const EnumType *ETy = T->getAs<EnumType>())
|
2008-06-28 14:23:08 +08:00
|
|
|
T = ETy->getDecl()->getIntegerType();
|
2009-10-18 04:33:28 +08:00
|
|
|
|
|
|
|
const BuiltinType *BTy = T->getAs<BuiltinType>();
|
|
|
|
assert(BTy && "Unexpected signed integer type");
|
2008-06-28 14:23:08 +08:00
|
|
|
switch (BTy->getKind()) {
|
|
|
|
case BuiltinType::Char_S:
|
|
|
|
case BuiltinType::SChar:
|
|
|
|
return UnsignedCharTy;
|
|
|
|
case BuiltinType::Short:
|
|
|
|
return UnsignedShortTy;
|
|
|
|
case BuiltinType::Int:
|
|
|
|
return UnsignedIntTy;
|
|
|
|
case BuiltinType::Long:
|
|
|
|
return UnsignedLongTy;
|
|
|
|
case BuiltinType::LongLong:
|
|
|
|
return UnsignedLongLongTy;
|
2009-04-30 10:43:43 +08:00
|
|
|
case BuiltinType::Int128:
|
|
|
|
return UnsignedInt128Ty;
|
2008-06-28 14:23:08 +08:00
|
|
|
default:
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("Unexpected signed integer type");
|
2008-06-28 14:23:08 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-25 01:26:36 +08:00
|
|
|
ASTMutationListener::~ASTMutationListener() { }
|
|
|
|
|
2009-06-14 08:45:47 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Builtin Type Computation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// DecodeTypeFromStr - This decodes one type descriptor from Str, advancing the
|
2010-10-02 06:42:38 +08:00
|
|
|
/// pointer over the consumed characters. This returns the resultant type. If
|
|
|
|
/// AllowTypeModifiers is false then modifier like * are not parsed, just basic
|
|
|
|
/// types. This allows "v2i*" to be parsed as a pointer to a v2i instead of
|
|
|
|
/// a vector of "i*".
|
2010-10-02 06:53:11 +08:00
|
|
|
///
|
|
|
|
/// RequiresICE is filled in on return to indicate whether the value is required
|
|
|
|
/// to be an Integer Constant Expression.
|
2011-01-12 17:06:06 +08:00
|
|
|
static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
|
2009-06-14 08:45:47 +08:00
|
|
|
ASTContext::GetBuiltinTypeError &Error,
|
2010-10-02 06:53:11 +08:00
|
|
|
bool &RequiresICE,
|
2010-10-02 06:42:38 +08:00
|
|
|
bool AllowTypeModifiers) {
|
2009-06-14 08:45:47 +08:00
|
|
|
// Modifiers.
|
|
|
|
int HowLong = 0;
|
|
|
|
bool Signed = false, Unsigned = false;
|
2010-10-02 06:53:11 +08:00
|
|
|
RequiresICE = false;
|
2010-10-01 15:13:18 +08:00
|
|
|
|
2010-10-02 06:42:38 +08:00
|
|
|
// Read the prefixed modifiers first.
|
2009-06-14 08:45:47 +08:00
|
|
|
bool Done = false;
|
|
|
|
while (!Done) {
|
|
|
|
switch (*Str++) {
|
2009-09-09 23:08:12 +08:00
|
|
|
default: Done = true; --Str; break;
|
2010-10-01 15:13:18 +08:00
|
|
|
case 'I':
|
2010-10-02 06:53:11 +08:00
|
|
|
RequiresICE = true;
|
2010-10-01 15:13:18 +08:00
|
|
|
break;
|
2009-06-14 08:45:47 +08:00
|
|
|
case 'S':
|
|
|
|
assert(!Unsigned && "Can't use both 'S' and 'U' modifiers!");
|
|
|
|
assert(!Signed && "Can't use 'S' modifier multiple times!");
|
|
|
|
Signed = true;
|
|
|
|
break;
|
|
|
|
case 'U':
|
|
|
|
assert(!Signed && "Can't use both 'S' and 'U' modifiers!");
|
|
|
|
assert(!Unsigned && "Can't use 'S' modifier multiple times!");
|
|
|
|
Unsigned = true;
|
|
|
|
break;
|
|
|
|
case 'L':
|
|
|
|
assert(HowLong <= 2 && "Can't have LLLL modifier");
|
|
|
|
++HowLong;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType Type;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-14 08:45:47 +08:00
|
|
|
// Read the base type.
|
|
|
|
switch (*Str++) {
|
2011-09-23 13:06:16 +08:00
|
|
|
default: llvm_unreachable("Unknown builtin type letter!");
|
2009-06-14 08:45:47 +08:00
|
|
|
case 'v':
|
|
|
|
assert(HowLong == 0 && !Signed && !Unsigned &&
|
|
|
|
"Bad modifiers used with 'v'!");
|
|
|
|
Type = Context.VoidTy;
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
assert(HowLong == 0 && !Signed && !Unsigned &&
|
|
|
|
"Bad modifiers used with 'f'!");
|
|
|
|
Type = Context.FloatTy;
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
assert(HowLong < 2 && !Signed && !Unsigned &&
|
|
|
|
"Bad modifiers used with 'd'!");
|
|
|
|
if (HowLong)
|
|
|
|
Type = Context.LongDoubleTy;
|
|
|
|
else
|
|
|
|
Type = Context.DoubleTy;
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
assert(HowLong == 0 && "Bad modifiers used with 's'!");
|
|
|
|
if (Unsigned)
|
|
|
|
Type = Context.UnsignedShortTy;
|
|
|
|
else
|
|
|
|
Type = Context.ShortTy;
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
if (HowLong == 3)
|
|
|
|
Type = Unsigned ? Context.UnsignedInt128Ty : Context.Int128Ty;
|
|
|
|
else if (HowLong == 2)
|
|
|
|
Type = Unsigned ? Context.UnsignedLongLongTy : Context.LongLongTy;
|
|
|
|
else if (HowLong == 1)
|
|
|
|
Type = Unsigned ? Context.UnsignedLongTy : Context.LongTy;
|
|
|
|
else
|
|
|
|
Type = Unsigned ? Context.UnsignedIntTy : Context.IntTy;
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
assert(HowLong == 0 && "Bad modifiers used with 'c'!");
|
|
|
|
if (Signed)
|
|
|
|
Type = Context.SignedCharTy;
|
|
|
|
else if (Unsigned)
|
|
|
|
Type = Context.UnsignedCharTy;
|
|
|
|
else
|
|
|
|
Type = Context.CharTy;
|
|
|
|
break;
|
|
|
|
case 'b': // boolean
|
|
|
|
assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'b'!");
|
|
|
|
Type = Context.BoolTy;
|
|
|
|
break;
|
|
|
|
case 'z': // size_t.
|
|
|
|
assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'z'!");
|
|
|
|
Type = Context.getSizeType();
|
|
|
|
break;
|
|
|
|
case 'F':
|
|
|
|
Type = Context.getCFConstantStringType();
|
|
|
|
break;
|
2010-11-10 05:38:20 +08:00
|
|
|
case 'G':
|
|
|
|
Type = Context.getObjCIdType();
|
|
|
|
break;
|
|
|
|
case 'H':
|
|
|
|
Type = Context.getObjCSelType();
|
|
|
|
break;
|
2013-01-05 02:45:40 +08:00
|
|
|
case 'M':
|
|
|
|
Type = Context.getObjCSuperType();
|
|
|
|
break;
|
2009-06-14 08:45:47 +08:00
|
|
|
case 'a':
|
|
|
|
Type = Context.getBuiltinVaListType();
|
|
|
|
assert(!Type.isNull() && "builtin va list type not initialized!");
|
|
|
|
break;
|
|
|
|
case 'A':
|
|
|
|
// This is a "reference" to a va_list; however, what exactly
|
|
|
|
// this means depends on how va_list is defined. There are two
|
|
|
|
// different kinds of va_list: ones passed by value, and ones
|
|
|
|
// passed by reference. An example of a by-value va_list is
|
|
|
|
// x86, where va_list is a char*. An example of by-ref va_list
|
|
|
|
// is x86-64, where va_list is a __va_list_tag[1]. For x86,
|
|
|
|
// we want this argument to be a char*&; for x86-64, we want
|
|
|
|
// it to be a __va_list_tag*.
|
|
|
|
Type = Context.getBuiltinVaListType();
|
|
|
|
assert(!Type.isNull() && "builtin va list type not initialized!");
|
2010-10-02 06:53:11 +08:00
|
|
|
if (Type->isArrayType())
|
2009-06-14 08:45:47 +08:00
|
|
|
Type = Context.getArrayDecayedType(Type);
|
2010-10-02 06:53:11 +08:00
|
|
|
else
|
2009-06-14 08:45:47 +08:00
|
|
|
Type = Context.getLValueReferenceType(Type);
|
|
|
|
break;
|
|
|
|
case 'V': {
|
|
|
|
char *End;
|
|
|
|
unsigned NumElements = strtoul(Str, &End, 10);
|
|
|
|
assert(End != Str && "Missing vector size");
|
|
|
|
Str = End;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-10-02 06:53:11 +08:00
|
|
|
QualType ElementType = DecodeTypeFromStr(Str, Context, Error,
|
|
|
|
RequiresICE, false);
|
|
|
|
assert(!RequiresICE && "Can't require vector ICE");
|
2010-10-02 06:42:38 +08:00
|
|
|
|
|
|
|
// TODO: No way to make AltiVec vectors in builtins yet.
|
2010-06-23 14:00:24 +08:00
|
|
|
Type = Context.getVectorType(ElementType, NumElements,
|
2010-11-11 05:56:12 +08:00
|
|
|
VectorType::GenericVector);
|
2009-06-14 08:45:47 +08:00
|
|
|
break;
|
|
|
|
}
|
2012-06-08 02:08:25 +08:00
|
|
|
case 'E': {
|
|
|
|
char *End;
|
|
|
|
|
|
|
|
unsigned NumElements = strtoul(Str, &End, 10);
|
|
|
|
assert(End != Str && "Missing vector size");
|
|
|
|
|
|
|
|
Str = End;
|
|
|
|
|
|
|
|
QualType ElementType = DecodeTypeFromStr(Str, Context, Error, RequiresICE,
|
|
|
|
false);
|
|
|
|
Type = Context.getExtVectorType(ElementType, NumElements);
|
|
|
|
break;
|
|
|
|
}
|
2009-09-29 05:45:01 +08:00
|
|
|
case 'X': {
|
2010-10-02 06:53:11 +08:00
|
|
|
QualType ElementType = DecodeTypeFromStr(Str, Context, Error, RequiresICE,
|
|
|
|
false);
|
|
|
|
assert(!RequiresICE && "Can't require complex ICE");
|
2009-09-29 05:45:01 +08:00
|
|
|
Type = Context.getComplexType(ElementType);
|
|
|
|
break;
|
2011-08-24 07:33:09 +08:00
|
|
|
}
|
|
|
|
case 'Y' : {
|
|
|
|
Type = Context.getPointerDiffType();
|
|
|
|
break;
|
|
|
|
}
|
2009-07-29 06:49:34 +08:00
|
|
|
case 'P':
|
2009-07-08 00:35:42 +08:00
|
|
|
Type = Context.getFILEType();
|
|
|
|
if (Type.isNull()) {
|
2009-07-29 07:57:15 +08:00
|
|
|
Error = ASTContext::GE_Missing_stdio;
|
2009-06-14 08:45:47 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
2009-07-29 07:47:15 +08:00
|
|
|
break;
|
2009-07-29 06:49:34 +08:00
|
|
|
case 'J':
|
2009-07-29 07:57:15 +08:00
|
|
|
if (Signed)
|
2009-07-28 10:25:19 +08:00
|
|
|
Type = Context.getsigjmp_bufType();
|
2009-07-29 07:57:15 +08:00
|
|
|
else
|
|
|
|
Type = Context.getjmp_bufType();
|
|
|
|
|
2009-07-29 07:47:15 +08:00
|
|
|
if (Type.isNull()) {
|
2009-07-29 07:57:15 +08:00
|
|
|
Error = ASTContext::GE_Missing_setjmp;
|
2009-07-29 07:47:15 +08:00
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
break;
|
2011-11-14 05:51:09 +08:00
|
|
|
case 'K':
|
|
|
|
assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'K'!");
|
|
|
|
Type = Context.getucontext_tType();
|
|
|
|
|
|
|
|
if (Type.isNull()) {
|
|
|
|
Error = ASTContext::GE_Missing_ucontext;
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
break;
|
2012-11-27 10:58:24 +08:00
|
|
|
case 'p':
|
|
|
|
Type = Context.getProcessIDType();
|
|
|
|
break;
|
2009-07-28 10:25:19 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-10-02 06:42:38 +08:00
|
|
|
// If there are modifiers and if we're allowed to parse them, go for it.
|
|
|
|
Done = !AllowTypeModifiers;
|
2009-06-14 08:45:47 +08:00
|
|
|
while (!Done) {
|
2010-03-12 12:21:28 +08:00
|
|
|
switch (char c = *Str++) {
|
2010-10-02 06:42:38 +08:00
|
|
|
default: Done = true; --Str; break;
|
|
|
|
case '*':
|
|
|
|
case '&': {
|
|
|
|
// Both pointers and references can have their pointee types
|
|
|
|
// qualified with an address space.
|
|
|
|
char *End;
|
|
|
|
unsigned AddrSpace = strtoul(Str, &End, 10);
|
|
|
|
if (End != Str && AddrSpace != 0) {
|
|
|
|
Type = Context.getAddrSpaceQualType(Type, AddrSpace);
|
|
|
|
Str = End;
|
|
|
|
}
|
|
|
|
if (c == '*')
|
|
|
|
Type = Context.getPointerType(Type);
|
|
|
|
else
|
|
|
|
Type = Context.getLValueReferenceType(Type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// FIXME: There's no way to have a built-in with an rvalue ref arg.
|
|
|
|
case 'C':
|
|
|
|
Type = Type.withConst();
|
|
|
|
break;
|
|
|
|
case 'D':
|
|
|
|
Type = Context.getVolatileType(Type);
|
|
|
|
break;
|
2012-01-21 05:40:12 +08:00
|
|
|
case 'R':
|
|
|
|
Type = Type.withRestrict();
|
|
|
|
break;
|
2009-06-14 08:45:47 +08:00
|
|
|
}
|
|
|
|
}
|
2010-10-01 15:13:18 +08:00
|
|
|
|
2010-10-02 06:53:11 +08:00
|
|
|
assert((!RequiresICE || Type->isIntegralOrEnumerationType()) &&
|
2010-10-01 15:13:18 +08:00
|
|
|
"Integer constant 'I' type must be an integer");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-14 08:45:47 +08:00
|
|
|
return Type;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// GetBuiltinType - Return the type for the specified builtin.
|
2010-10-02 06:42:38 +08:00
|
|
|
QualType ASTContext::GetBuiltinType(unsigned Id,
|
2010-10-02 06:53:11 +08:00
|
|
|
GetBuiltinTypeError &Error,
|
2011-01-12 17:06:06 +08:00
|
|
|
unsigned *IntegerConstantArgs) const {
|
2010-10-02 06:42:38 +08:00
|
|
|
const char *TypeStr = BuiltinInfo.GetTypeString(Id);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<QualType, 8> ArgTypes;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-10-02 06:53:11 +08:00
|
|
|
bool RequiresICE = false;
|
2009-06-14 08:45:47 +08:00
|
|
|
Error = GE_None;
|
2010-10-02 06:53:11 +08:00
|
|
|
QualType ResType = DecodeTypeFromStr(TypeStr, *this, Error,
|
|
|
|
RequiresICE, true);
|
2009-06-14 08:45:47 +08:00
|
|
|
if (Error != GE_None)
|
|
|
|
return QualType();
|
2010-10-02 06:53:11 +08:00
|
|
|
|
|
|
|
assert(!RequiresICE && "Result of intrinsic cannot be required to be an ICE");
|
|
|
|
|
2009-06-14 08:45:47 +08:00
|
|
|
while (TypeStr[0] && TypeStr[0] != '.') {
|
2010-10-02 06:53:11 +08:00
|
|
|
QualType Ty = DecodeTypeFromStr(TypeStr, *this, Error, RequiresICE, true);
|
2009-06-14 08:45:47 +08:00
|
|
|
if (Error != GE_None)
|
|
|
|
return QualType();
|
|
|
|
|
2010-10-02 06:53:11 +08:00
|
|
|
// If this argument is required to be an IntegerConstantExpression and the
|
|
|
|
// caller cares, fill in the bitmask we return.
|
|
|
|
if (RequiresICE && IntegerConstantArgs)
|
|
|
|
*IntegerConstantArgs |= 1 << ArgTypes.size();
|
|
|
|
|
2009-06-14 08:45:47 +08:00
|
|
|
// Do array -> pointer decay. The builtin should use the decayed type.
|
|
|
|
if (Ty->isArrayType())
|
|
|
|
Ty = getArrayDecayedType(Ty);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-14 08:45:47 +08:00
|
|
|
ArgTypes.push_back(Ty);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert((TypeStr[0] != '.' || TypeStr[1] == 0) &&
|
|
|
|
"'.' should only occur at end of builtin type list!");
|
|
|
|
|
2010-12-21 08:44:39 +08:00
|
|
|
FunctionType::ExtInfo EI;
|
|
|
|
if (BuiltinInfo.isNoReturn(Id)) EI = EI.withNoReturn(true);
|
|
|
|
|
|
|
|
bool Variadic = (TypeStr[0] == '.');
|
|
|
|
|
|
|
|
// We really shouldn't be making a no-proto type here, especially in C++.
|
|
|
|
if (ArgTypes.empty() && Variadic)
|
|
|
|
return getFunctionNoProtoType(ResType, EI);
|
2010-02-22 06:15:06 +08:00
|
|
|
|
2010-12-14 16:05:40 +08:00
|
|
|
FunctionProtoType::ExtProtoInfo EPI;
|
2010-12-21 08:44:39 +08:00
|
|
|
EPI.ExtInfo = EI;
|
|
|
|
EPI.Variadic = Variadic;
|
2010-12-14 16:05:40 +08:00
|
|
|
|
|
|
|
return getFunctionType(ResType, ArgTypes.data(), ArgTypes.size(), EPI);
|
2009-06-14 08:45:47 +08:00
|
|
|
}
|
2009-08-19 15:44:53 +08:00
|
|
|
|
2010-07-30 02:15:58 +08:00
|
|
|
GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) {
|
|
|
|
GVALinkage External = GVA_StrongExternal;
|
|
|
|
|
|
|
|
Linkage L = FD->getLinkage();
|
|
|
|
switch (L) {
|
|
|
|
case NoLinkage:
|
|
|
|
case InternalLinkage:
|
|
|
|
case UniqueExternalLinkage:
|
|
|
|
return GVA_Internal;
|
|
|
|
|
|
|
|
case ExternalLinkage:
|
|
|
|
switch (FD->getTemplateSpecializationKind()) {
|
|
|
|
case TSK_Undeclared:
|
|
|
|
case TSK_ExplicitSpecialization:
|
|
|
|
External = GVA_StrongExternal;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TSK_ExplicitInstantiationDefinition:
|
|
|
|
return GVA_ExplicitTemplateInstantiation;
|
|
|
|
|
|
|
|
case TSK_ExplicitInstantiationDeclaration:
|
|
|
|
case TSK_ImplicitInstantiation:
|
|
|
|
External = GVA_TemplateInstantiation;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!FD->isInlined())
|
|
|
|
return External;
|
|
|
|
|
2012-03-11 15:00:24 +08:00
|
|
|
if (!getLangOpts().CPlusPlus || FD->hasAttr<GNUInlineAttr>()) {
|
2010-07-30 02:15:58 +08:00
|
|
|
// GNU or C99 inline semantics. Determine whether this symbol should be
|
|
|
|
// externally visible.
|
|
|
|
if (FD->isInlineDefinitionExternallyVisible())
|
|
|
|
return External;
|
|
|
|
|
|
|
|
// C99 inline semantics, where the symbol is not externally visible.
|
|
|
|
return GVA_C99Inline;
|
|
|
|
}
|
|
|
|
|
|
|
|
// C++0x [temp.explicit]p9:
|
|
|
|
// [ Note: The intent is that an inline function that is the subject of
|
|
|
|
// an explicit instantiation declaration will still be implicitly
|
|
|
|
// instantiated when used so that the body can be considered for
|
|
|
|
// inlining, but that no out-of-line copy of the inline function would be
|
|
|
|
// generated in the translation unit. -- end note ]
|
|
|
|
if (FD->getTemplateSpecializationKind()
|
|
|
|
== TSK_ExplicitInstantiationDeclaration)
|
|
|
|
return GVA_C99Inline;
|
|
|
|
|
|
|
|
return GVA_CXXInline;
|
|
|
|
}
|
|
|
|
|
|
|
|
GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
|
|
|
|
// If this is a static data member, compute the kind of template
|
|
|
|
// specialization. Otherwise, this variable is not part of a
|
|
|
|
// template.
|
|
|
|
TemplateSpecializationKind TSK = TSK_Undeclared;
|
|
|
|
if (VD->isStaticDataMember())
|
|
|
|
TSK = VD->getTemplateSpecializationKind();
|
|
|
|
|
|
|
|
Linkage L = VD->getLinkage();
|
2013-01-02 12:19:07 +08:00
|
|
|
assert (!(L == ExternalLinkage && getLangOpts().CPlusPlus &&
|
|
|
|
VD->getType()->getLinkage() == UniqueExternalLinkage));
|
2010-07-30 02:15:58 +08:00
|
|
|
|
|
|
|
switch (L) {
|
|
|
|
case NoLinkage:
|
|
|
|
case InternalLinkage:
|
|
|
|
case UniqueExternalLinkage:
|
|
|
|
return GVA_Internal;
|
|
|
|
|
|
|
|
case ExternalLinkage:
|
|
|
|
switch (TSK) {
|
|
|
|
case TSK_Undeclared:
|
|
|
|
case TSK_ExplicitSpecialization:
|
|
|
|
return GVA_StrongExternal;
|
|
|
|
|
|
|
|
case TSK_ExplicitInstantiationDeclaration:
|
|
|
|
llvm_unreachable("Variable should not be instantiated");
|
|
|
|
// Fall through to treat this like any other instantiation.
|
|
|
|
|
|
|
|
case TSK_ExplicitInstantiationDefinition:
|
|
|
|
return GVA_ExplicitTemplateInstantiation;
|
|
|
|
|
|
|
|
case TSK_ImplicitInstantiation:
|
|
|
|
return GVA_TemplateInstantiation;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-17 14:56:22 +08:00
|
|
|
llvm_unreachable("Invalid Linkage!");
|
2010-07-30 02:15:58 +08:00
|
|
|
}
|
|
|
|
|
2010-07-30 04:08:05 +08:00
|
|
|
bool ASTContext::DeclMustBeEmitted(const Decl *D) {
|
2010-07-30 02:15:58 +08:00
|
|
|
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
|
|
|
|
if (!VD->isFileVarDecl())
|
|
|
|
return false;
|
2011-09-14 05:35:00 +08:00
|
|
|
} else if (!isa<FunctionDecl>(D))
|
2010-07-30 02:15:58 +08:00
|
|
|
return false;
|
|
|
|
|
2010-07-30 04:07:52 +08:00
|
|
|
// Weak references don't produce any output by themselves.
|
|
|
|
if (D->hasAttr<WeakRefAttr>())
|
|
|
|
return false;
|
|
|
|
|
2010-07-30 02:15:58 +08:00
|
|
|
// Aliases and used decls are required.
|
|
|
|
if (D->hasAttr<AliasAttr>() || D->hasAttr<UsedAttr>())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
|
|
|
// Forward declarations aren't required.
|
2011-05-07 04:44:56 +08:00
|
|
|
if (!FD->doesThisDeclarationHaveABody())
|
2011-07-18 13:26:13 +08:00
|
|
|
return FD->doesDeclarationForceExternallyVisibleDefinition();
|
2010-07-30 02:15:58 +08:00
|
|
|
|
|
|
|
// Constructors and destructors are required.
|
|
|
|
if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
|
|
|
|
return true;
|
|
|
|
|
2013-01-26 06:31:03 +08:00
|
|
|
// The key function for a class is required. This rule only comes
|
|
|
|
// into play when inline functions can be key functions, though.
|
|
|
|
if (getTargetInfo().getCXXABI().canKeyFunctionBeInline()) {
|
|
|
|
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
|
|
|
|
const CXXRecordDecl *RD = MD->getParent();
|
|
|
|
if (MD->isOutOfLine() && RD->isDynamicClass()) {
|
|
|
|
const CXXMethodDecl *KeyFunc = getCurrentKeyFunction(RD);
|
|
|
|
if (KeyFunc && KeyFunc->getCanonicalDecl() == MD->getCanonicalDecl())
|
|
|
|
return true;
|
|
|
|
}
|
2010-07-30 02:15:58 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GVALinkage Linkage = GetGVALinkageForFunction(FD);
|
|
|
|
|
|
|
|
// static, static inline, always_inline, and extern inline functions can
|
|
|
|
// always be deferred. Normal inline functions can be deferred in C99/C++.
|
|
|
|
// Implicit template instantiations can also be deferred in C++.
|
|
|
|
if (Linkage == GVA_Internal || Linkage == GVA_C99Inline ||
|
2012-02-02 14:06:34 +08:00
|
|
|
Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation)
|
2010-07-30 02:15:58 +08:00
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
2011-09-10 08:22:34 +08:00
|
|
|
|
2010-07-30 02:15:58 +08:00
|
|
|
const VarDecl *VD = cast<VarDecl>(D);
|
|
|
|
assert(VD->isFileVarDecl() && "Expected file scoped var");
|
|
|
|
|
2010-07-30 04:07:52 +08:00
|
|
|
if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly)
|
|
|
|
return false;
|
|
|
|
|
2012-11-13 05:38:00 +08:00
|
|
|
// Variables that can be needed in other TUs are required.
|
2010-07-30 02:15:58 +08:00
|
|
|
GVALinkage L = GetGVALinkageForVariable(VD);
|
2012-11-13 05:38:00 +08:00
|
|
|
if (L != GVA_Internal && L != GVA_TemplateInstantiation)
|
|
|
|
return true;
|
2010-07-30 02:15:58 +08:00
|
|
|
|
2012-11-13 05:38:00 +08:00
|
|
|
// Variables that have destruction with side-effects are required.
|
|
|
|
if (VD->getType().isDestructedType())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Variables that have initialization with side-effects are required.
|
|
|
|
if (VD->getInit() && VD->getInit()->HasSideEffects(*this))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
2010-07-30 02:15:58 +08:00
|
|
|
}
|
2010-08-16 11:33:14 +08:00
|
|
|
|
2012-07-12 17:50:54 +08:00
|
|
|
CallingConv ASTContext::getDefaultCXXMethodCallConv(bool isVariadic) {
|
2010-11-10 02:04:24 +08:00
|
|
|
// Pass through to the C++ ABI object
|
2012-07-12 17:50:54 +08:00
|
|
|
return ABI->getDefaultMethodCallConv(isVariadic);
|
|
|
|
}
|
|
|
|
|
|
|
|
CallingConv ASTContext::getCanonicalCallConv(CallingConv CC) const {
|
2013-01-26 06:30:49 +08:00
|
|
|
if (CC == CC_C && !LangOpts.MRTD &&
|
|
|
|
getTargetInfo().getCXXABI().isMemberFunctionCCDefault())
|
2012-07-12 17:50:54 +08:00
|
|
|
return CC_Default;
|
|
|
|
return CC;
|
2010-11-10 02:04:24 +08:00
|
|
|
}
|
|
|
|
|
2011-01-12 17:06:06 +08:00
|
|
|
bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const {
|
2010-11-25 09:51:53 +08:00
|
|
|
// Pass through to the C++ ABI object
|
|
|
|
return ABI->isNearlyEmpty(RD);
|
|
|
|
}
|
|
|
|
|
2011-01-14 02:57:25 +08:00
|
|
|
MangleContext *ASTContext::createMangleContext() {
|
2013-01-26 06:30:49 +08:00
|
|
|
switch (Target->getCXXABI().getKind()) {
|
2013-01-31 20:13:10 +08:00
|
|
|
case TargetCXXABI::GenericAArch64:
|
2013-01-26 06:30:49 +08:00
|
|
|
case TargetCXXABI::GenericItanium:
|
|
|
|
case TargetCXXABI::GenericARM:
|
|
|
|
case TargetCXXABI::iOS:
|
2011-01-14 02:57:25 +08:00
|
|
|
return createItaniumMangleContext(*this, getDiagnostics());
|
2013-01-26 06:30:49 +08:00
|
|
|
case TargetCXXABI::Microsoft:
|
2011-01-14 02:57:25 +08:00
|
|
|
return createMicrosoftMangleContext(*this, getDiagnostics());
|
|
|
|
}
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("Unsupported ABI");
|
2011-01-14 02:57:25 +08:00
|
|
|
}
|
|
|
|
|
2010-08-16 11:33:14 +08:00
|
|
|
CXXABI::~CXXABI() {}
|
2011-04-28 12:53:38 +08:00
|
|
|
|
|
|
|
size_t ASTContext::getSideTableAllocatedMemory() const {
|
2011-07-28 02:41:12 +08:00
|
|
|
return ASTRecordLayouts.getMemorySize()
|
|
|
|
+ llvm::capacity_in_bytes(ObjCLayouts)
|
|
|
|
+ llvm::capacity_in_bytes(KeyFunctions)
|
|
|
|
+ llvm::capacity_in_bytes(ObjCImpls)
|
|
|
|
+ llvm::capacity_in_bytes(BlockVarCopyInits)
|
|
|
|
+ llvm::capacity_in_bytes(DeclAttrs)
|
|
|
|
+ llvm::capacity_in_bytes(InstantiatedFromStaticDataMember)
|
|
|
|
+ llvm::capacity_in_bytes(InstantiatedFromUsingDecl)
|
|
|
|
+ llvm::capacity_in_bytes(InstantiatedFromUsingShadowDecl)
|
|
|
|
+ llvm::capacity_in_bytes(InstantiatedFromUnnamedFieldDecl)
|
|
|
|
+ llvm::capacity_in_bytes(OverriddenMethods)
|
|
|
|
+ llvm::capacity_in_bytes(Types)
|
2011-08-14 11:52:19 +08:00
|
|
|
+ llvm::capacity_in_bytes(VariableArrayTypes)
|
2011-08-14 22:28:49 +08:00
|
|
|
+ llvm::capacity_in_bytes(ClassScopeSpecializationPattern);
|
2011-04-28 12:53:38 +08:00
|
|
|
}
|
2011-10-06 13:00:56 +08:00
|
|
|
|
2012-11-14 09:52:05 +08:00
|
|
|
void ASTContext::addUnnamedTag(const TagDecl *Tag) {
|
|
|
|
// FIXME: This mangling should be applied to function local classes too
|
|
|
|
if (!Tag->getName().empty() || Tag->getTypedefNameForAnonDecl() ||
|
|
|
|
!isa<CXXRecordDecl>(Tag->getParent()) || Tag->getLinkage() != ExternalLinkage)
|
|
|
|
return;
|
|
|
|
|
|
|
|
std::pair<llvm::DenseMap<const DeclContext *, unsigned>::iterator, bool> P =
|
|
|
|
UnnamedMangleContexts.insert(std::make_pair(Tag->getParent(), 0));
|
|
|
|
UnnamedMangleNumbers.insert(std::make_pair(Tag, P.first->second++));
|
|
|
|
}
|
|
|
|
|
|
|
|
int ASTContext::getUnnamedTagManglingNumber(const TagDecl *Tag) const {
|
|
|
|
llvm::DenseMap<const TagDecl *, unsigned>::const_iterator I =
|
|
|
|
UnnamedMangleNumbers.find(Tag);
|
|
|
|
return I != UnnamedMangleNumbers.end() ? I->second : -1;
|
|
|
|
}
|
|
|
|
|
2012-02-21 03:44:39 +08:00
|
|
|
unsigned ASTContext::getLambdaManglingNumber(CXXMethodDecl *CallOperator) {
|
|
|
|
CXXRecordDecl *Lambda = CallOperator->getParent();
|
|
|
|
return LambdaMangleContexts[Lambda->getDeclContext()]
|
|
|
|
.getManglingNumber(CallOperator);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-06 13:00:56 +08:00
|
|
|
void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) {
|
|
|
|
ParamIndices[D] = index;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned ASTContext::getParameterIndex(const ParmVarDecl *D) const {
|
|
|
|
ParameterIndexTable::const_iterator I = ParamIndices.find(D);
|
|
|
|
assert(I != ParamIndices.end() &&
|
|
|
|
"ParmIndices lacks entry set by ParmVarDecl");
|
|
|
|
return I->second;
|
|
|
|
}
|