diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-03-21 10:50:08 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-03-21 10:50:08 +0000 |
commit | 1e255aab650a7fa2047fd953cae65b12215280af (patch) | |
tree | 508d4388db78f87d35bf26a0400b4b03bc4c1f13 /lib/AST/ASTContext.cpp | |
parent | 1033b7c1e32962948b01a25145829f17bc70a8de (diff) | |
download | FreeBSD-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.cpp | 264 |
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(); |