summaryrefslogtreecommitdiffstats
path: root/lib/AST/ASTContext.cpp
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2010-03-21 10:50:08 +0000
committerrdivacky <rdivacky@FreeBSD.org>2010-03-21 10:50:08 +0000
commit1e255aab650a7fa2047fd953cae65b12215280af (patch)
tree508d4388db78f87d35bf26a0400b4b03bc4c1f13 /lib/AST/ASTContext.cpp
parent1033b7c1e32962948b01a25145829f17bc70a8de (diff)
downloadFreeBSD-src-1e255aab650a7fa2047fd953cae65b12215280af.zip
FreeBSD-src-1e255aab650a7fa2047fd953cae65b12215280af.tar.gz
Update clang to r99115.
Diffstat (limited to 'lib/AST/ASTContext.cpp')
-rw-r--r--lib/AST/ASTContext.cpp264
1 files changed, 60 insertions, 204 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 8230cde..7f5c9b1 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -43,8 +43,7 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
GlobalNestedNameSpecifier(0), CFConstantStringTypeDecl(0),
ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), jmp_bufDecl(0),
sigjmp_bufDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0),
- SourceMgr(SM), LangOpts(LOpts),
- LoadedExternalComments(false), FreeMemory(FreeMem), Target(t),
+ SourceMgr(SM), LangOpts(LOpts), FreeMemory(FreeMem), Target(t),
Idents(idents), Selectors(sels),
BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts) {
ObjCIdRedefinitionType = QualType();
@@ -413,201 +412,6 @@ namespace {
};
}
-/// \brief Determine whether the given comment is a Doxygen-style comment.
-///
-/// \param Start the start of the comment text.
-///
-/// \param End the end of the comment text.
-///
-/// \param Member whether we want to check whether this is a member comment
-/// (which requires a < after the Doxygen-comment delimiter). Otherwise,
-/// we only return true when we find a non-member comment.
-static bool
-isDoxygenComment(SourceManager &SourceMgr, SourceRange Comment,
- bool Member = false) {
- bool Invalid = false;
- const char *BufferStart
- = SourceMgr.getBufferData(SourceMgr.getFileID(Comment.getBegin()),
- &Invalid).data();
- if (Invalid)
- return false;
-
- const char *Start = BufferStart + SourceMgr.getFileOffset(Comment.getBegin());
- const char* End = BufferStart + SourceMgr.getFileOffset(Comment.getEnd());
-
- if (End - Start < 4)
- return false;
-
- assert(Start[0] == '/' && "Not a comment?");
- if (Start[1] == '*' && !(Start[2] == '!' || Start[2] == '*'))
- return false;
- if (Start[1] == '/' && !(Start[2] == '!' || Start[2] == '/'))
- return false;
-
- return (Start[3] == '<') == Member;
-}
-
-/// \brief Retrieve the comment associated with the given declaration, if
-/// it has one.
-const char *ASTContext::getCommentForDecl(const Decl *D) {
- if (!D)
- return 0;
-
- // Check whether we have cached a comment string for this declaration
- // already.
- llvm::DenseMap<const Decl *, std::string>::iterator Pos
- = DeclComments.find(D);
- if (Pos != DeclComments.end())
- return Pos->second.c_str();
-
- // If we have an external AST source and have not yet loaded comments from
- // that source, do so now.
- if (ExternalSource && !LoadedExternalComments) {
- std::vector<SourceRange> LoadedComments;
- ExternalSource->ReadComments(LoadedComments);
-
- if (!LoadedComments.empty())
- Comments.insert(Comments.begin(), LoadedComments.begin(),
- LoadedComments.end());
-
- LoadedExternalComments = true;
- }
-
- // If there are no comments anywhere, we won't find anything.
- if (Comments.empty())
- return 0;
-
- // If the declaration doesn't map directly to a location in a file, we
- // can't find the comment.
- SourceLocation DeclStartLoc = D->getLocStart();
- if (DeclStartLoc.isInvalid() || !DeclStartLoc.isFileID())
- return 0;
-
- // Find the comment that occurs just before this declaration.
- std::vector<SourceRange>::iterator LastComment
- = std::lower_bound(Comments.begin(), Comments.end(),
- SourceRange(DeclStartLoc),
- BeforeInTranslationUnit(&SourceMgr));
-
- // Decompose the location for the start of the declaration and find the
- // beginning of the file buffer.
- std::pair<FileID, unsigned> DeclStartDecomp
- = SourceMgr.getDecomposedLoc(DeclStartLoc);
- bool Invalid = false;
- const char *FileBufferStart
- = SourceMgr.getBufferData(DeclStartDecomp.first, &Invalid).data();
- if (Invalid)
- return 0;
-
- // First check whether we have a comment for a member.
- if (LastComment != Comments.end() &&
- !isa<TagDecl>(D) && !isa<NamespaceDecl>(D) &&
- isDoxygenComment(SourceMgr, *LastComment, true)) {
- std::pair<FileID, unsigned> LastCommentEndDecomp
- = SourceMgr.getDecomposedLoc(LastComment->getEnd());
- if (DeclStartDecomp.first == LastCommentEndDecomp.first &&
- SourceMgr.getLineNumber(DeclStartDecomp.first, DeclStartDecomp.second)
- == SourceMgr.getLineNumber(LastCommentEndDecomp.first,
- LastCommentEndDecomp.second)) {
- // The Doxygen member comment comes after the declaration starts and
- // is on the same line and in the same file as the declaration. This
- // is the comment we want.
- std::string &Result = DeclComments[D];
- Result.append(FileBufferStart +
- SourceMgr.getFileOffset(LastComment->getBegin()),
- FileBufferStart + LastCommentEndDecomp.second + 1);
- return Result.c_str();
- }
- }
-
- if (LastComment == Comments.begin())
- return 0;
- --LastComment;
-
- // Decompose the end of the comment.
- std::pair<FileID, unsigned> LastCommentEndDecomp
- = SourceMgr.getDecomposedLoc(LastComment->getEnd());
-
- // If the comment and the declaration aren't in the same file, then they
- // aren't related.
- if (DeclStartDecomp.first != LastCommentEndDecomp.first)
- return 0;
-
- // Check that we actually have a Doxygen comment.
- if (!isDoxygenComment(SourceMgr, *LastComment))
- return 0;
-
- // Compute the starting line for the declaration and for the end of the
- // comment (this is expensive).
- unsigned DeclStartLine
- = SourceMgr.getLineNumber(DeclStartDecomp.first, DeclStartDecomp.second);
- unsigned CommentEndLine
- = SourceMgr.getLineNumber(LastCommentEndDecomp.first,
- LastCommentEndDecomp.second);
-
- // If the comment does not end on the line prior to the declaration, then
- // the comment is not associated with the declaration at all.
- if (CommentEndLine + 1 != DeclStartLine)
- return 0;
-
- // We have a comment, but there may be more comments on the previous lines.
- // Keep looking so long as the comments are still Doxygen comments and are
- // still adjacent.
- unsigned ExpectedLine
- = SourceMgr.getSpellingLineNumber(LastComment->getBegin()) - 1;
- std::vector<SourceRange>::iterator FirstComment = LastComment;
- while (FirstComment != Comments.begin()) {
- // Look at the previous comment
- --FirstComment;
- std::pair<FileID, unsigned> Decomp
- = SourceMgr.getDecomposedLoc(FirstComment->getEnd());
-
- // If this previous comment is in a different file, we're done.
- if (Decomp.first != DeclStartDecomp.first) {
- ++FirstComment;
- break;
- }
-
- // If this comment is not a Doxygen comment, we're done.
- if (!isDoxygenComment(SourceMgr, *FirstComment)) {
- ++FirstComment;
- break;
- }
-
- // If the line number is not what we expected, we're done.
- unsigned Line = SourceMgr.getLineNumber(Decomp.first, Decomp.second);
- if (Line != ExpectedLine) {
- ++FirstComment;
- break;
- }
-
- // Set the next expected line number.
- ExpectedLine
- = SourceMgr.getSpellingLineNumber(FirstComment->getBegin()) - 1;
- }
-
- // The iterator range [FirstComment, LastComment] contains all of the
- // BCPL comments that, together, are associated with this declaration.
- // Form a single comment block string for this declaration that concatenates
- // all of these comments.
- std::string &Result = DeclComments[D];
- while (FirstComment != LastComment) {
- std::pair<FileID, unsigned> DecompStart
- = SourceMgr.getDecomposedLoc(FirstComment->getBegin());
- std::pair<FileID, unsigned> DecompEnd
- = SourceMgr.getDecomposedLoc(FirstComment->getEnd());
- Result.append(FileBufferStart + DecompStart.second,
- FileBufferStart + DecompEnd.second + 1);
- ++FirstComment;
- }
-
- // Append the last comment line.
- Result.append(FileBufferStart +
- SourceMgr.getFileOffset(LastComment->getBegin()),
- FileBufferStart + LastCommentEndDecomp.second + 1);
- return Result.c_str();
-}
-
//===----------------------------------------------------------------------===//
// Type Sizing and Analysis
//===----------------------------------------------------------------------===//
@@ -4315,6 +4119,41 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
return false;
}
+/// canAssignObjCInterfacesInBlockPointer - This routine is specifically written
+/// for providing type-safty for objective-c pointers used to pass/return
+/// 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,
+ const ObjCObjectPointerType *RHSOPT) {
+ if (RHSOPT->isObjCBuiltinType())
+ return true;
+
+ if (LHSOPT->isObjCBuiltinType()) {
+ return RHSOPT->isObjCBuiltinType() || RHSOPT->isObjCQualifiedIdType();
+ }
+
+ if (LHSOPT->isObjCQualifiedIdType() || RHSOPT->isObjCQualifiedIdType())
+ 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()))
+ return false;
+ if (RHS->getDecl()->isSuperClassOf(LHS->getDecl()))
+ return true;
+ }
+ else
+ return true;
+ }
+ return false;
+}
+
/// 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
@@ -4451,7 +4290,12 @@ bool ASTContext::typesAreCompatible(QualType LHS, QualType RHS) {
return !mergeTypes(LHS, RHS).isNull();
}
-QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs) {
+bool ASTContext::typesAreBlockPointerCompatible(QualType LHS, QualType RHS) {
+ return !mergeTypes(LHS, RHS, true).isNull();
+}
+
+QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
+ bool OfBlockPointer) {
const FunctionType *lbase = lhs->getAs<FunctionType>();
const FunctionType *rbase = rhs->getAs<FunctionType>();
const FunctionProtoType *lproto = dyn_cast<FunctionProtoType>(lbase);
@@ -4460,7 +4304,11 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs) {
bool allRTypes = true;
// Check return type
- QualType retType = mergeTypes(lbase->getResultType(), rbase->getResultType());
+ QualType retType;
+ if (OfBlockPointer)
+ retType = mergeTypes(rbase->getResultType(), lbase->getResultType(), true);
+ else
+ retType = mergeTypes(lbase->getResultType(), rbase->getResultType());
if (retType.isNull()) return QualType();
if (getCanonicalType(retType) != getCanonicalType(lbase->getResultType()))
allLTypes = false;
@@ -4500,7 +4348,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs) {
for (unsigned i = 0; i < lproto_nargs; i++) {
QualType largtype = lproto->getArgType(i).getUnqualifiedType();
QualType rargtype = rproto->getArgType(i).getUnqualifiedType();
- QualType argtype = mergeTypes(largtype, rargtype);
+ QualType argtype = mergeTypes(largtype, rargtype, OfBlockPointer);
if (argtype.isNull()) return QualType();
types.push_back(argtype);
if (getCanonicalType(argtype) != getCanonicalType(largtype))
@@ -4554,7 +4402,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs) {
return getFunctionNoProtoType(retType, NoReturn, lcc);
}
-QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
+QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
+ bool OfBlockPointer) {
// 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
@@ -4681,7 +4530,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
// Merge two block pointer types, while trying to preserve typedef info
QualType LHSPointee = LHS->getAs<BlockPointerType>()->getPointeeType();
QualType RHSPointee = RHS->getAs<BlockPointerType>()->getPointeeType();
- QualType ResultType = mergeTypes(LHSPointee, RHSPointee);
+ QualType ResultType = mergeTypes(LHSPointee, RHSPointee, OfBlockPointer);
if (ResultType.isNull()) return QualType();
if (getCanonicalType(LHSPointee) == getCanonicalType(ResultType))
return LHS;
@@ -4732,7 +4581,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
ArrayType::ArraySizeModifier(), 0);
}
case Type::FunctionNoProto:
- return mergeFunctionTypes(LHS, RHS);
+ return mergeFunctionTypes(LHS, RHS, OfBlockPointer);
case Type::Record:
case Type::Enum:
return QualType();
@@ -4761,12 +4610,19 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
return QualType();
}
case Type::ObjCObjectPointer: {
+ if (OfBlockPointer) {
+ if (canAssignObjCInterfacesInBlockPointer(
+ LHS->getAs<ObjCObjectPointerType>(),
+ RHS->getAs<ObjCObjectPointerType>()))
+ return LHS;
+ return QualType();
+ }
if (canAssignObjCInterfaces(LHS->getAs<ObjCObjectPointerType>(),
RHS->getAs<ObjCObjectPointerType>()))
return LHS;
return QualType();
- }
+ }
}
return QualType();
OpenPOWER on IntegriCloud