/* * Copyright 2010-2012, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "slang_rs_export_var.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Type.h" #include "llvm/ADT/APSInt.h" #include "slang_rs_context.h" #include "slang_rs_export_type.h" namespace slang { namespace { static clang::DiagnosticBuilder ReportVarError(RSContext *Context, const clang::SourceLocation Loc, const char *Message) { clang::DiagnosticsEngine *DiagEngine = Context->getDiagnostics(); const clang::SourceManager *SM = Context->getSourceManager(); return DiagEngine->Report(clang::FullSourceLoc(Loc, *SM), DiagEngine->getCustomDiagID(clang::DiagnosticsEngine::Error, Message)); } } // namespace RSExportVar::RSExportVar(RSContext *Context, const clang::VarDecl *VD, const RSExportType *ET) : RSExportable(Context, RSExportable::EX_VAR), mName(VD->getName().data(), VD->getName().size()), mET(ET), mIsConst(false), mIsUnsigned(false), mArraySize(0), mNumInits(0) { // mInit - Evaluate initializer expression const clang::Expr *Initializer = VD->getAnyInitializer(); if (Initializer != NULL) { switch (ET->getClass()) { case RSExportType::ExportClassPrimitive: case RSExportType::ExportClassVector: { Initializer->EvaluateAsRValue(mInit, Context->getASTContext()); break; } case RSExportType::ExportClassPointer: { if (Initializer->isNullPointerConstant(Context->getASTContext(), clang::Expr::NPC_ValueDependentIsNotNull)) { mInit.Val = clang::APValue(llvm::APSInt(1)); } else { if (!Initializer->EvaluateAsRValue(mInit, Context->getASTContext())) { ReportVarError(Context, Initializer->getExprLoc(), "initializer is not an R-value"); } } break; } case RSExportType::ExportClassConstantArray: { const clang::InitListExpr *IList = static_cast<const clang::InitListExpr*>(Initializer); if (!IList) { ReportVarError(Context, VD->getLocation(), "Unable to find initializer list"); break; } const RSExportConstantArrayType *ECAT = static_cast<const RSExportConstantArrayType*>(ET); mArraySize = ECAT->getSize(); mNumInits = IList->getNumInits(); for (unsigned int i = 0; i < mNumInits; i++) { clang::Expr::EvalResult tempInit; if (!IList->getInit(i)->EvaluateAsRValue(tempInit, Context->getASTContext())) { ReportVarError(Context, IList->getInit(i)->getExprLoc(), "initializer is not an R-value"); } mInitArray.push_back(tempInit); } break; } case RSExportType::ExportClassMatrix: case RSExportType::ExportClassRecord: { ReportVarError(Context, VD->getLocation(), "Reflection of initializer to variable '%0' (of type " "'%1') is unsupported currently.") << mName << ET->getName(); break; } default: { slangAssert(false && "Unknown class of type"); } } } clang::QualType QT = VD->getTypeSourceInfo()->getType(); if (!QT.isNull()) { mIsConst = QT.isConstQualified(); mIsUnsigned = QT->hasUnsignedIntegerRepresentation(); if (QT == Context->getASTContext().BoolTy) { mIsUnsigned = false; } } return; } } // namespace slang